diff --git a/contracts/SubnetProjectVote.sol b/contracts/SubnetProjectVote.sol deleted file mode 100644 index 166e8b52..00000000 --- a/contracts/SubnetProjectVote.sol +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (C) 2020-2024 SubQuery Pte Ltd authors & contributors -// SPDX-License-Identifier: GPL-3.0-or-later - -pragma solidity 0.8.15; - -import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; -import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; -import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; -import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol'; - -import './interfaces/ISettings.sol'; -import './utils/SQParameter.sol'; - -/** - * @title SubnetProjectVote - * @notice A voting contract that allows users to vote for projects using SQT tokens - * @dev This contract enables users to: - * - Vote for specific projects by sending SQT tokens to the contract - * - Withdraw their votes at any time without any locking period - * - Track voting activity through emitted events - * - * Key features: - * - No validation of projectId existence (external validation responsibility) - * - No time-based restrictions on voting or withdrawing - * - Complete transparency through view functions and events - */ -contract SubnetProjectVote is Initializable, OwnableUpgradeable, SQParameter { - using SafeERC20 for IERC20; - - /// @notice Settings contract to access SQT token address - ISettings public settings; - - /// @notice Mapping from user address to project ID to vote amount - /// @dev userVotes[user][projectId] = amount of SQT tokens voted by user for projectId - mapping(address => mapping(bytes32 => uint256)) public userVotes; - - /// @notice Mapping from project ID to total votes received - /// @dev totalVotes[projectId] = total SQT tokens voted for projectId by all users - mapping(bytes32 => uint256) public totalVotes; - - /// @notice Alternative mapping for project-centric vote queries - /// @dev projectUserVotes[projectId][user] = amount voted by user for projectId - /// This provides gas-efficient queries when iterating through project voters - mapping(bytes32 => mapping(address => uint256)) public projectUserVotes; - - /// @notice Emitted when a user votes SQT tokens for a project - /// @param user The address of the voter - /// @param projectId The unique identifier of the project being voted for - /// @param amount The amount of SQT tokens voted - event Voted(address indexed user, bytes32 indexed projectId, uint256 amount); - - /// @notice Emitted when a user withdraws their votes from a project - /// @param user The address of the voter withdrawing - /// @param projectId The unique identifier of the project being withdrawn from - /// @param amount The amount of SQT tokens withdrawn - event Withdrawn(address indexed user, bytes32 indexed projectId, uint256 amount); - - /** - * @notice Initializes the contract with the settings address - * @dev This function can only be called once due to the initializer modifier - * @param _settings Address of the Settings contract that provides access to other contract addresses - */ - function initialize(address _settings) external initializer { - __Ownable_init(); - settings = ISettings(_settings); - } - - /** - * @notice Vote for a project by transferring SQT tokens to the contract - * @dev Users must approve this contract to spend their SQT tokens before calling this function - * @param projectId The unique identifier of the project to vote for (bytes32 hash) - * @param amount The amount of SQT tokens to vote with (must be > 0) - * - * Requirements: - * - amount must be greater than 0 - * - user must have sufficient SQT token balance - * - user must have approved this contract to spend at least `amount` SQT tokens - * - * Effects: - * - Transfers `amount` SQT tokens from user to this contract - * - Increases user's vote count for the project - * - Increases total vote count for the project - * - Emits Voted event - */ - function vote(bytes32 projectId, uint256 amount) external { - require(amount > 0, 'Amount must be greater than 0'); - - // Get SQT token contract address from settings - IERC20 sqtToken = IERC20(settings.getContractAddress(SQContracts.SQToken)); - // Transfer SQT tokens from user to this contract - sqtToken.safeTransferFrom(msg.sender, address(this), amount); - - // Update vote tracking state - userVotes[msg.sender][projectId] += amount; - totalVotes[projectId] += amount; - projectUserVotes[projectId][msg.sender] += amount; - - emit Voted(msg.sender, projectId, amount); - } - - /** - * @notice Withdraw a specific amount of votes from a project - * @dev Allows partial withdrawal of votes without any time restrictions - * @param projectId The unique identifier of the project to withdraw votes from - * @param amount The amount of SQT tokens to withdraw (must be > 0 and <= user's votes) - * - * Requirements: - * - amount must be greater than 0 - * - user must have at least `amount` votes for the specified project - * - * Effects: - * - Decreases user's vote count for the project - * - Decreases total vote count for the project - * - Transfers `amount` SQT tokens back to the user - * - Emits Withdrawn event - */ - function withdraw(bytes32 projectId, uint256 amount) external { - require(amount > 0, 'Amount must be greater than 0'); - require(userVotes[msg.sender][projectId] >= amount, 'Insufficient votes'); - - // Update vote tracking state - userVotes[msg.sender][projectId] -= amount; - totalVotes[projectId] -= amount; - projectUserVotes[projectId][msg.sender] -= amount; - - // Transfer SQT tokens back to user - IERC20 sqtToken = IERC20(settings.getContractAddress(SQContracts.SQToken)); - sqtToken.safeTransfer(msg.sender, amount); - - emit Withdrawn(msg.sender, projectId, amount); - } - - /** - * @notice Withdraw all votes from a project at once - * @dev Convenience function to withdraw entire voting position for a project - * @param projectId The unique identifier of the project to withdraw all votes from - * - * Requirements: - * - user must have votes for the specified project (amount > 0) - * - * Effects: - * - Sets user's vote count for the project to 0 - * - Decreases total vote count for the project by user's full amount - * - Transfers all user's SQT tokens for this project back to the user - * - Emits Withdrawn event with the full amount - */ - function withdrawAll(bytes32 projectId) external { - uint256 amount = userVotes[msg.sender][projectId]; - require(amount > 0, 'No votes to withdraw'); - - // Reset user's votes for this project to 0 - userVotes[msg.sender][projectId] = 0; - totalVotes[projectId] -= amount; - projectUserVotes[projectId][msg.sender] = 0; - - // Transfer all SQT tokens back to user - IERC20 sqtToken = IERC20(settings.getContractAddress(SQContracts.SQToken)); - sqtToken.safeTransfer(msg.sender, amount); - - emit Withdrawn(msg.sender, projectId, amount); - } - - /** - * @notice Get the amount of votes a user has for a specific project - * @dev View function that doesn't modify state - * @param user The address of the user to query - * @param projectId The unique identifier of the project - * @return The amount of SQT tokens the user has voted for the project - */ - function getUserVotes(address user, bytes32 projectId) external view returns (uint256) { - return userVotes[user][projectId]; - } - - /** - * @notice Get the total amount of votes received by a project - * @dev View function that returns the sum of all votes from all users for a project - * @param projectId The unique identifier of the project - * @return The total amount of SQT tokens voted for the project by all users - */ - function getProjectTotalVotes(bytes32 projectId) external view returns (uint256) { - return totalVotes[projectId]; - } - - /** - * @notice Update the settings contract address - * @dev Only the contract owner can call this function - * @param _settings The new address of the Settings contract - * - * Requirements: - * - Can only be called by the contract owner - * - * Effects: - * - Updates the settings contract address - * - This affects which SQT token contract is used for transfers - */ - function setSettings(address _settings) external onlyOwner { - settings = ISettings(_settings); - } -} diff --git a/publish/testnet.json b/publish/testnet.json index 004b8f0f..283f3c2b 100644 --- a/publish/testnet.json +++ b/publish/testnet.json @@ -217,12 +217,6 @@ "address": "0x45B94e2D1373eC761f8f322c37Fa80ea7eDe61D7", "bytecodeHash": "d38c34ddc8be512acb83f9fa950a52a4a48119c348759db8334c190c4e6296cf", "lastUpdate": "Tue, 16 Apr 2024 03:16:07 GMT" - }, - "SubnetProjectVote": { - "innerAddress": "0x897391d9EBE527429b275cf194D36f9E8826aBcB", - "address": "0x117fB7631b269efefd4c6b2393a8b24B7939CB82", - "bytecodeHash": "d3fec5dfe9a0fae6aafb5dbd1aa6c5db333971d3a8ab50fc3e150f62d7b674ce", - "lastUpdate": "Mon, 18 Aug 2025 07:22:47 GMT" } } } \ No newline at end of file diff --git a/scripts/contracts.ts b/scripts/contracts.ts index fb2b4380..3579b24a 100644 --- a/scripts/contracts.ts +++ b/scripts/contracts.ts @@ -65,8 +65,6 @@ import { L2Vesting, L2Vesting__factory, Airdropper__factory, - SubnetProjectVote, - SubnetProjectVote__factory, } from '../src'; export type Contracts = { @@ -105,7 +103,6 @@ export type Contracts = { sqtRedeem: SQTRedeem; airdropperLite: AirdropperLite; l2Vesting: L2Vesting; - subnetProjectVote: SubnetProjectVote; }; export const UPGRADEBAL_CONTRACTS: Partial< @@ -138,7 +135,6 @@ export const UPGRADEBAL_CONTRACTS: Partial< SQTRedeem: [CONTRACTS.SQTRedeem, SQTRedeem__factory], L2Vesting: [CONTRACTS.L2Vesting, L2Vesting__factory], Airdropper: [CONTRACTS.Airdropper, Airdropper__factory], - SubnetProjectVote: [CONTRACTS.SubnetProjectVote, SubnetProjectVote__factory], }; export type Config = number | string | string[]; diff --git a/scripts/deployContracts.ts b/scripts/deployContracts.ts index c8286dbc..0f8921ba 100644 --- a/scripts/deployContracts.ts +++ b/scripts/deployContracts.ts @@ -58,7 +58,6 @@ import { AirdropperLite, L2Vesting, UniswapPriceOracle, - SubnetProjectVote, } from '../src'; import { Config, ContractConfig, Contracts, UPGRADEBAL_CONTRACTS } from './contracts'; import { l1StandardBridge } from './L1StandardBridge'; @@ -525,17 +524,9 @@ export async function deployContracts( initConfig: [settingsAddress], }); - if (network === 'mainnet') { - //deploy uniswapPriceOracle contract - const uniswapPriceOracle = await deployContract('UniswapPriceOracle', 'child', { - deployConfig: [...config['UniswapPriceOracle']], - }); - } - - //deploy subnetProjectVote contract - const subnetProjectVote = await deployContract('SubnetProjectVote', 'child', { - proxyAdmin, - initConfig: [settingsAddress], + //deploy uniswapPriceOracle contract + const uniswapPriceOracle = await deployContract('UniswapPriceOracle', 'child', { + deployConfig: [...config['UniswapPriceOracle']], }); // Register addresses on settings contract diff --git a/src/contracts.ts b/src/contracts.ts index 8fa57622..e685b79b 100644 --- a/src/contracts.ts +++ b/src/contracts.ts @@ -37,7 +37,6 @@ import L2SQToken from './artifacts/contracts/l2/L2SQToken.sol/L2SQToken.json'; import AirdropperLite from './artifacts/contracts/root/AirdropperLite.sol/AirdropperLite.json'; import L2Vesting from './artifacts/contracts/l2/L2Vesting.sol/L2Vesting.json'; import UniswapPriceOracle from './artifacts/contracts/l2/UniswapPriceOracle.sol/UniswapPriceOracle.json'; -import SubnetProjectVote from './artifacts/contracts/SubnetProjectVote.sol/SubnetProjectVote.json'; export default { Settings, @@ -76,5 +75,4 @@ export default { AirdropperLite, L2Vesting, UniswapPriceOracle, - SubnetProjectVote, }; diff --git a/src/sdk.ts b/src/sdk.ts index 1135a184..91e44ad5 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -32,7 +32,6 @@ import { RewardsBooster, StakingAllocation, L2Vesting, - SubnetProjectVote, } from './typechain'; import { CONTRACT_FACTORY, ContractDeploymentInner, ContractName, FactoryContstructor, SdkOptions } from './types'; import assert from 'assert'; @@ -74,7 +73,6 @@ export class ContractSDK { readonly sqtRedeem!: SQTRedeem; readonly stakingAllocation!: StakingAllocation; readonly l2Vesting!: L2Vesting; - readonly subnetProjectVote!: SubnetProjectVote; constructor( // eslint-disable-next-line no-unused-vars diff --git a/src/types.ts b/src/types.ts index 189fd8c3..92259c01 100644 --- a/src/types.ts +++ b/src/types.ts @@ -44,7 +44,6 @@ import { AirdropperLite__factory, L2Vesting__factory, UniswapPriceOracle__factory, - SubnetProjectVote__factory, } from './typechain'; export type SubqueryNetwork = 'testnet' | 'testnet-mumbai' | 'mainnet' | 'local'; @@ -140,7 +139,6 @@ export const CONTRACT_FACTORY: Record = { AirdropperLite: AirdropperLite__factory, L2Vesting: L2Vesting__factory, UniswapPriceOracle: UniswapPriceOracle__factory, - SubnetProjectVote: SubnetProjectVote__factory, }; export enum SQContracts {