mirror of https://github.com/nucypher/nucypher.git
Merge pull request #1764 from vzotova/se-pre-allocation
StakingEscrow pre-allocationspull/1821/head
commit
e0233dc8ac
|
@ -693,8 +693,8 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
|
||||
# TODO: Consider looking for absence of Initialized event - see #1193
|
||||
# This mimics initialization pre-condition in Issuer (StakingEscrow's base contract)
|
||||
current_supply_1 = deployed_contract.functions.currentSupply1().call()
|
||||
return current_supply_1 == 0
|
||||
current_minting_period = deployed_contract.functions.currentMintingPeriod().call()
|
||||
return current_minting_period == 0
|
||||
|
||||
@property
|
||||
def is_active(self) -> bool:
|
||||
|
@ -705,8 +705,8 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
|
||||
# TODO: Consider looking for Initialized event - see #1193
|
||||
# This mimics isInitialized() modifier in Issuer (StakingEscrow's base contract)
|
||||
current_supply_1 = deployed_contract.functions.currentSupply1().call()
|
||||
return current_supply_1 != 0
|
||||
current_minting_period = deployed_contract.functions.currentMintingPeriod().call()
|
||||
return current_minting_period != 0
|
||||
|
||||
|
||||
class PolicyManagerDeployer(BaseContractDeployer, UpgradeableContractMixin, OwnableContractMixin):
|
||||
|
|
|
@ -11,7 +11,7 @@ import "zeppelin/token/ERC20/SafeERC20.sol";
|
|||
|
||||
/**
|
||||
* @notice Contract for calculate issued tokens
|
||||
* @dev |v1.1.3|
|
||||
* @dev |v1.1.4|
|
||||
*/
|
||||
contract Issuer is Upgradeable {
|
||||
using SafeERC20 for NuCypherToken;
|
||||
|
@ -86,7 +86,7 @@ contract Issuer is Upgradeable {
|
|||
*/
|
||||
modifier isInitialized()
|
||||
{
|
||||
require(currentSupply1 != 0);
|
||||
require(currentMintingPeriod != 0);
|
||||
_;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ contract Issuer is Upgradeable {
|
|||
* @notice Initialize reserved tokens for reward
|
||||
*/
|
||||
function initialize(uint256 _reservedReward) external onlyOwner {
|
||||
require(currentSupply1 == 0);
|
||||
require(currentMintingPeriod == 0);
|
||||
token.safeTransferFrom(msg.sender, address(this), _reservedReward);
|
||||
currentMintingPeriod = getCurrentPeriod();
|
||||
uint256 currentTotalSupply = totalSupply - _reservedReward;
|
||||
|
@ -168,15 +168,15 @@ contract Issuer is Upgradeable {
|
|||
* @param _amount Amount of tokens
|
||||
*/
|
||||
function unMint(uint256 _amount) internal {
|
||||
currentSupply1 = currentSupply1 - _amount;
|
||||
currentSupply2 = currentSupply2 - _amount;
|
||||
currentSupply1 -= _amount;
|
||||
currentSupply2 -= _amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Burn sender's tokens. Amount of tokens will be returned for future minting
|
||||
* @param _value Amount to burn
|
||||
*/
|
||||
function burn(uint256 _value) external {
|
||||
function burn(uint256 _value) external isInitialized {
|
||||
token.safeTransferFrom(msg.sender, address(this), _value);
|
||||
unMint(_value);
|
||||
emit Burnt(msg.sender, _value);
|
||||
|
|
|
@ -34,7 +34,7 @@ contract WorkLockInterface {
|
|||
/**
|
||||
* @notice Contract holds and locks stakers tokens.
|
||||
* Each staker that locks their tokens will receive some compensation
|
||||
* @dev |v2.2.3|
|
||||
* @dev |v2.3.1|
|
||||
*/
|
||||
contract StakingEscrow is Issuer {
|
||||
using AdditionalMath for uint256;
|
||||
|
@ -479,7 +479,7 @@ contract StakingEscrow is Issuer {
|
|||
* Only if this parameter is not locked
|
||||
* @param _reStake Value for parameter
|
||||
*/
|
||||
function setReStake(bool _reStake) external isInitialized {
|
||||
function setReStake(bool _reStake) external {
|
||||
require(!isReStakeLocked(msg.sender));
|
||||
StakerInfo storage info = stakerInfo[msg.sender];
|
||||
if (info.reStakeDisabled == !_reStake) {
|
||||
|
@ -493,7 +493,7 @@ contract StakingEscrow is Issuer {
|
|||
* @notice Lock `reStake` parameter. Only if this parameter is not locked
|
||||
* @param _lockReStakeUntilPeriod Can't change `reStake` value until this period
|
||||
*/
|
||||
function lockReStake(uint16 _lockReStakeUntilPeriod) external isInitialized {
|
||||
function lockReStake(uint16 _lockReStakeUntilPeriod) external {
|
||||
require(!isReStakeLocked(msg.sender) &&
|
||||
_lockReStakeUntilPeriod > getCurrentPeriod());
|
||||
stakerInfo[msg.sender].lockReStakeUntilPeriod = _lockReStakeUntilPeriod;
|
||||
|
@ -542,6 +542,59 @@ contract StakingEscrow is Issuer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Batch deposit. Allowed only initial deposit for each staker
|
||||
* @param _stakers Stakers
|
||||
* @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
|
||||
*/
|
||||
function batchDeposit(
|
||||
address[] calldata _stakers,
|
||||
uint256[] calldata _numberOfSubStakes,
|
||||
uint256[] calldata _values,
|
||||
uint16[] calldata _periods
|
||||
)
|
||||
external
|
||||
{
|
||||
uint256 subStakesLength = _values.length;
|
||||
require(_stakers.length != 0 &&
|
||||
_stakers.length == _numberOfSubStakes.length &&
|
||||
subStakesLength >= _stakers.length &&
|
||||
_periods.length == subStakesLength);
|
||||
uint16 previousPeriod = getCurrentPeriod() - 1;
|
||||
uint16 nextPeriod = previousPeriod + 2;
|
||||
uint256 sumValue = 0;
|
||||
|
||||
uint256 j = 0;
|
||||
for (uint256 i = 0; i < _stakers.length; i++) {
|
||||
address staker = _stakers[i];
|
||||
uint256 numberOfSubStakes = _numberOfSubStakes[i];
|
||||
uint256 endIndex = j + numberOfSubStakes;
|
||||
require(numberOfSubStakes > 0 && subStakesLength >= endIndex);
|
||||
StakerInfo storage info = stakerInfo[staker];
|
||||
require(info.subStakes.length == 0);
|
||||
require(workerToStaker[staker] == address(0), "A staker can't be a worker for another staker");
|
||||
stakers.push(staker);
|
||||
policyManager.register(staker, previousPeriod);
|
||||
|
||||
for (; j < endIndex; j++) {
|
||||
uint256 value = _values[j];
|
||||
uint16 periods = _periods[j];
|
||||
require(value >= minAllowableLockedTokens && periods >= minLockedPeriods);
|
||||
info.value = info.value.add(value);
|
||||
info.subStakes.push(SubStakeInfo(nextPeriod, 0, periods, value));
|
||||
sumValue = sumValue.add(value);
|
||||
emit Deposited(staker, value, periods);
|
||||
emit Locked(staker, value, nextPeriod, periods);
|
||||
}
|
||||
require(info.value <= maxAllowableLockedTokens);
|
||||
}
|
||||
require(j == subStakesLength);
|
||||
|
||||
token.safeTransferFrom(msg.sender, address(this), sumValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Implementation of the receiveApproval(address,uint256,address,bytes) method
|
||||
* (see NuCypherToken contract). Deposit all tokens that were approved to transfer
|
||||
|
@ -608,7 +661,7 @@ contract StakingEscrow is Issuer {
|
|||
* @param _value Amount of tokens to deposit
|
||||
* @param _periods Amount of periods during which tokens will be locked
|
||||
*/
|
||||
function deposit(address _staker, address _payer, uint256 _value, uint16 _periods) internal isInitialized {
|
||||
function deposit(address _staker, address _payer, uint256 _value, uint16 _periods) internal {
|
||||
require(_value != 0);
|
||||
StakerInfo storage info = stakerInfo[_staker];
|
||||
require(workerToStaker[_staker] == address(0) || workerToStaker[_staker] == info.worker,
|
||||
|
@ -773,7 +826,7 @@ contract StakingEscrow is Issuer {
|
|||
/**
|
||||
* @notice Confirm activity for the next period and mine for the previous period
|
||||
*/
|
||||
function confirmActivity() external {
|
||||
function confirmActivity() external isInitialized {
|
||||
address staker = getStakerFromWorker(msg.sender);
|
||||
StakerInfo storage info = stakerInfo[staker];
|
||||
require(info.value > 0, "Staker must have a stake to confirm activity");
|
||||
|
@ -958,7 +1011,7 @@ contract StakingEscrow is Issuer {
|
|||
address _investigator,
|
||||
uint256 _reward
|
||||
)
|
||||
public
|
||||
public isInitialized
|
||||
{
|
||||
require(msg.sender == address(adjudicator));
|
||||
require(_penalty > 0);
|
||||
|
|
|
@ -78,6 +78,11 @@ def test_issuer(testerchain, token, deploy_contract):
|
|||
tx = token.functions.approve(issuer.address, economics.erc20_reward_supply).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Can't burn tokens before initialization
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = issuer.functions.burn(1).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Only owner can initialize
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = issuer.functions.initialize(0).transact({'from': ursula})
|
||||
|
|
|
@ -303,20 +303,33 @@ def test_all(testerchain,
|
|||
tx = token.functions.approve(escrow.address, 10000).transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Staker can't deposit tokens before Escrow initialization
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.deposit(1, 1).transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
# Check that nothing is locked
|
||||
assert 0 == escrow.functions.getLockedTokens(staker1, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(staker2, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(staker3, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(staker4, 0).call()
|
||||
|
||||
# Initialize escrow
|
||||
tx = token.functions.transfer(multisig.address, token_economics.erc20_reward_supply).transact({'from': creator})
|
||||
# Deposit tokens for 1 staker
|
||||
staker1_tokens = token_economics.minimum_allowed_locked
|
||||
duration = token_economics.minimum_locked_periods
|
||||
tx = token.functions.approve(escrow.address, 2 * staker1_tokens).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = escrow.functions.batchDeposit([staker1], [1], [staker1_tokens], [duration]).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
escrow_supply = token_economics.minimum_allowed_locked
|
||||
assert token.functions.balanceOf(escrow.address).call() == escrow_supply
|
||||
assert escrow.functions.getAllTokens(staker1).call() == staker1_tokens
|
||||
assert escrow.functions.getLockedTokens(staker1, 0).call() == 0
|
||||
assert escrow.functions.getLockedTokens(staker1, 1).call() == staker1_tokens
|
||||
assert escrow.functions.getLockedTokens(staker1, duration).call() == staker1_tokens
|
||||
assert escrow.functions.getLockedTokens(staker1, duration + 1).call() == 0
|
||||
|
||||
# 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)
|
||||
tx = token.functions.approve(escrow.address, 0).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = token.functions.approve(escrow.address, token_economics.erc20_reward_supply)\
|
||||
.buildTransaction({'from': multisig.address, 'gasPrice': 0})
|
||||
execute_multisig_transaction(testerchain, multisig, [contracts_owners[0], contracts_owners[1]], tx)
|
||||
tx = escrow.functions.initialize(token_economics.erc20_reward_supply)\
|
||||
.buildTransaction({'from': multisig.address, 'gasPrice': 0})
|
||||
execute_multisig_transaction(testerchain, multisig, [contracts_owners[0], contracts_owners[1]], tx)
|
||||
|
||||
# Initialize worklock
|
||||
worklock_supply = 3 * token_economics.minimum_allowed_locked + token_economics.maximum_allowed_locked
|
||||
|
@ -453,7 +466,7 @@ def test_all(testerchain,
|
|||
assert token.functions.balanceOf(worklock.address).call() == worklock_supply - staker2_tokens
|
||||
tx = escrow.functions.setWorker(staker2).transact({'from': staker2})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
escrow_supply = token_economics.erc20_reward_supply + staker2_tokens
|
||||
escrow_supply += staker2_tokens
|
||||
assert escrow.functions.getAllTokens(staker2).call() == staker2_tokens
|
||||
assert escrow.functions.getCompletedWork(staker2).call() == 0
|
||||
tx = escrow.functions.setWindDown(True).transact({'from': staker2})
|
||||
|
@ -463,9 +476,10 @@ def test_all(testerchain,
|
|||
tx = worklock.functions.claim().transact({'from': staker1, 'gas_price': 0})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert worklock.functions.workInfo(staker1).call()[2]
|
||||
staker1_tokens = worklock.functions.ethToTokens(2 * deposited_eth_2).call()
|
||||
staker1_claims = worklock.functions.ethToTokens(2 * deposited_eth_2).call()
|
||||
staker1_tokens += staker1_claims
|
||||
assert escrow.functions.getLockedTokens(staker1, 1).call() == staker1_tokens
|
||||
escrow_supply += staker1_tokens
|
||||
escrow_supply += staker1_claims
|
||||
|
||||
# Staker prolongs lock duration
|
||||
tx = escrow.functions.prolongStake(0, 3).transact({'from': staker2, 'gas_price': 0})
|
||||
|
@ -544,10 +558,6 @@ def test_all(testerchain,
|
|||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Check that nothing is locked
|
||||
assert 0 == escrow.functions.getLockedTokens(staker1, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(staker2, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(staker3, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(staker4, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(preallocation_escrow_1.address, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(preallocation_escrow_2.address, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(contracts_owners[0], 0).call()
|
||||
|
@ -562,6 +572,28 @@ def test_all(testerchain,
|
|||
tx = escrow.functions.deposit(2001, 1).transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Can't confirm activity before initialization
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.confirmActivity().transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.confirmActivity().transact({'from': staker2})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.confirmActivity().transact({'from': staker3})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Initialize escrow
|
||||
tx = token.functions.transfer(multisig.address, token_economics.erc20_reward_supply).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = token.functions.approve(escrow.address, token_economics.erc20_reward_supply) \
|
||||
.buildTransaction({'from': multisig.address, 'gasPrice': 0})
|
||||
execute_multisig_transaction(testerchain, multisig, [contracts_owners[0], contracts_owners[1]], tx)
|
||||
tx = escrow.functions.initialize(token_economics.erc20_reward_supply) \
|
||||
.buildTransaction({'from': multisig.address, 'gasPrice': 0})
|
||||
execute_multisig_transaction(testerchain, multisig, [contracts_owners[0], contracts_owners[1]], tx)
|
||||
escrow_supply += token_economics.erc20_reward_supply
|
||||
|
||||
# Grant access to transfer tokens
|
||||
tx = token.functions.approve(escrow.address, 10000).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
@ -579,12 +611,11 @@ def test_all(testerchain,
|
|||
tx = escrow.functions.confirmActivity().transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
escrow_supply += 1000
|
||||
first_sub_stake = staker1_tokens
|
||||
second_sub_stake = 1000
|
||||
staker1_tokens += second_sub_stake
|
||||
assert token.functions.balanceOf(escrow.address).call() == escrow_supply
|
||||
assert token.functions.balanceOf(staker1).call() == 9000
|
||||
assert escrow.functions.getLockedTokens(staker1, 0).call() == 0
|
||||
assert escrow.functions.getLockedTokens(staker1, 0).call() == token_economics.minimum_allowed_locked
|
||||
assert escrow.functions.getLockedTokens(staker1, 1).call() == staker1_tokens
|
||||
assert escrow.functions.getLockedTokens(staker1, token_economics.minimum_locked_periods).call() == staker1_tokens
|
||||
assert escrow.functions.getLockedTokens(staker1, token_economics.minimum_locked_periods + 1).call() == second_sub_stake
|
||||
|
@ -638,7 +669,7 @@ def test_all(testerchain,
|
|||
# Divide stakes
|
||||
tx = escrow.functions.divideStake(0, 500, 6).transact({'from': staker2})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = escrow.functions.divideStake(1, 500, 9).transact({'from': staker1})
|
||||
tx = escrow.functions.divideStake(2, 500, 9).transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = preallocation_escrow_interface_1.functions.divideStake(0, 500, 6).transact({'from': staker3})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
|
|
@ -19,6 +19,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
import pytest
|
||||
from eth_tester.exceptions import TransactionFailed
|
||||
from eth_utils import to_checksum_address
|
||||
from web3.contract import Contract
|
||||
|
||||
MAX_SUB_STAKES = 30
|
||||
MAX_UINT16 = 65535
|
||||
|
@ -73,15 +74,6 @@ def test_staking(testerchain, token, escrow_contract):
|
|||
assert 0 == escrow.functions.getLockedTokens(staker2, 0).call()
|
||||
assert 0 == escrow.functions.getLockedTokens(testerchain.client.accounts[3], 0).call()
|
||||
|
||||
# Staker can't deposit tokens before Escrow initialization
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.deposit(500, 2).transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Initialize Escrow contract
|
||||
tx = escrow.functions.initialize(0).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Can't deposit for too short a period (less than _minLockedPeriods coefficient)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.deposit(1000, 1).transact({'from': staker1})
|
||||
|
@ -91,7 +83,7 @@ def test_staking(testerchain, token, escrow_contract):
|
|||
.transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Staker transfers some tokens to the escrow and lock them
|
||||
# Staker transfers some tokens to the escrow and locks them before initialization
|
||||
current_period = escrow.functions.getCurrentPeriod().call()
|
||||
tx = escrow.functions.deposit(1000, 2).transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
@ -126,7 +118,16 @@ def test_staking(testerchain, token, escrow_contract):
|
|||
assert staker1 == event_args['staker']
|
||||
assert event_args['windDown']
|
||||
|
||||
# Staker(2) stakes tokens also
|
||||
# Can't confirm activity before initialization
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.confirmActivity().transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Initialize Escrow contract
|
||||
tx = escrow.functions.initialize(0).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Ursula(2) stakes tokens also
|
||||
tx = escrow.functions.deposit(500, 2).transact({'from': staker2})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = escrow.functions.setWorker(staker2).transact({'from': staker2})
|
||||
|
@ -712,3 +713,283 @@ def test_allowable_locked_tokens(testerchain, token_economics, token, escrow_con
|
|||
staker1_lock += minimum_allowed
|
||||
tx = escrow.functions.lock(maximum_allowed - staker1_lock, duration).transact({'from': staker1})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
|
||||
escrow = escrow_contract(1500)
|
||||
policy_manager_interface = testerchain.get_contract_factory('PolicyManagerForStakingEscrowMock')
|
||||
policy_manager = testerchain.client.get_contract(
|
||||
abi=policy_manager_interface.abi,
|
||||
address=escrow.functions.policyManager().call(),
|
||||
ContractFactoryClass=Contract)
|
||||
|
||||
creator = testerchain.client.accounts[0]
|
||||
deposit_log = escrow.events.Deposited.createFilter(fromBlock='latest')
|
||||
lock_log = escrow.events.Locked.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
|
||||
staker = testerchain.client.accounts[1]
|
||||
tx = escrow.functions.batchDeposit([staker], [1], [1000], [10]).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
escrow_balance = 1000
|
||||
assert token.functions.balanceOf(escrow.address).call() == escrow_balance
|
||||
assert escrow.functions.getAllTokens(staker).call() == 1000
|
||||
assert escrow.functions.getLockedTokens(staker, 0).call() == 0
|
||||
assert escrow.functions.getLockedTokens(staker, 1).call() == 1000
|
||||
assert escrow.functions.getLockedTokens(staker, 10).call() == 1000
|
||||
assert escrow.functions.getLockedTokens(staker, 11).call() == 0
|
||||
current_period = escrow.functions.getCurrentPeriod().call()
|
||||
assert policy_manager.functions.getPeriodsLength(staker).call() == 1
|
||||
assert policy_manager.functions.getPeriod(staker, 0).call() == current_period - 1
|
||||
assert escrow.functions.getPastDowntimeLength(staker).call() == 0
|
||||
assert escrow.functions.getLastActivePeriod(staker).call() == 0
|
||||
|
||||
deposit_events = deposit_log.get_all_entries()
|
||||
assert len(deposit_events) == 1
|
||||
event_args = deposit_events[-1]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == 1000
|
||||
assert event_args['periods'] == 10
|
||||
|
||||
lock_events = lock_log.get_all_entries()
|
||||
assert len(lock_events) == 1
|
||||
event_args = lock_events[-1]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == 1000
|
||||
assert event_args['firstPeriod'] == current_period + 1
|
||||
assert event_args['periods'] == 10
|
||||
|
||||
# Can't deposit tokens again for the same staker twice
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.batchDeposit([staker], [1], [1000], [10])\
|
||||
.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])\
|
||||
.transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.batchDeposit([staker], [1], [1501], [10])\
|
||||
.transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.batchDeposit([staker], [1], [500], [1])\
|
||||
.transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.batchDeposit([staker], [2], [1000, 501], [10, 10])\
|
||||
.transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Inconsistent input
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.batchDeposit([staker], [0], [500], [10])\
|
||||
.transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.batchDeposit([staker], [2], [500], [10])\
|
||||
.transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.batchDeposit([staker], [1, 1], [500], [10])\
|
||||
.transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.batchDeposit([staker], [1, 1], [500, 500], [10])\
|
||||
.transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.batchDeposit([staker], [1, 1], [500, 500], [10, 10])\
|
||||
.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])\
|
||||
.transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Initialize Escrow contract
|
||||
tx = escrow.functions.initialize(0).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Deposit tokens for multiple stakers
|
||||
stakers = testerchain.client.accounts[2:7]
|
||||
tx = escrow.functions.batchDeposit(
|
||||
stakers, [1, 1, 1, 1, 1], [100, 200, 300, 400, 500], [50, 100, 150, 200, 250]).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()
|
||||
|
||||
assert len(deposit_events) == 6
|
||||
assert len(lock_events) == 6
|
||||
|
||||
for index, staker in enumerate(stakers):
|
||||
value = 100 * (index + 1)
|
||||
duration = 50 * (index + 1)
|
||||
assert escrow.functions.getAllTokens(staker).call() == value
|
||||
assert escrow.functions.getLockedTokens(staker, 0).call() == 0
|
||||
assert escrow.functions.getLockedTokens(staker, 1).call() == value
|
||||
assert escrow.functions.getLockedTokens(staker, duration).call() == value
|
||||
assert escrow.functions.getLockedTokens(staker, duration + 1).call() == 0
|
||||
assert policy_manager.functions.getPeriodsLength(staker).call() == 1
|
||||
assert policy_manager.functions.getPeriod(staker, 0).call() == current_period - 1
|
||||
assert escrow.functions.getPastDowntimeLength(staker).call() == 0
|
||||
assert escrow.functions.getLastActivePeriod(staker).call() == 0
|
||||
|
||||
event_args = deposit_events[index + 1]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value
|
||||
assert event_args['periods'] == duration
|
||||
|
||||
event_args = lock_events[index + 1]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value
|
||||
assert event_args['firstPeriod'] == current_period + 1
|
||||
assert event_args['periods'] == duration
|
||||
|
||||
# Deposit tokens for multiple stakers with multiple sub-stakes
|
||||
stakers = testerchain.client.accounts[7:10]
|
||||
tx = escrow.functions.batchDeposit(
|
||||
stakers, [1, 2, 3], [100, 200, 300, 400, 500, 600], [50, 100, 150, 200, 250, 300])\
|
||||
.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()
|
||||
|
||||
assert len(deposit_events) == 12
|
||||
assert len(lock_events) == 12
|
||||
|
||||
staker = stakers[0]
|
||||
duration = 50
|
||||
value = 100
|
||||
assert escrow.functions.getAllTokens(staker).call() == value
|
||||
assert escrow.functions.getLockedTokens(staker, 1).call() == value
|
||||
assert escrow.functions.getLockedTokens(staker, duration).call() == value
|
||||
assert escrow.functions.getLockedTokens(staker, duration + 1).call() == 0
|
||||
assert policy_manager.functions.getPeriodsLength(staker).call() == 1
|
||||
assert policy_manager.functions.getPeriod(staker, 0).call() == current_period - 1
|
||||
assert escrow.functions.getPastDowntimeLength(staker).call() == 0
|
||||
assert escrow.functions.getLastActivePeriod(staker).call() == 0
|
||||
assert escrow.functions.getSubStakesLength(staker).call() == 1
|
||||
|
||||
event_args = deposit_events[6]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value
|
||||
assert event_args['periods'] == duration
|
||||
|
||||
event_args = lock_events[6]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value
|
||||
assert event_args['firstPeriod'] == current_period + 1
|
||||
assert event_args['periods'] == duration
|
||||
|
||||
staker = stakers[1]
|
||||
duration1 = 100
|
||||
duration2 = 150
|
||||
value1 = 200
|
||||
value2 = 300
|
||||
assert escrow.functions.getAllTokens(staker).call() == value1 + value2
|
||||
assert escrow.functions.getLockedTokens(staker, 0).call() == 0
|
||||
assert escrow.functions.getLockedTokens(staker, 1).call() == value1 + value2
|
||||
assert escrow.functions.getLockedTokens(staker, duration1).call() == value1 + value2
|
||||
assert escrow.functions.getLockedTokens(staker, duration1 + 1).call() == value2
|
||||
assert escrow.functions.getLockedTokens(staker, duration2).call() == value2
|
||||
assert escrow.functions.getLockedTokens(staker, duration2 + 1).call() == 0
|
||||
assert policy_manager.functions.getPeriodsLength(staker).call() == 1
|
||||
assert policy_manager.functions.getPeriod(staker, 0).call() == current_period - 1
|
||||
assert escrow.functions.getPastDowntimeLength(staker).call() == 0
|
||||
assert escrow.functions.getLastActivePeriod(staker).call() == 0
|
||||
assert escrow.functions.getSubStakesLength(staker).call() == 2
|
||||
|
||||
event_args = deposit_events[7]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value1
|
||||
assert event_args['periods'] == duration1
|
||||
|
||||
event_args = lock_events[7]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value1
|
||||
assert event_args['firstPeriod'] == current_period + 1
|
||||
assert event_args['periods'] == duration1
|
||||
|
||||
event_args = deposit_events[8]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value2
|
||||
assert event_args['periods'] == duration2
|
||||
|
||||
event_args = lock_events[8]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value2
|
||||
assert event_args['firstPeriod'] == current_period + 1
|
||||
assert event_args['periods'] == duration2
|
||||
|
||||
staker = stakers[2]
|
||||
duration1 = 200
|
||||
duration2 = 250
|
||||
duration3 = 300
|
||||
value1 = 400
|
||||
value2 = 500
|
||||
value3 = 600
|
||||
assert escrow.functions.getAllTokens(staker).call() == value1 + value2 + value3
|
||||
assert escrow.functions.getLockedTokens(staker, 0).call() == 0
|
||||
assert escrow.functions.getLockedTokens(staker, 1).call() == value1 + value2 + value3
|
||||
assert escrow.functions.getLockedTokens(staker, duration1).call() == value1 + value2 + value3
|
||||
assert escrow.functions.getLockedTokens(staker, duration1 + 1).call() == value2 + value3
|
||||
assert escrow.functions.getLockedTokens(staker, duration2).call() == value2 + value3
|
||||
assert escrow.functions.getLockedTokens(staker, duration2 + 1).call() == value3
|
||||
assert escrow.functions.getLockedTokens(staker, duration3).call() == value3
|
||||
assert escrow.functions.getLockedTokens(staker, duration3 + 1).call() == 0
|
||||
assert policy_manager.functions.getPeriodsLength(staker).call() == 1
|
||||
assert policy_manager.functions.getPeriod(staker, 0).call() == current_period - 1
|
||||
assert escrow.functions.getPastDowntimeLength(staker).call() == 0
|
||||
assert escrow.functions.getLastActivePeriod(staker).call() == 0
|
||||
assert escrow.functions.getSubStakesLength(staker).call() == 3
|
||||
|
||||
event_args = deposit_events[9]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value1
|
||||
assert event_args['periods'] == duration1
|
||||
|
||||
event_args = lock_events[9]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value1
|
||||
assert event_args['firstPeriod'] == current_period + 1
|
||||
assert event_args['periods'] == duration1
|
||||
|
||||
event_args = deposit_events[10]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value2
|
||||
assert event_args['periods'] == duration2
|
||||
|
||||
event_args = lock_events[10]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value2
|
||||
assert event_args['firstPeriod'] == current_period + 1
|
||||
assert event_args['periods'] == duration2
|
||||
|
||||
event_args = deposit_events[11]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value3
|
||||
assert event_args['periods'] == duration3
|
||||
|
||||
event_args = lock_events[11]['args']
|
||||
assert event_args['staker'] == staker
|
||||
assert event_args['value'] == value3
|
||||
assert event_args['firstPeriod'] == current_period + 1
|
||||
assert event_args['periods'] == duration3
|
||||
|
|
|
@ -132,11 +132,13 @@ def test_stake_in_idle_network(testerchain, token_economics, test_registry):
|
|||
staker.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=staker.checksum_address)
|
||||
staker.transacting_power.activate()
|
||||
|
||||
# Since StakingEscrow hasn't been activated yet, trying to deposit must fail
|
||||
# Since StakingEscrow hasn't been activated yet, deposit should work but confirmation must fail
|
||||
amount = token_economics.minimum_allowed_locked
|
||||
periods = token_economics.minimum_locked_periods
|
||||
staker.initialize_stake(amount=amount, lock_periods=periods)
|
||||
staker.set_worker(account)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
staker.initialize_stake(amount=amount, lock_periods=periods)
|
||||
staker.staking_agent.confirm_activity(worker_address=account)
|
||||
|
||||
|
||||
@pytest.mark.slow()
|
||||
|
|
|
@ -206,6 +206,17 @@ def estimate_gas(analyzer: AnalyzeGas = None) -> None:
|
|||
transact(token_functions.transfer(ursula2, MIN_ALLOWED_LOCKED * 10), {'from': origin})
|
||||
transact(token_functions.transfer(ursula3, MIN_ALLOWED_LOCKED * 10), {'from': origin})
|
||||
|
||||
#
|
||||
# Batch deposit tokens
|
||||
#
|
||||
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),
|
||||
{'from': origin})
|
||||
|
||||
#
|
||||
# Ursula and Alice give Escrow rights to transfer
|
||||
#
|
||||
|
|
Loading…
Reference in New Issue