diff --git a/contracts/factory/PoolFactory.sol b/contracts/factory/PoolFactory.sol index 22c4f9c7..6c69178a 100644 --- a/contracts/factory/PoolFactory.sol +++ b/contracts/factory/PoolFactory.sol @@ -204,7 +204,7 @@ contract PoolFactory is IPoolFactory, AbstractPoolFactory { GovPool(payable(poolProxy)).__GovPool_init( govPoolDeps, parameters.verifier, - parameters.onlyBABHolders, + parameters.onlyBABTHolders, babtId, parameters.descriptionURL, parameters.name diff --git a/contracts/interfaces/factory/IPoolFactory.sol b/contracts/interfaces/factory/IPoolFactory.sol index 168c35c5..299810ee 100644 --- a/contracts/interfaces/factory/IPoolFactory.sol +++ b/contracts/interfaces/factory/IPoolFactory.sol @@ -83,7 +83,7 @@ interface IPoolFactory { /// @param tokenSaleParams the token sale proposal parameters /// @param votePowerParams vote power parameters /// @param verifier the address of the verifier - /// @param onlyBABHolders if true, only KYCed users will be allowed to interact with the pool + /// @param onlyBABTHolders if true, only KYCed users will be allowed to interact with the pool /// @param descriptionURL the description of the pool /// @param name the name of the pool struct GovPoolDeployParams { @@ -93,7 +93,7 @@ interface IPoolFactory { TokenSaleProposalDeployParams tokenSaleParams; VotePowerDeployParams votePowerParams; address verifier; - bool onlyBABHolders; + bool onlyBABTHolders; string descriptionURL; string name; } diff --git a/docs/factory/IPoolFactory.md b/docs/factory/IPoolFactory.md index e37856e9..400e6064 100644 --- a/docs/factory/IPoolFactory.md +++ b/docs/factory/IPoolFactory.md @@ -157,7 +157,7 @@ struct GovPoolDeployParams { IPoolFactory.TokenSaleProposalDeployParams tokenSaleParams; IPoolFactory.VotePowerDeployParams votePowerParams; address verifier; - bool onlyBABHolders; + bool onlyBABTHolders; string descriptionURL; string name; } @@ -176,7 +176,7 @@ Parameters: | tokenSaleParams | struct IPoolFactory.TokenSaleProposalDeployParams | the token sale proposal parameters | | votePowerParams | struct IPoolFactory.VotePowerDeployParams | vote power parameters | | verifier | address | the address of the verifier | -| onlyBABHolders | bool | if true, only KYCed users will be allowed to interact with the pool | +| onlyBABTHolders | bool | if true, only KYCed users will be allowed to interact with the pool | | descriptionURL | string | the description of the pool | | name | string | the name of the pool | diff --git a/test/gov/GovPool.test.js b/test/gov/GovPool.test.js index 4ec57b32..9db3a961 100644 --- a/test/gov/GovPool.test.js +++ b/test/gov/GovPool.test.js @@ -42,6 +42,7 @@ const { ValidatorsProposalState, ProposalType, VoteType, + VotePowerType, } = require("../utils/constants"); const Reverter = require("../helpers/reverter"); const truffleAssert = require("truffle-assertions"); @@ -50,11 +51,14 @@ const { impersonate } = require("../helpers/impersonator"); const { assert } = require("chai"); const ethSigUtil = require("@metamask/eth-sig-util"); const { web3 } = require("hardhat"); +const { getBytesLinearPowerInit } = require("../utils/gov-vote-power-utils"); const ContractsRegistry = artifacts.require("ContractsRegistry"); const PoolRegistry = artifacts.require("PoolRegistry"); +const PoolFactory = artifacts.require("PoolFactory"); const CoreProperties = artifacts.require("CoreProperties"); const GovPool = artifacts.require("GovPool"); +const TokenSaleProposal = artifacts.require("TokenSaleProposalMock"); const DistributionProposal = artifacts.require("DistributionProposal"); const GovValidators = artifacts.require("GovValidators"); const GovSettings = artifacts.require("GovSettings"); @@ -83,10 +87,19 @@ const GovPoolOffchainLib = artifacts.require("GovPoolOffchain"); const GovValidatorsCreateLib = artifacts.require("GovValidatorsCreate"); const GovValidatorsVoteLib = artifacts.require("GovValidatorsVote"); const GovValidatorsExecuteLib = artifacts.require("GovValidatorsExecute"); +const GovTokenDeployer = artifacts.require("GovTokenDeployer"); +const TokenSaleProposalCreateLib = artifacts.require("TokenSaleProposalCreate"); +const TokenSaleProposalBuyLib = artifacts.require("TokenSaleProposalBuy"); +const TokenSaleProposalVestingLib = artifacts.require("TokenSaleProposalVesting"); +const TokenSaleProposalWhitelistLib = artifacts.require("TokenSaleProposalWhitelist"); +const TokenSaleProposalClaimLib = artifacts.require("TokenSaleProposalClaim"); +const TokenSaleProposalRecoverLib = artifacts.require("TokenSaleProposalRecover"); ContractsRegistry.numberFormat = "BigNumber"; PoolRegistry.numberFormat = "BigNumber"; +PoolFactory.numberFormat = "BigNumber"; CoreProperties.numberFormat = "BigNumber"; +TokenSaleProposal.numberFormat = "BigNumber"; DistributionProposal.numberFormat = "BigNumber"; GovPool.numberFormat = "BigNumber"; GovValidators.numberFormat = "BigNumber"; @@ -99,19 +112,19 @@ ERC20.numberFormat = "BigNumber"; BABTMock.numberFormat = "BigNumber"; ExecutorTransferMock.numberFormat = "BigNumber"; -describe("GovPool", () => { +describe.only("GovPool", () => { let OWNER; let SECOND; let THIRD; let FOURTH; let FIFTH; let SIXTH; - let FACTORY; let NOTHING; let contractsRegistry; let coreProperties; let poolRegistry; + let poolFactory; let token; let nft; @@ -187,7 +200,6 @@ describe("GovPool", () => { FOURTH = await accounts(3); FIFTH = await accounts(4); SIXTH = await accounts(5); - FACTORY = await accounts(6); NOTHING = await accounts(9); const govUserKeeperViewLib = await GovUserKeeperViewLib.new(); @@ -222,9 +234,28 @@ describe("GovPool", () => { await GovValidators.link(govValidatorsVoteLib); await GovValidators.link(govValidatorsExecuteLib); + const govTokenDeployer = await GovTokenDeployer.new(); + + await PoolFactory.link(govTokenDeployer); + + const tspCreateLib = await TokenSaleProposalCreateLib.new(); + const tspBuyLib = await TokenSaleProposalBuyLib.new(); + const tspVestingLib = await TokenSaleProposalVestingLib.new(); + const tspWhitelistLib = await TokenSaleProposalWhitelistLib.new(); + const tspClaimLib = await TokenSaleProposalClaimLib.new(); + const tspRecoverLib = await TokenSaleProposalRecoverLib.new(); + + await TokenSaleProposal.link(tspCreateLib); + await TokenSaleProposal.link(tspBuyLib); + await TokenSaleProposal.link(tspVestingLib); + await TokenSaleProposal.link(tspWhitelistLib); + await TokenSaleProposal.link(tspClaimLib); + await TokenSaleProposal.link(tspRecoverLib); + contractsRegistry = await ContractsRegistry.new(); const _coreProperties = await CoreProperties.new(); const _poolRegistry = await PoolRegistry.new(); + const _poolFactory = await PoolFactory.new(); dexeExpertNft = await ERC721Expert.new(); babt = await BABTMock.new(); token = await ERC20Mock.new("Mock", "Mock", 18); @@ -248,8 +279,7 @@ describe("GovPool", () => { await contractsRegistry.addProxyContract(await contractsRegistry.CORE_PROPERTIES_NAME(), _coreProperties.address); await contractsRegistry.addProxyContract(await contractsRegistry.POOL_REGISTRY_NAME(), _poolRegistry.address); - - await contractsRegistry.addContract(await contractsRegistry.POOL_FACTORY_NAME(), FACTORY); + await contractsRegistry.addProxyContract(await contractsRegistry.POOL_FACTORY_NAME(), _poolFactory.address); await contractsRegistry.addContract(await contractsRegistry.TREASURY_NAME(), ETHER_ADDR); @@ -258,6 +288,7 @@ describe("GovPool", () => { coreProperties = await CoreProperties.at(await contractsRegistry.getCorePropertiesContract()); poolRegistry = await PoolRegistry.at(await contractsRegistry.getPoolRegistryContract()); + poolFactory = await PoolFactory.at(await contractsRegistry.getPoolFactoryContract()); await coreProperties.__CoreProperties_init(DEFAULT_CORE_PROPERTIES); await poolRegistry.__OwnablePoolContractsRegistry_init(); @@ -265,6 +296,7 @@ describe("GovPool", () => { await contractsRegistry.injectDependencies(await contractsRegistry.CORE_PROPERTIES_NAME()); await contractsRegistry.injectDependencies(await contractsRegistry.POOL_REGISTRY_NAME()); + await contractsRegistry.injectDependencies(await contractsRegistry.POOL_FACTORY_NAME()); await reverter.snapshot(); }); @@ -272,84 +304,55 @@ describe("GovPool", () => { afterEach(reverter.revert); async function deployPool(poolParams) { - const NAME = await poolRegistry.GOV_POOL_NAME(); - const settings = await GovSettings.new(); const validators = await GovValidators.new(); const userKeeper = await GovUserKeeper.new(); + const tsp = await TokenSaleProposal.new(); const dp = await DistributionProposal.new(); const expertNft = await ERC721Expert.new(); const votePower = await LinearPower.new(); const govPool = await GovPool.new(); const nftMultiplier = await ERC721Multiplier.new(); - await settings.__GovSettings_init( - govPool.address, - validators.address, - userKeeper.address, - poolParams.settingsParams.proposalSettings, - [...poolParams.settingsParams.additionalProposalExecutors, dp.address] - ); - - await validators.__GovValidators_init( - poolParams.validatorsParams.name, - poolParams.validatorsParams.symbol, + await poolRegistry.setNewImplementations( [ - poolParams.validatorsParams.proposalSettings.duration, - poolParams.validatorsParams.proposalSettings.executionDelay, - poolParams.validatorsParams.proposalSettings.quorum, + await poolRegistry.GOV_POOL_NAME(), + await poolRegistry.SETTINGS_NAME(), + await poolRegistry.VALIDATORS_NAME(), + await poolRegistry.USER_KEEPER_NAME(), + await poolRegistry.DISTRIBUTION_PROPOSAL_NAME(), + await poolRegistry.TOKEN_SALE_PROPOSAL_NAME(), + await poolRegistry.EXPERT_NFT_NAME(), + await poolRegistry.NFT_MULTIPLIER_NAME(), + await poolRegistry.LINEAR_POWER_NAME(), + await poolRegistry.POLYNOMIAL_POWER_NAME(), ], - poolParams.validatorsParams.validators, - poolParams.validatorsParams.balances - ); - await userKeeper.__GovUserKeeper_init( - poolParams.userKeeperParams.tokenAddress, - poolParams.userKeeperParams.nftAddress, - poolParams.userKeeperParams.totalPowerInTokens, - poolParams.userKeeperParams.nftsTotalSupply - ); - - await nftMultiplier.__ERC721Multiplier_init("Mock Multiplier Nft", "MCKMULNFT"); - await dp.__DistributionProposal_init(govPool.address); - await expertNft.__ERC721Expert_init("Mock Expert Nft", "MCKEXPNFT"); - await votePower.__LinearPower_init(); - await govPool.__GovPool_init( [ + govPool.address, settings.address, - userKeeper.address, validators.address, + userKeeper.address, + dp.address, + tsp.address, expertNft.address, nftMultiplier.address, votePower.address, - ], - OWNER, - poolParams.onlyBABTHolders, - poolParams.deployerBABTid, - poolParams.descriptionURL, - poolParams.name + votePower.address, + ] ); - await settings.transferOwnership(govPool.address); - await validators.transferOwnership(govPool.address); - await userKeeper.transferOwnership(govPool.address); - await expertNft.transferOwnership(govPool.address); - await votePower.transferOwnership(govPool.address); - - await poolRegistry.addProxyPool(NAME, govPool.address, { - from: FACTORY, - }); - - await poolRegistry.injectDependenciesToExistingPools(NAME, 0, 10); + const tx = await poolFactory.deployGovPool(poolParams); + const args = tx.receipt.logs[0].args; return { - settings: settings, - validators: validators, - userKeeper: userKeeper, - distributionProposal: dp, - expertNft: expertNft, - votePower: votePower, - govPool: govPool, - nftMultiplier: nftMultiplier, + settings: await GovSettings.at(args.govPoolDeps.settingsAddress), + validators: await GovValidators.at(args.govPoolDeps.validatorsAddress), + userKeeper: await GovUserKeeper.at(args.govPoolDeps.userKeeperAddress), + distributionProposal: await DistributionProposal.at(args.distributionProposal), + expertNft: await ERC721Expert.at(args.govPoolDeps.expertNftAddress), + votePower: await VotePowerMock.at(args.govPoolDeps.votePowerAddress), + govPool: await GovPool.at(args.govPool), + nftMultiplier: await ERC721Multiplier.at(args.govPoolDeps.nftMultiplierAddress), }; } @@ -414,25 +417,6 @@ describe("GovPool", () => { }, executorDescription: "validators", }, - { - earlyCompletion: false, - delegatedVotingAllowed: true, - validatorsVote: true, - duration: 600, - durationValidators: 800, - quorum: PRECISION.times("71").toFixed(), - quorumValidators: PRECISION.times("100").toFixed(), - minVotesForVoting: wei("20"), - minVotesForCreating: wei("3"), - executionDelay: 0, - rewardsInfo: { - rewardToken: rewardToken.address, - creationReward: wei("10"), - executionReward: wei("5"), - voteRewardsCoefficient: PRECISION.toFixed(), - }, - executorDescription: "DP", - }, ], additionalProposalExecutors: [], }, @@ -453,9 +437,26 @@ describe("GovPool", () => { totalPowerInTokens: wei("33000"), nftsTotalSupply: 33, }, + tokenSaleParams: { + tiersParams: [], + whitelistParams: [], + tokenParams: { + name: "", + symbol: "", + users: [], + saleAmount: 0, + cap: 0, + mintedTotal: 0, + amounts: [], + }, + }, + votePowerParams: { + voteType: VotePowerType.LINEAR_VOTES, + initData: getBytesLinearPowerInit(), + presetAddress: ZERO_ADDR, + }, verifier: OWNER, onlyBABTHolders: false, - deployerBABTid: 1, descriptionURL: "example.com", name: "Pool name", }; @@ -567,7 +568,7 @@ describe("GovPool", () => { await executeValidatorProposal( [ [settings.address, 0, getBytesAddSettings([GOV_POOL_SETTINGS])], - [settings.address, 0, getBytesChangeExecutors([govPool.address, settings.address], [4, 4])], + [settings.address, 0, getBytesChangeExecutors([govPool.address, settings.address], [3, 3])], ], [] ); @@ -614,7 +615,7 @@ describe("GovPool", () => { ], OWNER, POOL_PARAMETERS.onlyBABTHolders, - POOL_PARAMETERS.deployerBABTid, + 1, POOL_PARAMETERS.descriptionURL, POOL_PARAMETERS.name ), @@ -1522,7 +1523,7 @@ describe("GovPool", () => { [ [settings.address, 0, getBytesAddSettings([NEW_SETTINGS])], - [settings.address, 0, getBytesChangeExecutors([THIRD], [4])], + [settings.address, 0, getBytesChangeExecutors([THIRD], [3])], ], [] ); @@ -3005,7 +3006,7 @@ describe("GovPool", () => { assert.equal((await govPool.getWithdrawableAssets(OWNER)).tokens.toFixed(), wei("1000")); - const addedSettings = await settings.settings(4); + const addedSettings = await settings.settings(3); assert.isTrue(addedSettings.earlyCompletion); assert.isFalse(addedSettings.delegatedVotingAllowed); @@ -3098,7 +3099,7 @@ describe("GovPool", () => { const executorTransfer = await ExecutorTransferMock.new(govPool.address, token.address); const addSettingsBytes = getBytesAddSettings([NEW_SETTINGS]); - const changeExecutorBytes = getBytesChangeExecutors([executorTransfer.address], [4]); + const changeExecutorBytes = getBytesChangeExecutors([executorTransfer.address], [3]); assert.equal(await govPool.getProposalState(1), ProposalState.Undefined); @@ -3122,7 +3123,7 @@ describe("GovPool", () => { assert.equal(await govPool.getProposalState(1), ProposalState.ExecutedFor); assert.equal((await validators.getProposalState(1, false)).toFixed(), ValidatorsProposalState.Executed); - assert.equal(toBN(await settings.executorToSettings(executorTransfer.address)).toFixed(), "4"); + assert.equal(toBN(await settings.executorToSettings(executorTransfer.address)).toFixed(), "3"); const bytesExecute = getBytesExecute(); const bytesApprove = getBytesApprove(executorTransfer.address, wei("99")); @@ -3502,7 +3503,7 @@ describe("GovPool", () => { await govPool.execute(1); - const changeExecutorBytes = getBytesChangeExecutors([userKeeper.address], [4]); + const changeExecutorBytes = getBytesChangeExecutors([userKeeper.address], [3]); await govPool.createProposal("example.com", [[settings.address, 0, changeExecutorBytes]], []); await govPool.vote(2, true, wei("1000"), []); @@ -3858,8 +3859,9 @@ describe("GovPool", () => { it("should claim reward properly if nft multiplier has been set", async () => { await setNftMultiplierAddress(nftMultiplier.address); - await nftMultiplier.mint(OWNER, PRECISION.times("2.5"), 1000); - await nftMultiplier.transferOwnership(govPool.address); + await impersonate(govPool.address); + await nftMultiplier.mint(OWNER, PRECISION.times("2.5"), 1000, { from: govPool.address }); + await nftMultiplier.lock(1); const bytes = getBytesAddSettings([NEW_SETTINGS]); @@ -5141,4 +5143,6 @@ describe("GovPool", () => { }); }); }); + + describe("pool with SphereX feature", () => {}); });