diff --git a/backend/app/infrastructure/database/allocations.py b/backend/app/infrastructure/database/allocations.py index d3e3afc089..19c61a24bd 100644 --- a/backend/app/infrastructure/database/allocations.py +++ b/backend/app/infrastructure/database/allocations.py @@ -1,6 +1,6 @@ from collections import defaultdict from datetime import datetime -from typing import List, Optional +from typing import List from eth_utils import to_checksum_address from sqlalchemy.orm import Query @@ -182,42 +182,6 @@ def store_allocation_request( db.session.add_all(new_allocations) -@deprecated("Alloc rework") -def add_all(epoch: int, user_id: int, nonce: int, allocations): - new_allocations = [ - Allocation( - epoch=epoch, - user_id=user_id, - nonce=nonce, - proposal_address=to_checksum_address(a.proposal_address), - amount=str(a.amount), - ) - for a in allocations - ] - db.session.add_all(new_allocations) - - -@deprecated("Alloc rework") -def add_allocation_request( - user_address: str, - epoch: int, - nonce: int, - signature: str, - is_manually_edited: Optional[bool] = None, -): - user: User = get_by_address(user_address) - - allocation_request = AllocationRequest( - user=user, - epoch=epoch, - nonce=nonce, - signature=signature, - is_manually_edited=is_manually_edited, - ) - - db.session.add(allocation_request) - - def get_allocation_request_by_user_nonce( user_address: str, nonce: int ) -> AllocationRequest | None: diff --git a/backend/app/infrastructure/routes/allocations.py b/backend/app/infrastructure/routes/allocations.py index 66be78ef96..73ed8eed59 100644 --- a/backend/app/infrastructure/routes/allocations.py +++ b/backend/app/infrastructure/routes/allocations.py @@ -3,8 +3,6 @@ from flask import current_app as app from flask_restx import Namespace, fields -from app.legacy.controllers import allocations -from app.legacy.core.allocations import AllocationRequest from app.extensions import api from app.infrastructure import OctantResource from app.modules.user.allocations import controller @@ -165,14 +163,12 @@ class Allocation(OctantResource): @ns.expect(user_allocation_request) @ns.response(201, "User allocated successfully") def post(self): - payload, signature = ns.payload["payload"], ns.payload["signature"] + app.logger.info(f"User allocation: {ns.payload}") is_manually_edited = ( ns.payload["isManuallyEdited"] if "isManuallyEdited" in ns.payload else None ) - app.logger.info(f"User allocation payload: {payload}, signature: {signature}") - user_address = allocations.allocate( - AllocationRequest(payload, signature, override_existing_allocations=True), - is_manually_edited, + user_address = controller.allocate( + ns.payload, is_manually_edited=is_manually_edited ) app.logger.info(f"User: {user_address} allocated successfully") diff --git a/backend/app/legacy/controllers/allocations.py b/backend/app/legacy/controllers/allocations.py deleted file mode 100644 index 693535f21a..0000000000 --- a/backend/app/legacy/controllers/allocations.py +++ /dev/null @@ -1,14 +0,0 @@ -from typing_extensions import deprecated -from typing import Optional - -from app.modules.user.allocations import controller as new_controller -from app.legacy.core.allocations import ( - AllocationRequest, -) - - -@deprecated("ALLOCATIONS REWORK") -def allocate( - request: AllocationRequest, is_manually_edited: Optional[bool] = None -) -> str: - return new_controller.allocate(request, is_manually_edited=is_manually_edited) diff --git a/backend/app/legacy/core/allocations.py b/backend/app/legacy/core/allocations.py deleted file mode 100644 index 2e6c665b5e..0000000000 --- a/backend/app/legacy/core/allocations.py +++ /dev/null @@ -1,117 +0,0 @@ -from typing_extensions import deprecated -from dataclasses import dataclass -from typing import List, Dict, Tuple, Optional - -from dataclass_wizard import JSONWizard -from eth_utils import to_checksum_address - -from app import exceptions -from app.extensions import proposals -from app.infrastructure import database -from app.legacy.core.epochs.epoch_snapshots import has_pending_epoch_snapshot -from app.legacy.core.user.budget import get_budget -from app.legacy.core.user.patron_mode import get_patron_mode_status - - -@dataclass(frozen=True) -class Allocation(JSONWizard): - proposal_address: str - amount: int - - -@dataclass(frozen=True) -class AllocationRequest(JSONWizard): - payload: Dict - signature: str - override_existing_allocations: bool - - -def add_allocations_to_db( - epoch: int, - user_address: str, - nonce: int, - allocations: List[Allocation], - delete_existing_user_epoch_allocations: bool, -): - user = database.user.get_by_address(user_address) - if not user: - user = database.user.add_user(user_address) - - if delete_existing_user_epoch_allocations: - revoke_previous_allocation(user.address, epoch) - - database.allocations.add_all(epoch, user.id, nonce, allocations) - - -def deserialize_payload(payload) -> Tuple[int, List[Allocation]]: - allocations = [ - Allocation.from_dict(allocation_data) - for allocation_data in payload["allocations"] - ] - return payload["nonce"], allocations - - -@deprecated("ALLOCATIONS REWORK") -def verify_allocations( - epoch: Optional[int], user_address: str, allocations: List[Allocation] -): - if epoch is None: - raise exceptions.NotInDecisionWindow - - if not has_pending_epoch_snapshot(epoch): - raise exceptions.MissingSnapshot - - patron_mode_enabled = get_patron_mode_status( - user_address=to_checksum_address(user_address) - ) - if patron_mode_enabled: - raise exceptions.NotAllowedInPatronMode(user_address) - - # Check if allocations list is empty - if len(allocations) == 0: - raise exceptions.EmptyAllocations() - - # Check if the list of proposal addresses is a subset of - # proposal addresses in the Proposals contract - proposal_addresses = [a.proposal_address for a in allocations] - valid_proposals = proposals.get_proposal_addresses(epoch) - invalid_proposals = list(set(proposal_addresses) - set(valid_proposals)) - - if invalid_proposals: - raise exceptions.InvalidProjects(invalid_proposals) - - # Check if any allocation address has been duplicated in the payload - [proposal_addresses.remove(p) for p in set(proposal_addresses)] - - if proposal_addresses: - raise exceptions.DuplicatedProposals(proposal_addresses) - - # Check if user address is not in one of the allocations - for allocation in allocations: - if allocation.proposal_address == user_address: - raise exceptions.ProposalAllocateToItself - - # Check if user didn't exceed his budget - user_budget = get_budget(user_address, epoch) - proposals_sum = sum([a.amount for a in allocations]) - - if proposals_sum > user_budget: - raise exceptions.RewardsBudgetExceeded - - -@deprecated("ALLOCATIONS REWORK") -def revoke_previous_allocation(user_address: str, epoch: int): - user = database.user.get_by_address(user_address) - if user is None: - raise exceptions.UserNotFound - - database.allocations.soft_delete_all_by_epoch_and_user_id(epoch, user.id) - - -def has_user_allocated_rewards(user_address: str, epoch: int) -> List[str]: - allocation_signature = ( - database.allocations.get_allocation_request_by_user_and_epoch( - user_address, epoch - ) - ) - return allocation_signature is not None diff --git a/backend/app/modules/user/allocations/controller.py b/backend/app/modules/user/allocations/controller.py index a59144383e..a164bbc56d 100644 --- a/backend/app/modules/user/allocations/controller.py +++ b/backend/app/modules/user/allocations/controller.py @@ -103,9 +103,10 @@ def revoke_previous_allocation(user_address: str): def _deserialize_payload(payload: Dict) -> UserAllocationRequestPayload: - allocation_items = _deserialize_items(payload.payload) - nonce = int(payload.payload["nonce"]) - signature = payload.signature + allocation_payload = payload["payload"] + allocation_items = _deserialize_items(allocation_payload) + nonce = int(allocation_payload["nonce"]) + signature = payload["signature"] return UserAllocationRequestPayload( payload=UserAllocationPayload(allocation_items, nonce), signature=signature diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index 310d196f85..5fd0353e0f 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -4,13 +4,10 @@ import os import time import urllib.request -from typing import List -from random import randint from unittest.mock import MagicMock, Mock import gql import pytest -from eth_account import Account from flask import g as request_context from flask.testing import FlaskClient from web3 import Web3 @@ -23,8 +20,6 @@ from app.infrastructure.contracts.erc20 import ERC20 from app.infrastructure.contracts.proposals import Proposals from app.infrastructure.contracts.vault import Vault -from app.legacy.controllers.allocations import allocate -from app.legacy.core.allocations import Allocation, AllocationRequest from app.legacy.crypto.account import Account as CryptoAccount from app.legacy.crypto.eip712 import build_allocations_eip712_data, sign from app.modules.dto import AccountFundsDTO, AllocationItem @@ -55,6 +50,7 @@ MATCHED_REWARDS_AFTER_OVERHAUL, NO_PATRONS_REWARDS, ) +from tests.helpers import make_user_allocation from tests.helpers.context import get_context from tests.helpers.gql_client import MockGQLClient from tests.helpers.mocked_epoch_details import EPOCH_EVENTS @@ -437,7 +433,6 @@ def patch_epochs(monkeypatch): @pytest.fixture(scope="function") def patch_proposals(monkeypatch, proposal_accounts): - monkeypatch.setattr("app.legacy.core.allocations.proposals", MOCK_PROPOSALS) monkeypatch.setattr("app.legacy.core.proposals.proposals", MOCK_PROPOSALS) monkeypatch.setattr("app.context.projects.proposals", MOCK_PROPOSALS) @@ -492,12 +487,6 @@ def patch_eth_get_balance(monkeypatch): @pytest.fixture(scope="function") def patch_has_pending_epoch_snapshot(monkeypatch): - ( - monkeypatch.setattr( - "app.legacy.core.allocations.has_pending_epoch_snapshot", - MOCK_HAS_PENDING_SNAPSHOT, - ) - ) ( monkeypatch.setattr( "app.context.epoch_state._has_pending_epoch_snapshot", @@ -520,7 +509,6 @@ def patch_last_finalized_snapshot(monkeypatch): @pytest.fixture(scope="function") def patch_user_budget(monkeypatch): - monkeypatch.setattr("app.legacy.core.allocations.get_budget", MOCK_GET_USER_BUDGET) monkeypatch.setattr( "app.modules.user.budgets.service.saved.SavedUserBudgets.get_budget", MOCK_GET_USER_BUDGET, @@ -608,45 +596,51 @@ def mock_finalized_epoch_snapshot_db(app, user_accounts): @pytest.fixture(scope="function") -def mock_allocations_db(app, user_accounts, proposal_accounts): - user1 = database.user.get_or_add_user(user_accounts[0].address) - user2 = database.user.get_or_add_user(user_accounts[1].address) - db.session.commit() +def mock_allocations_db(app, mock_users_db, proposal_accounts): + prev_epoch_context = get_context(MOCKED_PENDING_EPOCH_NO - 1) + pending_epoch_context = get_context(MOCKED_PENDING_EPOCH_NO) + user1, user2, _ = mock_users_db user1_allocations = [ - Allocation(proposal_accounts[0].address, 10 * 10**18), - Allocation(proposal_accounts[1].address, 5 * 10**18), - Allocation(proposal_accounts[2].address, 300 * 10**18), + AllocationItem(proposal_accounts[0].address, 10 * 10**18), + AllocationItem(proposal_accounts[1].address, 5 * 10**18), + AllocationItem(proposal_accounts[2].address, 300 * 10**18), ] user1_allocations_prev_epoch = [ - Allocation(proposal_accounts[0].address, 101 * 10**18), - Allocation(proposal_accounts[1].address, 51 * 10**18), - Allocation(proposal_accounts[2].address, 3001 * 10**18), + AllocationItem(proposal_accounts[0].address, 101 * 10**18), + AllocationItem(proposal_accounts[1].address, 51 * 10**18), + AllocationItem(proposal_accounts[2].address, 3001 * 10**18), ] user2_allocations = [ - Allocation(proposal_accounts[1].address, 1050 * 10**18), - Allocation(proposal_accounts[3].address, 500 * 10**18), + AllocationItem(proposal_accounts[1].address, 1050 * 10**18), + AllocationItem(proposal_accounts[3].address, 500 * 10**18), ] user2_allocations_prev_epoch = [ - Allocation(proposal_accounts[1].address, 10501 * 10**18), - Allocation(proposal_accounts[3].address, 5001 * 10**18), + AllocationItem(proposal_accounts[1].address, 10501 * 10**18), + AllocationItem(proposal_accounts[3].address, 5001 * 10**18), ] - database.allocations.add_all( - MOCKED_PENDING_EPOCH_NO - 1, user1.id, 0, user1_allocations_prev_epoch + make_user_allocation( + prev_epoch_context, + user1, + nonce=0, + allocation_items=user1_allocations_prev_epoch, ) - database.allocations.add_all( - MOCKED_PENDING_EPOCH_NO - 1, user2.id, 0, user2_allocations_prev_epoch + make_user_allocation( + prev_epoch_context, + user2, + nonce=0, + allocation_items=user2_allocations_prev_epoch, ) - database.allocations.add_all( - MOCKED_PENDING_EPOCH_NO, user1.id, 1, user1_allocations + make_user_allocation( + pending_epoch_context, user1, nonce=1, allocation_items=user1_allocations ) - database.allocations.add_all( - MOCKED_PENDING_EPOCH_NO, user2.id, 1, user2_allocations + make_user_allocation( + pending_epoch_context, user2, nonce=1, allocation_items=user2_allocations ) db.session.commit() @@ -765,41 +759,6 @@ def mock_user_rewards(alice, bob): return user_rewards_service_mock -def allocate_user_rewards( - user_account: Account, proposal_account, allocation_amount, nonce: int = 0 -): - payload = create_payload([proposal_account], [allocation_amount], nonce) - signature = sign(user_account, build_allocations_eip712_data(payload)) - request = AllocationRequest(payload, signature, override_existing_allocations=False) - - allocate(request) - - -def create_payload(proposals, amounts: list[int] | None, nonce: int = 0): - if amounts is None: - amounts = [randint(1 * 10**18, 1000 * 10**18) for _ in proposals] - - allocations = [ - { - "proposalAddress": proposal.address, - "amount": str(amount), - } - for proposal, amount in zip(proposals, amounts) - ] - - return {"allocations": allocations, "nonce": nonce} - - -def deserialize_allocations(payload) -> List[Allocation]: - return [ - AllocationItem( - proposal_address=allocation_data["proposalAddress"], - amount=int(allocation_data["amount"]), - ) - for allocation_data in payload["allocations"] - ] - - def _split_deposit_events(deposit_events): deposit_events = deposit_events if deposit_events is not None else [] diff --git a/backend/tests/helpers/__init__.py b/backend/tests/helpers/__init__.py index d9b0cbbc2f..c93de11a06 100644 --- a/backend/tests/helpers/__init__.py +++ b/backend/tests/helpers/__init__.py @@ -1,3 +1,4 @@ +from .allocations import make_user_allocation # noqa from .subgraph.events import ( # noqa create_epoch_event, generate_epoch_events, diff --git a/backend/tests/helpers/allocations.py b/backend/tests/helpers/allocations.py new file mode 100644 index 0000000000..e8417402a0 --- /dev/null +++ b/backend/tests/helpers/allocations.py @@ -0,0 +1,59 @@ +from typing import List +from random import randint + +from app.modules.dto import ( + AllocationItem, + UserAllocationPayload, + UserAllocationRequestPayload, +) +from app.infrastructure import database + + +def create_payload(proposals, amounts: list[int] | None, nonce: int = 0): + if amounts is None: + amounts = [randint(1 * 10**18, 1000 * 10**18) for _ in proposals] + + allocations = [ + { + "proposalAddress": proposal.address, + "amount": str(amount), + } + for proposal, amount in zip(proposals, amounts) + ] + + return {"allocations": allocations, "nonce": nonce} + + +def deserialize_allocations(payload) -> List[AllocationItem]: + return [ + AllocationItem( + proposal_address=allocation_data["proposalAddress"], + amount=int(allocation_data["amount"]), + ) + for allocation_data in payload["allocations"] + ] + + +def make_user_allocation(context, user, allocations=1, nonce=0, **kwargs): + projects = context.projects_details.projects + database.allocations.soft_delete_all_by_epoch_and_user_id( + context.epoch_details.epoch_num, user.id + ) + + allocation_items = [ + AllocationItem(projects[i], (i + 1) * 100) for i in range(allocations) + ] + + if kwargs.get("allocation_items"): + allocation_items = kwargs.get("allocation_items") + + request = UserAllocationRequestPayload( + payload=UserAllocationPayload(allocations=allocation_items, nonce=nonce), + signature="0xdeadbeef", + ) + + database.allocations.store_allocation_request( + user.address, context.epoch_details.epoch_num, request, **kwargs + ) + + return allocation_items diff --git a/backend/tests/legacy/test_allocations.py b/backend/tests/legacy/test_allocations.py deleted file mode 100644 index 978f7ec484..0000000000 --- a/backend/tests/legacy/test_allocations.py +++ /dev/null @@ -1,311 +0,0 @@ -import pytest - -from app import exceptions -from app.infrastructure import database -from app.legacy.controllers.allocations import ( - allocate, -) -from app.legacy.core.allocations import ( - AllocationRequest, -) -from app.legacy.crypto.eip712 import sign, build_allocations_eip712_data -from tests.conftest import ( - create_payload, - deserialize_allocations, - mock_graphql, - MOCKED_PENDING_EPOCH_NO, - MOCK_PROPOSALS, - MOCK_GET_USER_BUDGET, -) -from tests.helpers import create_epoch_event - - -from app.modules.user.allocations import controller as new_controller - - -def get_allocation_nonce(user_address): - return new_controller.get_user_next_nonce(user_address) - - -def get_all_by_epoch(epoch, include_zeroes=False): - return new_controller.get_all_allocations(epoch) - - -@pytest.fixture(autouse=True) -def before( - app, - mocker, - graphql_client, - proposal_accounts, - patch_epochs, - patch_proposals, - patch_has_pending_epoch_snapshot, - patch_user_budget, -): - MOCK_PROPOSALS.get_proposal_addresses.return_value = [ - p.address for p in proposal_accounts[0:5] - ] - - mock_graphql( - mocker, epochs_events=[create_epoch_event(epoch=MOCKED_PENDING_EPOCH_NO)] - ) - - -def test_user_allocates_for_the_first_time(tos_users, proposal_accounts): - # Test data - payload = create_payload(proposal_accounts[0:2], None) - signature = sign(tos_users[0], build_allocations_eip712_data(payload)) - - # Call allocate method - allocate(AllocationRequest(payload, signature, override_existing_allocations=True)) - - # Check if allocations were created - check_allocations(tos_users[0].address, payload, 2) - - # Check if threshold is properly calculated - check_allocation_threshold(payload) - - -def test_multiple_users_allocate_for_the_first_time(tos_users, proposal_accounts): - # Test data - payload1 = create_payload(proposal_accounts[0:2], None) - signature1 = sign(tos_users[0], build_allocations_eip712_data(payload1)) - - payload2 = create_payload(proposal_accounts[0:3], None) - signature2 = sign(tos_users[1], build_allocations_eip712_data(payload2)) - - # Call allocate method for both users - allocate( - AllocationRequest(payload1, signature1, override_existing_allocations=True) - ) - allocate( - AllocationRequest(payload2, signature2, override_existing_allocations=True) - ) - - # Check if allocations were created for both users - check_allocations(tos_users[0].address, payload1, 2) - check_allocations(tos_users[1].address, payload2, 3) - - # Check if threshold is properly calculated - check_allocation_threshold(payload1, payload2) - - -def test_allocate_updates_with_more_proposals(tos_users, proposal_accounts): - # Test data - initial_payload = create_payload(proposal_accounts[0:2], None, 0) - initial_signature = sign( - tos_users[0], build_allocations_eip712_data(initial_payload) - ) - - # Call allocate method - allocate( - AllocationRequest( - initial_payload, initial_signature, override_existing_allocations=True - ) - ) - - # Create a new payload with more proposals - updated_payload = create_payload(proposal_accounts[0:3], None, 1) - updated_signature = sign( - tos_users[0], build_allocations_eip712_data(updated_payload) - ) - - # Call allocate method with updated_payload - allocate( - AllocationRequest( - updated_payload, updated_signature, override_existing_allocations=True - ) - ) - - # Check if allocations were updated - check_allocations(tos_users[0].address, updated_payload, 3) - - # Check if threshold is properly calculated - check_allocation_threshold(updated_payload) - - -def test_allocate_updates_with_less_proposals(tos_users, proposal_accounts): - # Test data - initial_payload = create_payload(proposal_accounts[0:3], None, 0) - initial_signature = sign( - tos_users[0], build_allocations_eip712_data(initial_payload) - ) - - # Call allocate method - allocate( - AllocationRequest( - initial_payload, initial_signature, override_existing_allocations=True - ) - ) - - # Create a new payload with fewer proposals - updated_payload = create_payload(proposal_accounts[0:2], None, 1) - updated_signature = sign( - tos_users[0], build_allocations_eip712_data(updated_payload) - ) - - # Call allocate method with updated_payload - allocate( - AllocationRequest( - updated_payload, updated_signature, override_existing_allocations=True - ) - ) - - # Check if allocations were updated - check_allocations(tos_users[0].address, updated_payload, 2) - - # Check if threshold is properly calculated - check_allocation_threshold(updated_payload) - - -def test_multiple_users_change_their_allocations(tos_users, proposal_accounts): - # Create initial payloads and signatures for both users - initial_payload1 = create_payload(proposal_accounts[0:2], None, 0) - initial_signature1 = sign( - tos_users[0], build_allocations_eip712_data(initial_payload1) - ) - initial_payload2 = create_payload(proposal_accounts[0:3], None, 0) - initial_signature2 = sign( - tos_users[1], build_allocations_eip712_data(initial_payload2) - ) - - # Call allocate method with initial payloads for both users - allocate( - AllocationRequest( - initial_payload1, initial_signature1, override_existing_allocations=True - ) - ) - allocate( - AllocationRequest( - initial_payload2, initial_signature2, override_existing_allocations=True - ) - ) - - # Create updated payloads for both users - updated_payload1 = create_payload(proposal_accounts[0:4], None, 1) - updated_signature1 = sign( - tos_users[0], build_allocations_eip712_data(updated_payload1) - ) - updated_payload2 = create_payload(proposal_accounts[2:5], None, 1) - updated_signature2 = sign( - tos_users[1], build_allocations_eip712_data(updated_payload2) - ) - - # Call allocate method with updated payloads for both users - allocate( - AllocationRequest( - updated_payload1, updated_signature1, override_existing_allocations=True - ) - ) - allocate( - AllocationRequest( - updated_payload2, updated_signature2, override_existing_allocations=True - ) - ) - - # Check if allocations were updated for both users - check_allocations(tos_users[0].address, updated_payload1, 4) - check_allocations(tos_users[1].address, updated_payload2, 3) - - # Check if threshold is properly calculated - check_allocation_threshold(updated_payload1, updated_payload2) - - -def test_user_exceeded_rewards_budget_in_allocations(app, proposal_accounts, tos_users): - # Set some reasonable user rewards budget - MOCK_GET_USER_BUDGET.return_value = 100 * 10**18 - - # First payload sums up to 110 eth (budget is set to 100) - payload = create_payload( - proposal_accounts[0:3], [10 * 10**18, 50 * 10**18, 50 * 10**18] - ) - signature = sign(tos_users[0], build_allocations_eip712_data(payload)) - - with pytest.raises(exceptions.RewardsBudgetExceeded): - allocate( - AllocationRequest(payload, signature, override_existing_allocations=True) - ) - - # Lower it to 100 total (should pass) - payload = create_payload( - proposal_accounts[0:3], [10 * 10**18, 40 * 10**18, 50 * 10**18] - ) - signature = sign(tos_users[0], build_allocations_eip712_data(payload)) - allocate(AllocationRequest(payload, signature, override_existing_allocations=True)) - - -def test_nonces(tos_users, proposal_accounts): - nonce0 = get_allocation_nonce(tos_users[0].address) - payload = create_payload( - proposal_accounts[0:2], [10 * 10**18, 20 * 10**18], nonce0 - ) - signature = sign(tos_users[0], build_allocations_eip712_data(payload)) - allocate(AllocationRequest(payload, signature, override_existing_allocations=True)) - nonce1 = get_allocation_nonce(tos_users[0].address) - assert nonce0 != nonce1 - payload = create_payload( - proposal_accounts[0:2], [10 * 10**18, 30 * 10**18], nonce1 - ) - signature = sign(tos_users[0], build_allocations_eip712_data(payload)) - allocate(AllocationRequest(payload, signature, override_existing_allocations=True)) - nonce2 = get_allocation_nonce(tos_users[0].address) - assert nonce1 != nonce2 - - payload = create_payload( - proposal_accounts[0:2], [10 * 10**18, 10 * 10**18], nonce1 - ) - signature = sign(tos_users[0], build_allocations_eip712_data(payload)) - with pytest.raises(exceptions.WrongAllocationsNonce): - allocate( - AllocationRequest(payload, signature, override_existing_allocations=True) - ) - - -def test_stores_allocation_request_signature(tos_users, proposal_accounts): - nonce0 = get_allocation_nonce(tos_users[0].address) - payload = create_payload( - proposal_accounts[0:2], [10 * 10**18, 20 * 10**18], nonce0 - ) - signature = sign(tos_users[0], build_allocations_eip712_data(payload)) - - allocate(AllocationRequest(payload, signature, override_existing_allocations=True)) - - alloc_signature = database.allocations.get_allocation_request_by_user_nonce( - tos_users[0].address, nonce0 - ) - - assert alloc_signature is not None - - assert alloc_signature.epoch == MOCKED_PENDING_EPOCH_NO - assert alloc_signature.signature == signature - - -def check_allocations(user_address, expected_payload, expected_count): - epoch = MOCKED_PENDING_EPOCH_NO - expected_allocations = deserialize_allocations(expected_payload) - user = database.user.get_by_address(user_address) - assert user is not None - - db_allocations = database.allocations.get_all_by_epoch_and_user_id(epoch, user.id) - assert len(db_allocations) == expected_count - - for db_allocation, expected_allocation in zip(db_allocations, expected_allocations): - assert db_allocation.epoch == epoch - assert db_allocation.user_id == user.id - assert db_allocation.user is not None - assert db_allocation.proposal_address == expected_allocation.proposal_address - assert int(db_allocation.amount) == expected_allocation.amount - - -def check_allocation_threshold(*payloads): - epoch = MOCKED_PENDING_EPOCH_NO - expected = [deserialize_allocations(payload) for payload in payloads] - - db_allocations = database.allocations.get_all_by_epoch(epoch) - - total_allocations = sum([int(allocation.amount) for allocation in db_allocations]) - total_payload_allocations = sum( - [allocation.amount for allocations in expected for allocation in allocations] - ) - - assert total_allocations == total_payload_allocations diff --git a/backend/tests/legacy/test_rewards.py b/backend/tests/legacy/test_rewards.py index 8c23b9b4cf..b1800ac328 100644 --- a/backend/tests/legacy/test_rewards.py +++ b/backend/tests/legacy/test_rewards.py @@ -1,21 +1,17 @@ import pytest from app import exceptions -from app.legacy.controllers.allocations import allocate +from app.modules.user.allocations.controller import allocate +from app.legacy.crypto.eip712 import build_allocations_eip712_data, sign + from app.legacy.controllers.rewards import ( get_allocation_threshold, ) -from app.legacy.core.allocations import AllocationRequest from tests.conftest import ( MOCK_EPOCHS, - deserialize_allocations, MOCK_PROPOSALS, ) -from tests.legacy.test_allocations import ( - build_allocations_eip712_data, - create_payload, - sign, -) +from tests.helpers.allocations import create_payload, deserialize_allocations from app.modules.user.allocations import controller as new_controller @@ -28,6 +24,7 @@ def get_allocation_nonce(user_address): @pytest.fixture(autouse=True) def before( proposal_accounts, + mock_epoch_details, patch_epochs, patch_proposals, patch_has_pending_epoch_snapshot, @@ -64,12 +61,8 @@ def _allocate_random_individual_rewards(user_accounts, proposal_accounts) -> int signature2 = sign(user_accounts[1], build_allocations_eip712_data(payload2)) # Call allocate method for both users - allocate( - AllocationRequest(payload1, signature1, override_existing_allocations=True) - ) - allocate( - AllocationRequest(payload2, signature2, override_existing_allocations=True) - ) + allocate({"payload": payload1, "signature": signature1}) + allocate({"payload": payload2, "signature": signature2}) allocations1 = sum([int(a.amount) for a in deserialize_allocations(payload1)]) allocations2 = sum([int(a.amount) for a in deserialize_allocations(payload2)]) diff --git a/backend/tests/legacy/test_user.py b/backend/tests/legacy/test_user.py index 0112e657ed..d820351816 100644 --- a/backend/tests/legacy/test_user.py +++ b/backend/tests/legacy/test_user.py @@ -22,7 +22,7 @@ @pytest.fixture(autouse=True) -def before(app, patch_epochs, patch_proposals, patch_is_contract): +def before(app, patch_epochs, patch_proposals, patch_is_contract, mock_epoch_details): pass diff --git a/backend/tests/modules/modules_factory/test_modules_factory.py b/backend/tests/modules/modules_factory/test_modules_factory.py index 5e94f8b0ce..8f9d79529f 100644 --- a/backend/tests/modules/modules_factory/test_modules_factory.py +++ b/backend/tests/modules/modules_factory/test_modules_factory.py @@ -102,13 +102,15 @@ def test_pending_services_factory(): result = PendingServices.create() events_based_patron_mode = EventsBasedUserPatronMode() + saved_user_budgets = SavedUserBudgets() octant_rewards = PendingOctantRewards(patrons_mode=events_based_patron_mode) user_allocations = PendingUserAllocations( - octant_rewards=octant_rewards, + user_budgets=saved_user_budgets, patrons_mode=events_based_patron_mode, + octant_rewards=octant_rewards, ) user_rewards = CalculatedUserRewards( - user_budgets=SavedUserBudgets(), + user_budgets=saved_user_budgets, patrons_mode=events_based_patron_mode, allocations=user_allocations, ) diff --git a/backend/tests/modules/octant_rewards/test_finalized_octant_rewards.py b/backend/tests/modules/octant_rewards/test_finalized_octant_rewards.py index 722fb987c9..8bd849f704 100644 --- a/backend/tests/modules/octant_rewards/test_finalized_octant_rewards.py +++ b/backend/tests/modules/octant_rewards/test_finalized_octant_rewards.py @@ -1,6 +1,7 @@ -from app.infrastructure import database -from app.modules.dto import AllocationDTO +from app.modules.dto import AllocationItem from app.modules.octant_rewards.service.finalized import FinalizedOctantRewards + +from tests.helpers import make_user_allocation from tests.helpers.constants import ( USER1_BUDGET, COMMUNITY_FUND, @@ -59,13 +60,13 @@ def test_finalized_get_leverage( proposal_accounts, mock_users_db, mock_finalized_epoch_snapshot_db ): user, _, _ = mock_users_db - database.allocations.add_all( - 1, - user.id, - 0, - [AllocationDTO(proposal_accounts[0].address, USER1_BUDGET)], - ) context = get_context() + make_user_allocation( + context, + user, + allocation_items=[AllocationItem(proposal_accounts[0].address, USER1_BUDGET)], + ) + service = FinalizedOctantRewards() result = service.get_leverage(context) diff --git a/backend/tests/modules/octant_rewards/test_pending_octant_rewards.py b/backend/tests/modules/octant_rewards/test_pending_octant_rewards.py index 8102a2a807..d56a0dc58f 100644 --- a/backend/tests/modules/octant_rewards/test_pending_octant_rewards.py +++ b/backend/tests/modules/octant_rewards/test_pending_octant_rewards.py @@ -1,7 +1,6 @@ from unittest.mock import Mock -from app.infrastructure import database -from app.modules.dto import AllocationDTO +from app.modules.dto import AllocationItem from app.modules.octant_rewards.service.pending import PendingOctantRewards from tests.helpers.constants import ( USER1_BUDGET, @@ -9,6 +8,7 @@ COMMUNITY_FUND, PPF, ) +from tests.helpers import make_user_allocation from tests.helpers.context import get_context from tests.helpers.pending_snapshot import create_pending_snapshot from tests.modules.octant_rewards.helpers.checker import check_octant_rewards @@ -75,14 +75,13 @@ def test_pending_get_leverage( proposal_accounts, mock_users_db, mock_pending_epoch_snapshot_db, mock_patron_mode ): user, _, _ = mock_users_db - database.allocations.add_all( - 1, - user.id, - 0, - [AllocationDTO(proposal_accounts[0].address, USER1_BUDGET)], - ) context = get_context() service = PendingOctantRewards(patrons_mode=mock_patron_mode) + make_user_allocation( + context, + user, + allocation_items=[AllocationItem(proposal_accounts[0].address, USER1_BUDGET)], + ) result = service.get_leverage(context) diff --git a/backend/tests/modules/project_rewards/test_estimated_rewards.py b/backend/tests/modules/project_rewards/test_estimated_rewards.py index 7a600b5787..1117d09d9b 100644 --- a/backend/tests/modules/project_rewards/test_estimated_rewards.py +++ b/backend/tests/modules/project_rewards/test_estimated_rewards.py @@ -1,8 +1,8 @@ import pytest -from app.infrastructure import database -from app.modules.dto import AllocationDTO +from app.modules.dto import AllocationItem from app.modules.project_rewards.service.estimated import EstimatedProjectRewards +from tests.helpers import make_user_allocation from tests.helpers.constants import USER1_BUDGET from tests.helpers.context import get_context @@ -35,11 +35,10 @@ def test_estimated_project_rewards_with_allocations( context = get_context(3) user, _, _ = mock_users_db - database.allocations.add_all( - 3, - user.id, - 0, - [AllocationDTO(proposal_accounts[0].address, USER1_BUDGET)], + make_user_allocation( + context, + user, + allocation_items=[AllocationItem(proposal_accounts[0].address, USER1_BUDGET)], ) service = EstimatedProjectRewards(octant_rewards=mock_octant_rewards) diff --git a/backend/tests/modules/snapshots/finalized/test_finalizing_snapshots.py b/backend/tests/modules/snapshots/finalized/test_finalizing_snapshots.py index ab0b7e3015..708dda4331 100644 --- a/backend/tests/modules/snapshots/finalized/test_finalizing_snapshots.py +++ b/backend/tests/modules/snapshots/finalized/test_finalizing_snapshots.py @@ -3,8 +3,9 @@ import pytest from app.infrastructure import database -from app.modules.dto import AllocationDTO +from app.modules.dto import AllocationItem from app.modules.snapshots.finalized.service.finalizing import FinalizingSnapshots +from tests.helpers import make_user_allocation from tests.helpers.constants import MATCHED_REWARDS, USER2_BUDGET from tests.helpers.context import get_context @@ -19,8 +20,8 @@ def test_create_finalized_snapshots_with_rewards( ): context = get_context(1) projects = context.projects_details.projects - database.allocations.add_all( - 1, mock_users_db[2].id, 0, [AllocationDTO(projects[0], 100)] + make_user_allocation( + context, mock_users_db[2], allocation_items=[AllocationItem(projects[0], 100)] ) service = FinalizingSnapshots( diff --git a/backend/tests/modules/snapshots/finalized/test_simulated_finalized_snapshots.py b/backend/tests/modules/snapshots/finalized/test_simulated_finalized_snapshots.py index bc636b8f17..2a6156a5eb 100644 --- a/backend/tests/modules/snapshots/finalized/test_simulated_finalized_snapshots.py +++ b/backend/tests/modules/snapshots/finalized/test_simulated_finalized_snapshots.py @@ -1,12 +1,12 @@ import pytest -from app.infrastructure import database -from app.modules.dto import AccountFundsDTO, AllocationDTO, ProjectAccountFundsDTO +from app.modules.dto import AccountFundsDTO, ProjectAccountFundsDTO from app.modules.snapshots.finalized.service.simulated import ( SimulatedFinalizedSnapshots, ) from tests.helpers.constants import MATCHED_REWARDS from tests.helpers.context import get_context +from tests.helpers import make_user_allocation @pytest.fixture(autouse=True) @@ -19,9 +19,7 @@ def test_simulate_finalized_snapshots( ): context = get_context(1) projects = context.projects_details.projects - database.allocations.add_all( - 1, mock_users_db[2].id, 0, [AllocationDTO(projects[0], 100)] - ) + make_user_allocation(context, mock_users_db[2]) service = SimulatedFinalizedSnapshots( patrons_mode=mock_patron_mode, diff --git a/backend/tests/modules/user/allocations/test_pending_allocations.py b/backend/tests/modules/user/allocations/test_pending_allocations.py index a9b6562802..db90320010 100644 --- a/backend/tests/modules/user/allocations/test_pending_allocations.py +++ b/backend/tests/modules/user/allocations/test_pending_allocations.py @@ -1,17 +1,57 @@ import pytest +from app import exceptions from app.engine.projects.rewards import ProjectRewardDTO -from app.infrastructure import database from app.context.epoch_state import EpochState +from app.infrastructure import database from app.modules.dto import AllocationDTO +from app.modules.user.allocations import controller from app.modules.user.allocations.service.pending import PendingUserAllocations + +from app.legacy.crypto.eip712 import sign, build_allocations_eip712_data + +from tests.conftest import ( + mock_graphql, + MOCKED_PENDING_EPOCH_NO, + MOCK_PROPOSALS, + MOCK_GET_USER_BUDGET, +) +from tests.helpers import create_epoch_event +from tests.helpers.allocations import ( + create_payload, + deserialize_allocations, + make_user_allocation, +) from tests.helpers.constants import MATCHED_REWARDS from tests.helpers.context import get_context +def get_allocation_nonce(user_address): + return controller.get_user_next_nonce(user_address) + + +def get_all_by_epoch(epoch, include_zeroes=False): + return controller.get_all_allocations(epoch) + + @pytest.fixture(autouse=True) -def before(app): - pass +def before( + app, + mocker, + graphql_client, + proposal_accounts, + patch_epochs, + patch_proposals, + patch_has_pending_epoch_snapshot, + patch_user_budget, +): + MOCK_PROPOSALS.get_proposal_addresses.return_value = [ + p.address for p in proposal_accounts[0:5] + ] + + mock_graphql( + mocker, epochs_events=[create_epoch_event(epoch=MOCKED_PENDING_EPOCH_NO)] + ) @pytest.fixture() @@ -27,10 +67,7 @@ def test_simulate_allocation(service, mock_users_db): user1, _, _ = mock_users_db context = get_context() projects = context.projects_details.projects - prev_allocation = [ - AllocationDTO(projects[0], 100_000000000), - ] - database.allocations.add_all(1, user1.id, 0, prev_allocation) + make_user_allocation(context, user1) next_allocations = [ AllocationDTO(projects[1], 200_000000000), @@ -56,17 +93,236 @@ def test_simulate_allocation(service, mock_users_db): ProjectRewardDTO(sorted_projects[9], 0, 0), ] + # but the allocation didn't change + assert service.get_user_allocation_sum(context, user1.address) == 100 + def test_revoke_previous_allocation(service, mock_users_db): user1, _, _ = mock_users_db context = get_context(epoch_state=EpochState.PENDING) + make_user_allocation(context, user1) - projects = context.projects_details.projects - prev_allocation = [ - AllocationDTO(projects[0], 100_000000000), - ] - database.allocations.add_all(1, user1.id, 0, prev_allocation) - - assert service.get_user_allocation_sum(context, user1.address) == 100_000000000 + assert service.get_user_allocation_sum(context, user1.address) == 100 service.revoke_previous_allocation(context, user1.address) assert service.get_user_allocation_sum(context, user1.address) == 0 + + +def test_user_allocates_for_the_first_time(tos_users, proposal_accounts): + # Test data + payload = create_payload(proposal_accounts[0:2], None) + signature = sign(tos_users[0], build_allocations_eip712_data(payload)) + + # Call allocate method + controller.allocate({"payload": payload, "signature": signature}) + + # Check if allocations were created + check_allocations(tos_users[0].address, payload, 2) + + # Check if threshold is properly calculated + check_allocation_threshold(payload) + + +def test_multiple_users_allocate_for_the_first_time(tos_users, proposal_accounts): + # Test data + payload1 = create_payload(proposal_accounts[0:2], None) + signature1 = sign(tos_users[0], build_allocations_eip712_data(payload1)) + + payload2 = create_payload(proposal_accounts[0:3], None) + signature2 = sign(tos_users[1], build_allocations_eip712_data(payload2)) + + # Call allocate method for both users + controller.allocate({"payload": payload1, "signature": signature1}) + controller.allocate({"payload": payload2, "signature": signature2}) + + # Check if allocations were created for both users + check_allocations(tos_users[0].address, payload1, 2) + check_allocations(tos_users[1].address, payload2, 3) + + # Check if threshold is properly calculated + check_allocation_threshold(payload1, payload2) + + +def test_allocate_updates_with_more_proposals(tos_users, proposal_accounts): + # Test data + initial_payload = create_payload(proposal_accounts[0:2], None, 0) + initial_signature = sign( + tos_users[0], build_allocations_eip712_data(initial_payload) + ) + + # Call allocate method + controller.allocate({"payload": initial_payload, "signature": initial_signature}) + + # Create a new payload with more proposals + updated_payload = create_payload(proposal_accounts[0:3], None, 1) + updated_signature = sign( + tos_users[0], build_allocations_eip712_data(updated_payload) + ) + + # Call allocate method with updated_payload + controller.allocate({"payload": updated_payload, "signature": updated_signature}) + + # Check if allocations were updated + check_allocations(tos_users[0].address, updated_payload, 3) + + # Check if threshold is properly calculated + check_allocation_threshold(updated_payload) + + +def test_allocate_updates_with_less_proposals(tos_users, proposal_accounts): + # Test data + initial_payload = create_payload(proposal_accounts[0:3], None, 0) + initial_signature = sign( + tos_users[0], build_allocations_eip712_data(initial_payload) + ) + + # Call allocate method + controller.allocate({"payload": initial_payload, "signature": initial_signature}) + + # Create a new payload with fewer proposals + updated_payload = create_payload(proposal_accounts[0:2], None, 1) + updated_signature = sign( + tos_users[0], build_allocations_eip712_data(updated_payload) + ) + + # Call allocate method with updated_payload + controller.allocate({"payload": updated_payload, "signature": updated_signature}) + + # Check if allocations were updated + check_allocations(tos_users[0].address, updated_payload, 2) + + # Check if threshold is properly calculated + check_allocation_threshold(updated_payload) + + +def test_multiple_users_change_their_allocations(tos_users, proposal_accounts): + # Create initial payloads and signatures for both users + initial_payload1 = create_payload(proposal_accounts[0:2], None, 0) + initial_signature1 = sign( + tos_users[0], build_allocations_eip712_data(initial_payload1) + ) + initial_payload2 = create_payload(proposal_accounts[0:3], None, 0) + initial_signature2 = sign( + tos_users[1], build_allocations_eip712_data(initial_payload2) + ) + + # Call allocate method with initial payloads for both users + controller.allocate({"payload": initial_payload1, "signature": initial_signature1}) + controller.allocate({"payload": initial_payload2, "signature": initial_signature2}) + + # Create updated payloads for both users + updated_payload1 = create_payload(proposal_accounts[0:4], None, 1) + updated_signature1 = sign( + tos_users[0], build_allocations_eip712_data(updated_payload1) + ) + updated_payload2 = create_payload(proposal_accounts[2:5], None, 1) + updated_signature2 = sign( + tos_users[1], build_allocations_eip712_data(updated_payload2) + ) + + # Call allocate method with updated payloads for both users + controller.allocate({"payload": updated_payload1, "signature": updated_signature1}) + controller.allocate({"payload": updated_payload2, "signature": updated_signature2}) + + # Check if allocations were updated for both users + check_allocations(tos_users[0].address, updated_payload1, 4) + check_allocations(tos_users[1].address, updated_payload2, 3) + + # Check if threshold is properly calculated + check_allocation_threshold(updated_payload1, updated_payload2) + + +def test_user_exceeded_rewards_budget_in_allocations(app, proposal_accounts, tos_users): + # Set some reasonable user rewards budget + MOCK_GET_USER_BUDGET.return_value = 100 * 10**18 + + # First payload sums up to 110 eth (budget is set to 100) + payload = create_payload( + proposal_accounts[0:3], [10 * 10**18, 50 * 10**18, 50 * 10**18] + ) + signature = sign(tos_users[0], build_allocations_eip712_data(payload)) + + with pytest.raises(exceptions.RewardsBudgetExceeded): + controller.allocate({"payload": payload, "signature": signature}) + + # Lower it to 100 total (should pass) + payload = create_payload( + proposal_accounts[0:3], [10 * 10**18, 40 * 10**18, 50 * 10**18] + ) + signature = sign(tos_users[0], build_allocations_eip712_data(payload)) + controller.allocate({"payload": payload, "signature": signature}) + + +def test_nonces(tos_users, proposal_accounts): + nonce0 = get_allocation_nonce(tos_users[0].address) + payload = create_payload( + proposal_accounts[0:2], [10 * 10**18, 20 * 10**18], nonce0 + ) + signature = sign(tos_users[0], build_allocations_eip712_data(payload)) + controller.allocate({"payload": payload, "signature": signature}) + nonce1 = get_allocation_nonce(tos_users[0].address) + assert nonce0 != nonce1 + payload = create_payload( + proposal_accounts[0:2], [10 * 10**18, 30 * 10**18], nonce1 + ) + signature = sign(tos_users[0], build_allocations_eip712_data(payload)) + controller.allocate({"payload": payload, "signature": signature}) + + nonce2 = get_allocation_nonce(tos_users[0].address) + assert nonce1 != nonce2 + + payload = create_payload( + proposal_accounts[0:2], [10 * 10**18, 10 * 10**18], nonce1 + ) + signature = sign(tos_users[0], build_allocations_eip712_data(payload)) + with pytest.raises(exceptions.WrongAllocationsNonce): + controller.allocate({"payload": payload, "signature": signature}) + + +def test_stores_allocation_request_signature(tos_users, proposal_accounts): + nonce0 = get_allocation_nonce(tos_users[0].address) + payload = create_payload( + proposal_accounts[0:2], [10 * 10**18, 20 * 10**18], nonce0 + ) + signature = sign(tos_users[0], build_allocations_eip712_data(payload)) + + controller.allocate({"payload": payload, "signature": signature}) + + alloc_signature = database.allocations.get_allocation_request_by_user_nonce( + tos_users[0].address, nonce0 + ) + + assert alloc_signature is not None + + assert alloc_signature.epoch == MOCKED_PENDING_EPOCH_NO + assert alloc_signature.signature == signature + + +def check_allocations(user_address, expected_payload, expected_count): + epoch = MOCKED_PENDING_EPOCH_NO + expected_allocations = deserialize_allocations(expected_payload) + user = database.user.get_by_address(user_address) + assert user is not None + + db_allocations = database.allocations.get_all_by_epoch_and_user_id(epoch, user.id) + assert len(db_allocations) == expected_count + + for db_allocation, expected_allocation in zip(db_allocations, expected_allocations): + assert db_allocation.epoch == epoch + assert db_allocation.user_id == user.id + assert db_allocation.user is not None + assert db_allocation.proposal_address == expected_allocation.proposal_address + assert int(db_allocation.amount) == expected_allocation.amount + + +def check_allocation_threshold(*payloads): + epoch = MOCKED_PENDING_EPOCH_NO + expected = [deserialize_allocations(payload) for payload in payloads] + + db_allocations = database.allocations.get_all(epoch) + + total_allocations = sum([int(allocation.amount) for allocation in db_allocations]) + total_payload_allocations = sum( + [allocation.amount for allocations in expected for allocation in allocations] + ) + + assert total_allocations == total_payload_allocations diff --git a/backend/tests/modules/user/allocations/test_saved_allocations.py b/backend/tests/modules/user/allocations/test_saved_allocations.py index 0b93e6a9e9..d0acbf4f64 100644 --- a/backend/tests/modules/user/allocations/test_saved_allocations.py +++ b/backend/tests/modules/user/allocations/test_saved_allocations.py @@ -13,6 +13,7 @@ from app.modules.history.dto import AllocationItem as HistoryAllocationItem from tests.helpers.context import get_context +from tests.helpers import make_user_allocation @pytest.fixture(autouse=True) @@ -25,35 +26,6 @@ def service(): return SavedUserAllocations() -@pytest.fixture() -def make_user_allocation(proposal_accounts): - def _make_user_allocation(context, user, allocations=1, nonce=0, **kwargs): - database.allocations.soft_delete_all_by_epoch_and_user_id( - context.epoch_details.epoch_num, user.id - ) - - allocation_items = [ - AllocationItem(proposal_accounts[i].address, (i + 1) * 100) - for i in range(allocations) - ] - - if kwargs.get("allocation_items"): - allocation_items = kwargs.get("allocation_items") - - request = UserAllocationRequestPayload( - payload=UserAllocationPayload(allocations=allocation_items, nonce=nonce), - signature="0xdeadbeef", - ) - - database.allocations.store_allocation_request( - user.address, context.epoch_details.epoch_num, request, **kwargs - ) - - return allocation_items - - return _make_user_allocation - - def _alloc_item_to_donation(item, user): return ProposalDonationDTO(user.address, item.amount, item.proposal_address) @@ -152,7 +124,7 @@ def test_user_nonce_is_continuous_despite_epoch_changes(service, mock_users_db): assert new_nonce == 3 -def test_get_all_donors_addresses(service, mock_users_db, make_user_allocation): +def test_get_all_donors_addresses(service, mock_users_db): user1, user2, user3 = mock_users_db context_epoch_1 = get_context(1) context_epoch_2 = get_context(2) @@ -168,9 +140,7 @@ def test_get_all_donors_addresses(service, mock_users_db, make_user_allocation): assert result_epoch_2 == [user3.address] -def test_return_only_not_removed_allocations( - service, mock_users_db, make_user_allocation -): +def test_return_only_not_removed_allocations(service, mock_users_db): user1, user2, _ = mock_users_db context = get_context(1) @@ -183,7 +153,7 @@ def test_return_only_not_removed_allocations( assert result == [user1.address] -def test_get_user_allocation_sum(service, context, mock_users_db, make_user_allocation): +def test_get_user_allocation_sum(service, context, mock_users_db): user1, user2, _ = mock_users_db make_user_allocation(context, user1, allocations=2) make_user_allocation(context, user2, allocations=2) @@ -193,9 +163,7 @@ def test_get_user_allocation_sum(service, context, mock_users_db, make_user_allo assert result == 300 -def test_has_user_allocated_rewards( - service, context, mock_users_db, make_user_allocation -): +def test_has_user_allocated_rewards(service, context, mock_users_db): user1, _, _ = mock_users_db make_user_allocation(context, user1) @@ -204,9 +172,7 @@ def test_has_user_allocated_rewards( assert result is True -def test_has_user_allocated_rewards_returns_false( - service, context, mock_users_db, make_user_allocation -): +def test_has_user_allocated_rewards_returns_false(service, context, mock_users_db): user1, user2, _ = mock_users_db make_user_allocation(context, user1) # other user makes an allocation @@ -218,7 +184,7 @@ def test_has_user_allocated_rewards_returns_false( @freeze_time("2024-03-18 00:00:00") def test_user_allocations_by_timestamp( - service, context, mock_users_db, proposal_accounts, make_user_allocation + service, context, mock_users_db, proposal_accounts ): user1, _, _ = mock_users_db timestamp_before = from_timestamp_s(1710719999) @@ -274,7 +240,7 @@ def test_get_all_allocations_returns_empty_list_when_no_allocations( def test_get_all_allocations_returns_list_of_allocations( - service, context, mock_users_db, make_user_allocation + service, context, mock_users_db ): user1, user2, _ = mock_users_db @@ -292,7 +258,7 @@ def test_get_all_allocations_returns_list_of_allocations( def test_get_all_allocations_does_not_include_revoked_allocations_in_returned_list( - service, context, mock_users_db, make_user_allocation + service, context, mock_users_db ): user1, user2, _ = mock_users_db @@ -312,7 +278,7 @@ def test_get_all_allocations_does_not_include_revoked_allocations_in_returned_li def test_get_all_allocations_does_not_return_allocations_from_previous_and_future_epochs( - service, context, mock_users_db, make_user_allocation + service, context, mock_users_db ): user1, _, _ = mock_users_db context_epoch_1 = get_context(1) @@ -326,7 +292,7 @@ def test_get_all_allocations_does_not_return_allocations_from_previous_and_futur def test_get_all_with_allocation_amount_equal_0( - service, context, mock_users_db, proposal_accounts, make_user_allocation + service, context, mock_users_db, proposal_accounts ): user1, _, _ = mock_users_db allocation_items = [AllocationItem(proposal_accounts[0].address, 0)] @@ -336,14 +302,12 @@ def test_get_all_with_allocation_amount_equal_0( assert service.get_all_allocations(context) == expected_result -def test_get_last_user_allocation_when_no_allocation( - service, context, alice, make_user_allocation -): +def test_get_last_user_allocation_when_no_allocation(service, context, alice): assert service.get_last_user_allocation(context, alice.address) == ([], None) def test_get_last_user_allocation_returns_the_only_allocation( - service, context, mock_users_db, make_user_allocation + service, context, mock_users_db ): user1, _, _ = mock_users_db expected_result = make_user_allocation(context, user1) @@ -355,7 +319,7 @@ def test_get_last_user_allocation_returns_the_only_allocation( def test_get_last_user_allocation_returns_the_only_the_last_allocation( - service, context, mock_users_db, make_user_allocation + service, context, mock_users_db ): user1, _, _ = mock_users_db _ = make_user_allocation(context, user1) @@ -368,7 +332,7 @@ def test_get_last_user_allocation_returns_the_only_the_last_allocation( def test_get_last_user_allocation_returns_stored_metadata( - service, context, mock_users_db, make_user_allocation + service, context, mock_users_db ): user1, _, _ = mock_users_db @@ -395,7 +359,7 @@ def test_get_allocations_by_project_returns_empty_list_when_no_allocations( def test_get_allocations_by_project_returns_list_of_donations_per_project( - service, context, mock_users_db, make_user_allocation + service, context, mock_users_db ): user1, user2, _ = mock_users_db project1, project2 = ( @@ -427,7 +391,7 @@ def test_get_allocations_by_project_returns_list_of_donations_per_project( def test_get_allocations_by_project_with_allocation_amount_equal_0( - service, context, mock_users_db, make_user_allocation + service, context, mock_users_db ): user1, _, _ = mock_users_db project1 = context.projects_details.projects[0]