diff --git a/integration_test/dapp_tests/configs/nftConfig.json b/integration_test/dapp_tests/configs/nftConfig.json new file mode 100644 index 000000000..daec096b4 --- /dev/null +++ b/integration_test/dapp_tests/configs/nftConfig.json @@ -0,0 +1,6 @@ +{ + "marketplace": "0x305E8dc769aae003c17fB08b9cc9108Cb4630E79", + "erc721token": "0x8Ee23935ca017dbe78Fc72b74C90F9FCF4e2f9E5", + "cw721Address": "sei1tpz0rk984996x87sgmzr0te7n4p2j9r8vq7pqq0psf0l7642ze2qx9wzsf", + "erc721PointerToken": "0xC88F617fa5943466437f7ce03aaE8779ae083847" +} \ No newline at end of file diff --git a/integration_test/dapp_tests/configs/steakConfig.json b/integration_test/dapp_tests/configs/steakConfig.json new file mode 100644 index 000000000..eb3775ef1 --- /dev/null +++ b/integration_test/dapp_tests/configs/steakConfig.json @@ -0,0 +1,5 @@ +{ + "hubAddress": "sei1dynepqqjm6u4prcvdyh5qlhrglld78xy7pa4w05gq9vas4ws3e4q7dmyff", + "tokenAddress": "sei1v7gfan5kjry9aqs2l6z0smx4cj2kgcz5ngmd09caex5y7ucr9yqq6pth9d", + "pointerAddress": "0x505868BB5Babd68D84D96bbc0851062C6cF0619a" +} \ No newline at end of file diff --git a/integration_test/dapp_tests/configs/uniswapConfig.json b/integration_test/dapp_tests/configs/uniswapConfig.json new file mode 100644 index 000000000..3a597d345 --- /dev/null +++ b/integration_test/dapp_tests/configs/uniswapConfig.json @@ -0,0 +1,10 @@ +{ + "manager": "0xcE11491995E05b947820836aecE9D7A5Fcdaeb01", + "router": "0x0c086805476d29b306ffF178B53176565F880893", + "erc20TokenFactory": "0x7e3378bcEad49Bbfc8D9024657c942d44f1A1a94", + "erc20cw20": "0x7E7095dfB469A39CF6C67554A8896314D6B0567F", + "weth9": "0x5cA05f8eA1a25d74eBD222a9Ea3730c82B4082A4", + "token": "0xB73a15C476A9D14d57162472527e3FbFdF21dE3F", + "tokenFactoryDenom": "factory/sei1ak5ztcchehv2gy64yxpcdnftepnacvwgxwwfzw/dappTests1727707705418", + "cw20Address": "sei127nvmtnn3tkt6xxgss2z4n0exgm043sc0e2na5lca7h3n4qxs8us4rykxp" +} \ No newline at end of file diff --git a/integration_test/dapp_tests/constants.js b/integration_test/dapp_tests/constants.js index aafad4d58..4434eb8cc 100644 --- a/integration_test/dapp_tests/constants.js +++ b/integration_test/dapp_tests/constants.js @@ -1,16 +1,25 @@ const rpcUrls = { + "seilocal": "http://127.0.0.1:26657", "testnet": "https://rpc-testnet.sei-apis.com", - "devnet": "https://rpc-arctic-1.sei-apis.com" + "devnet": "https://rpc-arctic-1.sei-apis.com", + "devnetFastTrack": "https://rpc-arctic-1.sei-apis.com", + "seiClusterFastTrack": "" } const evmRpcUrls = { + "seilocal": "http://127.0.0.1:8545", "testnet": "https://evm-rpc-testnet.sei-apis.com", - "devnet": "https://evm-rpc-arctic-1.sei-apis.com" + "devnet": "https://evm-rpc-arctic-1.sei-apis.com", + "devnetFastTrack": "https://evm-rpc-arctic-1.sei-apis.com", + "seiClusterFastTrack": "" } const chainIds = { + "seilocal": "sei-chain", "testnet": "atlantic-2", - "devnet": "arctic-1" + "devnet": "arctic-1", + "devnetFastTrack": "arctic-1", + "seiClusterFastTrack":"", } module.exports = { diff --git a/integration_test/dapp_tests/hardhat.config.js b/integration_test/dapp_tests/hardhat.config.js index c2e5a8496..a9e5db2c3 100644 --- a/integration_test/dapp_tests/hardhat.config.js +++ b/integration_test/dapp_tests/hardhat.config.js @@ -25,6 +25,15 @@ module.exports = { count: 1 }, }, + seiClusterFastTrack: { + url: "http://127.0.0.1:8545", + accounts: { + mnemonic: process.env.DAPP_TESTS_MNEMONIC, + path: "m/44'/118'/0'/0/0", + initialIndex: 0, + count: 1 + }, + }, testnet: { url: "https://evm-rpc-testnet.sei-apis.com", accounts: { @@ -43,5 +52,14 @@ module.exports = { count: 1 }, }, + devnetFastTrack: { + url: "https://evm-rpc-arctic-1.sei-apis.com", + accounts: { + mnemonic: process.env.DAPP_TESTS_MNEMONIC, + path: "m/44'/118'/0'/0/0", + initialIndex: 0, + count: 1 + }, + }, }, }; diff --git a/integration_test/dapp_tests/nftMarketplace/nftMarketplaceTests.js b/integration_test/dapp_tests/nftMarketplace/nftMarketplaceTests.js index 3b1fde0df..678ee9641 100644 --- a/integration_test/dapp_tests/nftMarketplace/nftMarketplaceTests.js +++ b/integration_test/dapp_tests/nftMarketplace/nftMarketplaceTests.js @@ -1,66 +1,39 @@ const { expect } = require("chai"); const hre = require("hardhat"); -const {sendFunds, deployEthersContract, estimateAndCall, deployCw721WithPointer, setupAccountWithMnemonic, - mintCw721 +const { + sendFunds, estimateAndCall, mintCw721, deployAndReturnContractsForNftTests, + queryLatestNftIds, setDaemonConfig } = require("../utils"); -const { fundAddress, getSeiAddress, execute } = require("../../../contracts/test/lib.js"); -const {evmRpcUrls, chainIds, rpcUrls} = require("../constants"); +const { getSeiAddress } = require("../../../contracts/test/lib.js"); const testChain = process.env.DAPP_TEST_ENV; -console.log("testChain", testChain); describe("NFT Marketplace", function () { - let marketplace, deployer, erc721token, erc721PointerToken, cw721Address, originalSeidConfig; + let marketplace, deployer, erc721token, erc721PointerToken, cw721Address, originalSeidConfig, nftId1; before(async function () { const accounts = hre.config.networks[testChain].accounts const deployerWallet = hre.ethers.Wallet.fromMnemonic(accounts.mnemonic, accounts.path); deployer = deployerWallet.connect(hre.ethers.provider); - - const seidConfig = await execute('seid config'); - originalSeidConfig = JSON.parse(seidConfig); - - if (testChain === 'seilocal') { - await fundAddress(deployer.address, amount="2000000000000000000000"); - } else { - // Set default seid config to the specified rpc url. - await execute(`seid config chain-id ${chainIds[testChain]}`) - await execute(`seid config node ${rpcUrls[testChain]}`) - } - - await execute(`seid config keyring-backend test`) - - await sendFunds('0.01', deployer.address, deployer) - await setupAccountWithMnemonic("dapptest", accounts.mnemonic, deployer); - - // Deploy MockNFT - const erc721ContractArtifact = await hre.artifacts.readArtifact("MockERC721"); - erc721token = await deployEthersContract("MockERC721", erc721ContractArtifact.abi, erc721ContractArtifact.bytecode, deployer, ["MockERC721", "MKTNFT"]) - - const numNftsToMint = 50 - await estimateAndCall(erc721token, "batchMint", [deployer.address, numNftsToMint]); - - // Deploy CW721 token with ERC721 pointer - const time = Date.now().toString(); + originalSeidConfig = setDaemonConfig(testChain); const deployerSeiAddr = await getSeiAddress(deployer.address); - const cw721Details = await deployCw721WithPointer(deployerSeiAddr, deployer, time, evmRpcUrls[testChain]) - erc721PointerToken = cw721Details.pointerContract; - cw721Address = cw721Details.cw721Address; - console.log("CW721 Address", cw721Address); + ({ + marketplace, + erc721token, + cw721Address, + erc721PointerToken + } = await deployAndReturnContractsForNftTests(deployer, testChain, accounts)); + nftId1 = (await queryLatestNftIds(cw721Address)) + 1; const numCwNftsToMint = 2; - for (let i = 1; i <= numCwNftsToMint; i++) { - await mintCw721(cw721Address, deployerSeiAddr, i) + for (let i = nftId1; i <= nftId1 + numCwNftsToMint; i++) { + await mintCw721(cw721Address, deployerSeiAddr, i); + console.log('nfts minted'); } - const cwbal = await erc721PointerToken.balanceOf(deployer.address); - expect(cwbal).to.equal(numCwNftsToMint) - - const nftMarketplaceArtifact = await hre.artifacts.readArtifact("NftMarketplace"); - marketplace = await deployEthersContract("NftMarketplace", nftMarketplaceArtifact.abi, nftMarketplaceArtifact.bytecode, deployer) }) describe("Orders", function () { - async function testNFTMarketplaceOrder(buyer, seller, nftContract, nftId="", expectTransferFail=false) { + async function testNFTMarketplaceOrder(buyer, seller, nftContract, nftId = "", expectTransferFail = false) { let tokenId; // If nftId is manually supplied (for pointer contract), ensure that deployer owns that token. if (nftId) { @@ -117,7 +90,7 @@ describe("NFT Marketplace", function () { const newSellerNftbalance = await nftContract.balanceOf(seller.address); expect(Number(newSellerNftbalance)).to.be.lessThan(Number(sellerNftbalance), "NFT should have been transferred from the seller.") - nftOwner = await nftContract.ownerOf(tokenId); + let nftOwner = await nftContract.ownerOf(tokenId); expect(nftOwner).to.equal(buyer.address, "NFT should have been transferred to the buyer."); } @@ -150,7 +123,7 @@ describe("NFT Marketplace", function () { const buyer = buyerWallet.connect(hre.ethers.provider); await sendFunds("0.5", buyer.address, deployer) await sendFunds('0.01', buyer.address, buyer) - await testNFTMarketplaceOrder(buyer, deployer, erc721PointerToken, '1'); + await testNFTMarketplaceOrder(buyer, deployer, erc721PointerToken, `${nftId1}`); }); it("Currently does not allow listing or buying erc721 pointer by unassociated users", async function () { @@ -164,15 +137,15 @@ describe("NFT Marketplace", function () { const buyer = buyerWallet.connect(hre.ethers.provider); await sendFunds("0.5", buyer.address, deployer) - await testNFTMarketplaceOrder(buyer, seller, erc721PointerToken, '2', true); + await testNFTMarketplaceOrder(buyer, seller, erc721PointerToken, `${nftId1 + 1}`, true); }); }) after(async function () { - // Set the chain back to regular state - console.log("Resetting") - await execute(`seid config chain-id ${originalSeidConfig["chain-id"]}`) - await execute(`seid config node ${originalSeidConfig["node"]}`) - await execute(`seid config keyring-backend ${originalSeidConfig["keyring-backend"]}`) + // Set the chain back to regular state + console.log("Resetting") + await execute(`seid config chain-id ${originalSeidConfig["chain-id"]}`) + await execute(`seid config node ${originalSeidConfig["node"]}`) + await execute(`seid config keyring-backend ${originalSeidConfig["keyring-backend"]}`) }) }) diff --git a/integration_test/dapp_tests/steak/SteakTests.js b/integration_test/dapp_tests/steak/SteakTests.js index 6f7786da6..b0bd8f036 100644 --- a/integration_test/dapp_tests/steak/SteakTests.js +++ b/integration_test/dapp_tests/steak/SteakTests.js @@ -1,206 +1,119 @@ const { - storeWasm, - deployErc20PointerForCw20, - ABI, - getEvmAddress, - fundSeiAddress, - associateKey, - execute, - isDocker, + getEvmAddress, + execute, } = require("../../../contracts/test/lib.js"); const { - getValidators, - instantiateHubContract, - bond, - addAccount, - queryTokenBalance, - unbond, - transferTokens, - setupAccountWithMnemonic, - sendFunds + bond, + queryTokenBalance, + unbond, + transferTokens, } = require("../utils.js"); -const { expect } = require("chai"); -const { v4: uuidv4 } = require("uuid"); +const {expect} = require("chai"); +const {v4: uuidv4} = require("uuid"); const hre = require("hardhat"); -const {chainIds, rpcUrls, evmRpcUrls} = require("../constants"); -const path = require("path"); +const { + setupAccount, + deployAndReturnContractsForSteakTests, setDaemonConfig +} = require("../utils"); const testChain = process.env.DAPP_TEST_ENV; describe("Steak", async function () { - let owner; - let hubAddress; - let tokenAddress; - let tokenPointer; - let originalSeidConfig; - - async function setupAccount(baseName, associate = true, amount="100000000000", denom="usei", funder='admin') { - const uniqueName = `${baseName}-${uuidv4()}`; - - const account = await addAccount(uniqueName); - await fundSeiAddress(account.address, amount, denom, funder); - if (associate) { - await associateKey(account.address); - } - - return account; - } - - async function deployContracts(ownerAddress) { - // Store CW20 token wasm - const STEAK_TOKEN_WASM = (await isDocker()) ? '../integration_test/dapp_tests/steak/contracts/steak_token.wasm' : path.resolve(__dirname, '../steak/contracts/steak_token.wasm') - const tokenCodeId = await storeWasm(STEAK_TOKEN_WASM, ownerAddress); - - // Store Hub contract - const STEAK_HUB_WASM = (await isDocker()) ? '../integration_test/dapp_tests/steak/contracts/steak_hub.wasm' : path.resolve(__dirname, '../steak/contracts/steak_hub.wasm') - const hubCodeId = await storeWasm(STEAK_HUB_WASM, ownerAddress); - - // Instantiate hub and token contracts - const validators = await getValidators(); - const instantiateMsg = { - cw20_code_id: parseInt(tokenCodeId), - owner: ownerAddress, - name: "Steak", - symbol: "STEAK", - decimals: 6, - epoch_period: 259200, - unbond_period: 1814400, - validators: validators.slice(0, 3), - }; - const contractAddresses = await instantiateHubContract( - hubCodeId, - ownerAddress, - instantiateMsg, - "steakhub" - ); - - // Deploy pointer for token contract - const pointerAddr = await deployErc20PointerForCw20( - hre.ethers.provider, - contractAddresses.tokenContract, - 10, - ownerAddress, - evmRpcUrls[testChain] - ); - - const tokenPointer = new hre.ethers.Contract( - pointerAddr, - ABI.ERC20, - hre.ethers.provider - ); - - return { - hubAddress: contractAddresses.hubContract, - tokenAddress: contractAddresses.tokenContract, - tokenPointer, - }; - } - - async function testBonding(address, amount) { - const initialBalance = await queryTokenBalance(tokenAddress, address); - expect(initialBalance).to.equal("0"); - - await bond(hubAddress, address, amount); - const tokenBalance = await queryTokenBalance(tokenAddress, address); - expect(tokenBalance).to.equal(`${amount}`); - } - - async function testUnbonding(address, amount) { - const initialBalance = await queryTokenBalance(tokenAddress, address); - const response = await unbond(hubAddress, tokenAddress, address, amount); - expect(response.code).to.equal(0); - - // Balance should be updated - const tokenBalance = await queryTokenBalance(tokenAddress, address); - expect(tokenBalance).to.equal(`${Number(initialBalance) - amount}`); - } - - before(async function () { - - const seidConfig = await execute('seid config'); - originalSeidConfig = JSON.parse(seidConfig); - - // Set up the owner account - if (testChain === 'seilocal') { - owner = await setupAccount("steak-owner"); - } else { - // Set default seid config to the specified rpc url. - await execute(`seid config chain-id ${chainIds[testChain]}`) - await execute(`seid config node ${rpcUrls[testChain]}`) - - const accounts = hre.config.networks[testChain].accounts - const deployerWallet = hre.ethers.Wallet.fromMnemonic(accounts.mnemonic, accounts.path); - const deployer = deployerWallet.connect(hre.ethers.provider) - - await sendFunds('0.01', deployer.address, deployer) - // Set the config keyring to 'test' since we're using the key added to test from here. - owner = await setupAccountWithMnemonic("steak-owner", accounts.mnemonic, deployer) + let owner; + let hubAddress; + let tokenAddress; + let tokenPointer; + let originalSeidConfig; + + async function testBonding(address, amount) { + const initialBalance = await queryTokenBalance(tokenAddress, address); + await bond(hubAddress, address, amount); + const tokenBalance = await queryTokenBalance(tokenAddress, address); + const expectedBalance = Number(initialBalance) + amount; + expect(tokenBalance).to.equal(`${expectedBalance}`); } - await execute(`seid config keyring-backend test`); - - // Store and deploy contracts - ({ hubAddress, tokenAddress, tokenPointer } = await deployContracts( - owner.address - )); - }); + async function testUnbonding(address, amount) { + const initialBalance = await queryTokenBalance(tokenAddress, address); + const response = await unbond(hubAddress, tokenAddress, address, amount); + expect(response.code).to.equal(0); - describe("Bonding and unbonding", async function () { - it("Associated account should be able to bond and unbond", async function () { - const amount = 1000000; - await testBonding(owner.address, amount); - - // Verify that address is associated - const evmAddress = await getEvmAddress(owner.address); - expect(evmAddress).to.not.be.empty; - - // Check pointer balance - const pointerBalance = await tokenPointer.balanceOf(evmAddress); - expect(pointerBalance).to.equal(`${amount}`); + // Balance should be updated + const tokenBalance = await queryTokenBalance(tokenAddress, address); + expect(tokenBalance).to.equal(`${Number(initialBalance) - amount}`); + } - await testUnbonding(owner.address, 500000); + before(async function () { + originalSeidConfig = await setDaemonConfig(testChain); + const accounts = hre.config.networks[testChain].accounts + const deployerWallet = hre.ethers.Wallet.fromMnemonic(accounts.mnemonic, accounts.path); + const deployer = deployerWallet.connect(hre.ethers.provider); + ({ + hubAddress, + tokenAddress, + tokenPointer, + owner + } = await deployAndReturnContractsForSteakTests(deployer, testChain, accounts)) }); - it("Unassociated account should be able to bond", async function () { - const unassociatedAccount = await setupAccount("unassociated", false, '2000000', 'usei', owner.address); - // Verify that account is not associated yet - const initialEvmAddress = await getEvmAddress( - unassociatedAccount.address - ); - expect(initialEvmAddress).to.be.empty; - - await testBonding(unassociatedAccount.address, 1000000); - - // Account should now be associated - const evmAddress = await getEvmAddress(unassociatedAccount.address); - expect(evmAddress).to.not.be.empty; - - // Send tokens to a new unassociated account - const newUnassociatedAccount = await setupAccount("unassociated", false, '2000000', 'usei', owner.address); - const transferAmount = 500000; - await transferTokens( - tokenAddress, - unassociatedAccount.address, - newUnassociatedAccount.address, - transferAmount - ); - const tokenBalance = await queryTokenBalance( - tokenAddress, - newUnassociatedAccount.address - ); - expect(tokenBalance).to.equal(`${transferAmount}`); - - // Try unbonding on unassociated account - await testUnbonding(newUnassociatedAccount.address, transferAmount / 2); + describe("Bonding and unbonding", async function () { + it("Associated account should be able to bond and unbond", async function () { + const amount = 1000000; + const evmAddress = await getEvmAddress(owner.address); + const pointerInitialBalance = await tokenPointer.balanceOf(evmAddress); + await testBonding(owner.address, amount); + + // Verify that address is associated + expect(evmAddress).to.not.be.empty; + + // Check pointer balance + const pointerBalance = await tokenPointer.balanceOf(evmAddress); + const expectedAfterBalance = Number(pointerInitialBalance) + amount; + expect(pointerBalance).to.equal(`${expectedAfterBalance}`); + + await testUnbonding(owner.address, 500000); + }); + + it("Unassociated account should be able to bond", async function () { + const unassociatedAccount = await setupAccount("unassociated", false, '2000000', 'usei', owner.address); + // Verify that account is not associated yet + const initialEvmAddress = await getEvmAddress( + unassociatedAccount.address + ); + expect(initialEvmAddress).to.be.empty; + + await testBonding(unassociatedAccount.address, 1000000); + + // Account should now be associated + const evmAddress = await getEvmAddress(unassociatedAccount.address); + expect(evmAddress).to.not.be.empty; + + // Send tokens to a new unassociated account + const newUnassociatedAccount = await setupAccount("unassociated", false, '2000000', 'usei', owner.address); + const transferAmount = 500000; + await transferTokens( + tokenAddress, + unassociatedAccount.address, + newUnassociatedAccount.address, + transferAmount + ); + const tokenBalance = await queryTokenBalance( + tokenAddress, + newUnassociatedAccount.address + ); + expect(tokenBalance).to.equal(`${transferAmount}`); + + // Try unbonding on unassociated account + await testUnbonding(newUnassociatedAccount.address, transferAmount / 2); + }); }); - }); - - after(async function () { - // Set the chain back to regular state - console.log(`Resetting to ${originalSeidConfig}`) - await execute(`seid config chain-id ${originalSeidConfig["chain-id"]}`) - await execute(`seid config node ${originalSeidConfig["node"]}`) - await execute(`seid config keyring-backend ${originalSeidConfig["keyring-backend"]}`) - }) + + after(async function () { + // Set the chain back to regular state + console.log(`Resetting to ${originalSeidConfig}`) + await execute(`seid config chain-id ${originalSeidConfig["chain-id"]}`) + await execute(`seid config node ${originalSeidConfig["node"]}`) + await execute(`seid config keyring-backend ${originalSeidConfig["keyring-backend"]}`) + }) }); diff --git a/integration_test/dapp_tests/uniswap/uniswapTest.js b/integration_test/dapp_tests/uniswap/uniswapTest.js index 347bb62f0..adfa810d9 100755 --- a/integration_test/dapp_tests/uniswap/uniswapTest.js +++ b/integration_test/dapp_tests/uniswap/uniswapTest.js @@ -1,18 +1,27 @@ const hre = require("hardhat"); // Require Hardhat Runtime Environment -const { abi: WETH9_ABI, bytecode: WETH9_BYTECODE } = require("@uniswap/v2-periphery/build/WETH9.json"); -const { abi: FACTORY_ABI, bytecode: FACTORY_BYTECODE } = require("@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json"); -const { abi: DESCRIPTOR_ABI, bytecode: DESCRIPTOR_BYTECODE } = require("@uniswap/v3-periphery/artifacts/contracts/libraries/NFTDescriptor.sol/NFTDescriptor.json"); -const { abi: MANAGER_ABI, bytecode: MANAGER_BYTECODE } = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json"); -const { abi: SWAP_ROUTER_ABI, bytecode: SWAP_ROUTER_BYTECODE } = require("@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json"); -const {exec} = require("child_process"); -const { fundAddress, createTokenFactoryTokenAndMint, deployErc20PointerNative, execute, getSeiAddress, queryWasm, getSeiBalance, isDocker, ABI } = require("../../../contracts/test/lib.js"); -const { deployTokenPool, supplyLiquidity, deployCw20WithPointer, deployEthersContract, sendFunds, pollBalance, setupAccountWithMnemonic, estimateAndCall } = require("../utils") -const { rpcUrls, chainIds, evmRpcUrls} = require("../constants") -const { expect } = require("chai"); +const { + execute, + getSeiAddress, + queryWasm, + getSeiBalance, +} = require("../../../contracts/test/lib.js"); +const { + deployTokenPool, + supplyLiquidity, + sendFunds, + pollBalance, + estimateAndCall, + deployAndReturnUniswapContracts, setDaemonConfig +} = require("../utils") +const {expect} = require("chai"); const testChain = process.env.DAPP_TEST_ENV; +/** + * Deploy uniswap contracts => + */ + describe("Uniswap Test", function () { let weth9; let token; @@ -26,106 +35,40 @@ describe("Uniswap Test", function () { let deployer; let user; let originalSeidConfig; + before(async function () { - const accounts = hre.config.networks[testChain].accounts + originalSeidConfig = setDaemonConfig(testChain); + const accounts = hre.config.networks[testChain].accounts; const deployerWallet = hre.ethers.Wallet.fromMnemonic(accounts.mnemonic, accounts.path); deployer = deployerWallet.connect(hre.ethers.provider); - const seidConfig = await execute('seid config'); - originalSeidConfig = JSON.parse(seidConfig); - - if (testChain === 'seilocal') { - await fundAddress(deployer.address, amount="2000000000000000000000"); - } else { - // Set default seid config to the specified rpc url. - await execute(`seid config chain-id ${chainIds[testChain]}`) - await execute(`seid config node ${rpcUrls[testChain]}`) - } - - // Set the config keyring to 'test' since we're using the key added to test from here. - await execute(`seid config keyring-backend test`) - - await sendFunds('0.01', deployer.address, deployer) - await setupAccountWithMnemonic("dapptest", accounts.mnemonic, deployer); + ({ + router, + manager, + erc20cw20, + erc20TokenFactory, + weth9, + token, + tokenFactoryDenom, + cw20Address + } = await deployAndReturnUniswapContracts(deployer, testChain, accounts)); - - // Fund user account const userWallet = hre.ethers.Wallet.createRandom(); user = userWallet.connect(hre.ethers.provider); await sendFunds("1", user.address, deployer) - const deployerSeiAddr = await getSeiAddress(deployer.address); - - // Deploy Required Tokens - const time = Date.now().toString(); - - // Deploy TokenFactory token with ERC20 pointer - const tokenName = `dappTests${time}` - tokenFactoryDenom = await createTokenFactoryTokenAndMint(tokenName, hre.ethers.utils.parseEther("1000000").toString(), deployerSeiAddr, deployerSeiAddr) - console.log("DENOM", tokenFactoryDenom) - const pointerAddr = await deployErc20PointerNative(hre.ethers.provider, tokenFactoryDenom, deployerSeiAddr, evmRpcUrls[testChain]) - console.log("Pointer Addr", pointerAddr); - erc20TokenFactory = new hre.ethers.Contract(pointerAddr, ABI.ERC20, deployer); - - // Deploy CW20 token with ERC20 pointer - const cw20Details = await deployCw20WithPointer(deployerSeiAddr, deployer, time, evmRpcUrls[testChain]) - erc20cw20 = cw20Details.pointerContract; - cw20Address = cw20Details.cw20Address; - - // Deploy WETH9 Token (ETH representation on Uniswap) - weth9 = await deployEthersContract("WETH9", WETH9_ABI, WETH9_BYTECODE, deployer); - - // Deploy MockToken - console.log("Deploying MockToken with the account:", deployer.address); - const contractArtifact = await hre.artifacts.readArtifact("MockERC20"); - token = await deployEthersContract("MockToken", contractArtifact.abi, contractArtifact.bytecode, deployer, ["MockToken", "MKT", hre.ethers.utils.parseEther("1000000")]) - - // Deploy NFT Descriptor. These NFTs are used by the NonFungiblePositionManager to represent liquidity positions. - const descriptor = await deployEthersContract("NFT Descriptor", DESCRIPTOR_ABI, DESCRIPTOR_BYTECODE, deployer); - - // Deploy Uniswap Contracts - // Create UniswapV3 Factory - factory = await deployEthersContract("Uniswap V3 Factory", FACTORY_ABI, FACTORY_BYTECODE, deployer); - - // Deploy NonFungiblePositionManager - manager = await deployEthersContract("NonfungiblePositionManager", MANAGER_ABI, MANAGER_BYTECODE, deployer, deployParams=[factory.address, weth9.address, descriptor.address]); - - // Deploy SwapRouter - router = await deployEthersContract("SwapRouter", SWAP_ROUTER_ABI, SWAP_ROUTER_BYTECODE, deployer, deployParams=[factory.address, weth9.address]); - - const amountETH = hre.ethers.utils.parseEther("3") - - // Gets the amount of WETH9 required to instantiate pools by depositing Sei to the contract - let gasEstimate = await weth9.estimateGas.deposit({ value: amountETH }) - let gasPrice = await deployer.getGasPrice(); - const txWrap = await weth9.deposit({ value: amountETH, gasPrice, gasLimit: gasEstimate }); - await txWrap.wait(); - console.log(`Deposited ${amountETH.toString()} to WETH9`); - - // Create liquidity pools - await deployTokenPool(manager, weth9.address, token.address) - await deployTokenPool(manager, weth9.address, erc20TokenFactory.address) - await deployTokenPool(manager, weth9.address, erc20cw20.address) - - // Add Liquidity to pools - await supplyLiquidity(manager, deployer.address, weth9, token, hre.ethers.utils.parseEther("1"), hre.ethers.utils.parseEther("1")) - await supplyLiquidity(manager, deployer.address, weth9, erc20TokenFactory, hre.ethers.utils.parseEther("1"), hre.ethers.utils.parseEther("1")) - await supplyLiquidity(manager, deployer.address, weth9, erc20cw20, hre.ethers.utils.parseEther("1"), hre.ethers.utils.parseEther("1")) }) describe("Swaps", function () { // Swaps token1 for token2. - async function basicSwapTestAssociated(token1, token2, expectSwapFail=false) { + async function basicSwapTestAssociated(token1, token2, expectSwapFail = false) { const fee = 3000; // Fee tier (0.3%) // Perform a Swap const amountIn = hre.ethers.utils.parseEther("0.1"); const amountOutMin = hre.ethers.utils.parseEther("0"); // Minimum amount of MockToken expected - // const gasLimit = hre.ethers.utils.hexlify(1000000); // Example gas limit - // const gasPrice = await hre.ethers.provider.getGasPrice(); - await estimateAndCall(token1.connect(user), "deposit", [], amountIn) const token1balance = await token1.connect(user).balanceOf(user.address); @@ -167,7 +110,7 @@ describe("Uniswap Test", function () { } } - async function basicSwapTestUnassociated(token1, token2, expectSwapFail=false) { + async function basicSwapTestUnassociated(token1, token2, expectSwapFail = false) { const unassocUserWallet = ethers.Wallet.createRandom(); const unassocUser = unassocUserWallet.connect(ethers.provider); @@ -211,7 +154,9 @@ describe("Uniswap Test", function () { await estimateAndCall(router, "exactInputSingle", [txParams]) // Check User's MockToken Balance - const balance = await pollBalance(token2, unassocUser.address, function(bal) {return bal === 0}); + const balance = await pollBalance(token2, unassocUser.address, function (bal) { + return bal === 0 + }); // Check that it's more than 0 (no specified amount since there might be slippage) expect(Number(balance)).to.greaterThan(0, "User should have received some token2") @@ -258,20 +203,20 @@ describe("Uniswap Test", function () { }) it("Unassociated account should not be able to receive erc20cw20 tokens successfully", async function () { - await basicSwapTestUnassociated(weth9, erc20cw20, expectSwapFail=true) + await basicSwapTestUnassociated(weth9, erc20cw20, expectSwapFail = true) }); }) // We've already tested that an associated account (deployer) can deploy pools and supply liquidity in the Before() step. describe("Pools", function () { it("Unssosciated account should be able to deploy pools successfully", async function () { - const unassocUserWallet = hre.ethers.Wallet.createRandom(); - const unassocUser = unassocUserWallet.connect(hre.ethers.provider); + const unassocUserWallet = hre.ethers.Wallet.createRandom(); + const unassocUser = unassocUserWallet.connect(hre.ethers.provider); - // Fund the user account. Creating pools is a expensive operation so we supply more funds here for gas. - await sendFunds("0.5", unassocUser.address, deployer) + // Fund the user account. Creating pools is a expensive operation so we supply more funds here for gas. + await sendFunds("0.5", unassocUser.address, deployer) - await deployTokenPool(manager.connect(unassocUser), erc20TokenFactory.address, token.address) + await deployTokenPool(manager.connect(unassocUser), erc20TokenFactory.address, token.address) }) it("Unssosciated account should be able to supply liquidity pools successfully", async function () { @@ -291,7 +236,7 @@ describe("Uniswap Test", function () { const managerConnected = manager.connect(unassocUser); const erc20TokenFactoryConnected = erc20TokenFactory.connect(unassocUser); const mockTokenConnected = token.connect(unassocUser); - await supplyLiquidity(managerConnected, unassocUser.address, erc20TokenFactoryConnected, mockTokenConnected, Number(erc20TokenFactoryAmount)/2, Number(mockTokenAmount)/2) + await supplyLiquidity(managerConnected, unassocUser.address, erc20TokenFactoryConnected, mockTokenConnected, Number(erc20TokenFactoryAmount) / 2, Number(mockTokenAmount) / 2) }) }) diff --git a/integration_test/dapp_tests/utils.js b/integration_test/dapp_tests/utils.js index 9c66a92a0..526476d7d 100644 --- a/integration_test/dapp_tests/utils.js +++ b/integration_test/dapp_tests/utils.js @@ -1,7 +1,19 @@ const {v4: uuidv4} = require("uuid"); const hre = require("hardhat"); -const { ABI, deployErc20PointerForCw20, deployErc721PointerForCw721, getSeiAddress, deployWasm, execute, delay, isDocker } = require("../../contracts/test/lib.js"); -const path = require('path') +const { ABI, deployErc20PointerForCw20, associateKey, storeWasm, fundSeiAddress, deployErc721PointerForCw721, getSeiAddress, deployErc20PointerNative, deployWasm, execute, delay,createTokenFactoryTokenAndMint, isDocker, fundAddress } = require("../../contracts/test/lib.js"); +const path = require('path'); +const devnetUniswapConfig = require('./configs/uniswapConfig.json'); +const devnetSteakConfig = require('./configs/steakConfig.json'); +const devnetNftConfig = require('./configs/nftConfig.json'); + +const { abi: WETH9_ABI, bytecode: WETH9_BYTECODE } = require("@uniswap/v2-periphery/build/WETH9.json"); +const { abi: FACTORY_ABI, bytecode: FACTORY_BYTECODE } = require("@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json"); +const { abi: DESCRIPTOR_ABI, bytecode: DESCRIPTOR_BYTECODE } = require("@uniswap/v3-periphery/artifacts/contracts/libraries/NFTDescriptor.sol/NFTDescriptor.json"); +const { abi: MANAGER_ABI, bytecode: MANAGER_BYTECODE } = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json"); +const { abi: SWAP_ROUTER_ABI, bytecode: SWAP_ROUTER_BYTECODE } = require("@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json"); +const {chainIds, rpcUrls, evmRpcUrls} = require("./constants"); +const {expect} = require("chai"); +const {existsSync, readFileSync, writeFileSync} = require("node:fs"); async function deployTokenPool(managerContract, firstTokenAddr, secondTokenAddr, swapRatio=1, fee=3000) { const sqrtPriceX96 = BigInt(Math.sqrt(swapRatio) * (2 ** 96)); // Initial price (1:1) @@ -27,7 +39,6 @@ async function supplyLiquidity(managerContract, recipientAddr, firstTokenContrac // Approve the NonfungiblePositionManager to spend the specified amount of secondToken await estimateAndCall(secondTokenContract, "approve", [managerContract.address, secondTokenAmt]) - // Add liquidity to the pool await estimateAndCall(managerContract, "mint", [{ token0: token0.address, @@ -42,8 +53,6 @@ async function supplyLiquidity(managerContract, recipientAddr, firstTokenContrac recipient: recipientAddr, deadline: Math.floor(Date.now() / 1000) + 60 * 10, // 10 minutes from now }]); - - console.log("Liquidity added"); } // Orders the 2 addresses sequentially, since this is required by uniswap. @@ -60,6 +69,177 @@ function tokenOrder(firstTokenAddr, secondTokenAddr, firstTokenAmount=0, secondT return [token0, token1] } +async function returnContractsForFastTrackUniswap(deployer, config, testChain) { + const contractArtifact = await hre.artifacts.readArtifact("MockERC20"); + return { + manager: new hre.ethers.Contract(config.manager, MANAGER_ABI, deployer), + router: new hre.ethers.Contract(config.router, SWAP_ROUTER_ABI, deployer), + erc20TokenFactory: new hre.ethers.Contract(config.erc20TokenFactory, ABI.ERC20, deployer), + erc20cw20: new hre.ethers.Contract(config.erc20cw20, ABI.ERC20, deployer), + weth9: new hre.ethers.Contract(config.weth9, WETH9_ABI, deployer), + token: new hre.ethers.Contract(config.token, contractArtifact.abi, deployer), + tokenFactoryDenom: config.tokenFactoryDenom, + cw20Address: config.cw20Address + } +} + +async function returnContractsForFastTrackSteak(deployer, config, testChain) { + return { + hubAddress: config.hubAddress, + tokenAddress: config.tokenAddress, + tokenPointer: new hre.ethers.Contract( + config.pointerAddress, + ABI.ERC20, + hre.ethers.provider + ) + } +} + +async function deployAndReturnUniswapContracts(deployer, testChain, accounts) { + if (testChain === 'devnetFastTrack') { + console.log('Using already deployed contracts on arctic 1'); + return returnContractsForFastTrackUniswap(deployer, devnetUniswapConfig); + } else if (testChain === 'seiClusterFastTrack') { + if (clusterConfigExists('uniswapConfigCluster.json')) { + const contractConfig = path.join(__dirname, 'configs', 'uniswapConfigCluster.json'); + const clusterConfig = JSON.parse(readFileSync(contractConfig, 'utf8')); + return returnContractsForFastTrackUniswap(deployer, clusterConfig, testChain); + } else { + return writeAddressesIntoUniswapConfig(deployer, testChain, accounts); + } + } + return deployUniswapContracts(deployer, testChain, accounts); +} + +async function writeAddressesIntoUniswapConfig(deployer, testChain, accounts){ + const contracts = await deployUniswapContracts(deployer, testChain, accounts); + const contractAddresses = { + manager: contracts.manager.address, + router: contracts.router.address, + erc20TokenFactory: contracts.erc20TokenFactory.address, + erc20cw20: contracts.erc20cw20.address, + weth9: contracts.weth9.address, + token: contracts.token.address, + tokenFactoryDenom: contracts.tokenFactoryDenom, + cw20Address: contracts.cw20Address + }; + writeFileSync('./configs/uniswapConfigCluster.json', JSON.stringify(contractAddresses, null, 2), 'utf8'); + console.log('contract addresses are saved'); + return contracts; +} + +async function writeAddressesIntoSteakConfig(testChain){ + const contracts = await deployContractsForSteakTests(testChain); + const contractAddresses = { + hubAddress: contracts.hubAddress, + tokenAddress: contracts.tokenAddress, + pointerAddress: contracts.tokenPointer.address + }; + writeFileSync('./configs/steakConfigCluster.json', JSON.stringify(contractAddresses, null, 2), 'utf8'); + console.log('contract addresses are saved'); + return contracts; +} + +async function writeAddressesIntoNftConfig(deployer, testChain, accounts){ + const contracts = await deployContractsForNftTests(deployer, testChain, accounts); + const contractAddresses = { + marketplace: contracts.marketplace.address, + erc721token: contracts.erc721token.address, + cw721Address: contracts.cw721Address, + erc721PointerToken: contracts.erc721PointerToken.address, + }; + writeFileSync('./configs/nftConfigCluster.json', JSON.stringify(contractAddresses, null, 2), 'utf8'); + console.log('contract addresses are saved'); + return contracts; +} + +async function deployUniswapContracts(deployer, testChain, accounts){ + + if (testChain === 'seilocal') { + const tx = await fundAddress(deployer.address, amount="2000000000000000000000"); + await waitFor(1); + } + + // Set the config keyring to 'test' since we're using the key added to test from here. + await execute(`seid config keyring-backend test`) + + await sendFunds('0.01', deployer.address, deployer) + await setupAccountWithMnemonic("dapptest", accounts.mnemonic, deployer); + + const deployerSeiAddr = await getSeiAddress(deployer.address); + // Deploy Required Tokens + const time = Date.now().toString(); + + // Deploy TokenFactory token with ERC20 pointer + const tokenName = `dappTests${time}` + const tokenFactoryDenom = await createTokenFactoryTokenAndMint(tokenName, hre.ethers.utils.parseEther("1000000").toString(), deployerSeiAddr, deployerSeiAddr) + console.log("DENOM", tokenFactoryDenom) + const pointerAddr = await deployErc20PointerNative(hre.ethers.provider, tokenFactoryDenom, deployerSeiAddr, evmRpcUrls[testChain]) + console.log("Pointer Addr", pointerAddr); + const erc20TokenFactory = new hre.ethers.Contract(pointerAddr, ABI.ERC20, deployer); + + // Deploy CW20 token with ERC20 pointer + const cw20Details = await deployCw20WithPointer(deployerSeiAddr, deployer, time, evmRpcUrls[testChain]) + const erc20cw20 = cw20Details.pointerContract; + const cw20Address = cw20Details.cw20Address; + + // Deploy WETH9 Token (ETH representation on Uniswap) + const weth9 = await deployEthersContract("WETH9", WETH9_ABI, WETH9_BYTECODE, deployer); + + // Deploy MockToken + console.log("Deploying MockToken with the account:", deployer.address); + const contractArtifact = await hre.artifacts.readArtifact("MockERC20"); + const token = await deployEthersContract("MockToken", contractArtifact.abi, contractArtifact.bytecode, deployer, ["MockToken", "MKT", hre.ethers.utils.parseEther("1000000")]) + + // Deploy NFT Descriptor. These NFTs are used by the NonFungiblePositionManager to represent liquidity positions. + const descriptor = await deployEthersContract("NFT Descriptor", DESCRIPTOR_ABI, DESCRIPTOR_BYTECODE, deployer); + + // Deploy Uniswap Contracts + // Create UniswapV3 Factory + const factory = await deployEthersContract("Uniswap V3 Factory", FACTORY_ABI, FACTORY_BYTECODE, deployer); + + // Deploy NonFungiblePositionManager + const manager = await deployEthersContract("NonfungiblePositionManager", MANAGER_ABI, MANAGER_BYTECODE, deployer, deployParams=[factory.address, weth9.address, descriptor.address]); + + // Deploy SwapRouter + const router = await deployEthersContract("SwapRouter", SWAP_ROUTER_ABI, SWAP_ROUTER_BYTECODE, deployer, deployParams=[factory.address, weth9.address]); + + const amountETH = hre.ethers.utils.parseEther("3") + + // Gets the amount of WETH9 required to instantiate pools by depositing Sei to the contract + let gasEstimate = await weth9.estimateGas.deposit({ value: amountETH }) + let gasPrice = await deployer.getGasPrice(); + const txWrap = await weth9.deposit({ value: amountETH, gasPrice, gasLimit: gasEstimate }); + await txWrap.wait(); + console.log(`Deposited ${amountETH.toString()} to WETH9`); + + // Create liquidity pools + await deployTokenPool(manager, weth9.address, token.address) + await deployTokenPool(manager, weth9.address, erc20TokenFactory.address) + await deployTokenPool(manager, weth9.address, erc20cw20.address) + + // Add Liquidity to pools + await supplyLiquidity(manager, deployer.address, weth9, token, hre.ethers.utils.parseEther("1"), hre.ethers.utils.parseEther("1")) + await supplyLiquidity(manager, deployer.address, weth9, erc20TokenFactory, hre.ethers.utils.parseEther("1"), hre.ethers.utils.parseEther("1")) + await supplyLiquidity(manager, deployer.address, weth9, erc20cw20, hre.ethers.utils.parseEther("1"), hre.ethers.utils.parseEther("1")) + + return { + router, + manager, + erc20cw20, + erc20TokenFactory, + weth9, + token, + tokenFactoryDenom, + cw20Address + } +} + +function clusterConfigExists(fileName){ + const folderPath = path.join(__dirname, 'configs', fileName); + return existsSync(folderPath) +} + async function deployCw20WithPointer(deployerSeiAddr, signer, time, evmRpc="") { const CW20_BASE_PATH = (await isDocker()) ? '../integration_test/dapp_tests/uniswap/cw20_base.wasm' : path.resolve(__dirname, '../dapp_tests/uniswap/cw20_base.wasm') const cw20Address = await deployWasm(CW20_BASE_PATH, deployerSeiAddr, "cw20", { @@ -110,7 +290,6 @@ async function doesTokenFactoryDenomExist(denom) { } async function sendFunds(amountSei, recipient, signer) { - const bal = await signer.getBalance(); if (bal.lt(hre.ethers.utils.parseEther(amountSei))) { throw new Error(`Signer has insufficient balance. Want ${hre.ethers.utils.parseEther(amountSei)}, has ${bal}`); @@ -256,7 +435,7 @@ const bond = async (contractAddress, address, amount) => { bond: {}, }; const jsonString = JSON.stringify(msg).replace(/"/g, '\\"'); - const command = `seid tx wasm execute ${contractAddress} "${jsonString}" --amount=${amount}usei --from=${address} --gas=500000 --gas-prices=0.1usei --broadcast-mode=block -y --output=json`; + const command = `seid tx wasm execute ${contractAddress} "${jsonString}" --amount=${amount}usei --from=${address} --gas=600000 --gas-prices=0.1usei --broadcast-mode=block -y --output=json`; const output = await execute(command); const response = JSON.parse(output); if (response.code !== 0) { @@ -335,13 +514,21 @@ const transferTokens = async (tokenAddress, sender, destination, amount) => { return response; }; -async function setupAccountWithMnemonic(baseName, mnemonic, deployer) { +async function setupAccountWithMnemonic(baseName, mnemonic, deployer) { const uniqueName = `${baseName}-${uuidv4()}`; const address = await getSeiAddress(deployer.address) return await addDeployerAccount(uniqueName, address, mnemonic) } +async function waitFor(seconds){ + return new Promise((resolve) =>{ + setTimeout(() =>{ + resolve(); + }, seconds * 1000) + }) +} + async function addDeployerAccount(keyName, address, mnemonic) { // First try to retrieve by address try { @@ -366,8 +553,198 @@ async function addDeployerAccount(keyName, address, mnemonic) { return JSON.parse(output); } +async function setupAccount(baseName, associate = true, amount="100000000000", denom="usei", funder='admin') { + const uniqueName = `${baseName}-${uuidv4()}`; + + const account = await addAccount(uniqueName); + await fundSeiAddress(account.address, amount, denom, funder); + if (associate) { + await associateKey(account.address); + } + return account; +} + +async function deployAndReturnContractsForSteakTests(deployer, testChain, accounts){ + const owner = await setupAccountWithMnemonic("steak-owner", accounts.mnemonic, deployer); + let contracts; + // Check the test chain type and retrieve or write the contract configuration + if (testChain === 'devnetFastTrack') { + console.log('Using already deployed contracts on arctic 1'); + contracts = await returnContractsForFastTrackSteak(deployer, devnetSteakConfig, testChain); + } else if (testChain === 'seiClusterFastTrack') { + if (clusterConfigExists('steakConfigCluster.json')) { + const contractConfigPath = path.join(__dirname, 'configs', 'steakConfigCluster.json'); + const clusterConfig = JSON.parse(readFileSync(contractConfigPath, 'utf8')); + contracts = await returnContractsForFastTrackSteak(deployer, clusterConfig, testChain); + } else { + contracts = await writeAddressesIntoSteakConfig(testChain); + } + } else { + contracts = await deployContractsForSteakTests(testChain); + } + return { ...contracts, owner }; +} + +async function deployContractsForSteakTests(testChain){ + let owner; + // Set up the owner account + if (testChain === 'seilocal') { + owner = await setupAccount("steak-owner"); + } else { + const accounts = hre.config.networks[testChain].accounts + const deployerWallet = hre.ethers.Wallet.fromMnemonic(accounts.mnemonic, accounts.path); + const deployer = deployerWallet.connect(hre.ethers.provider) + + await sendFunds('0.01', deployer.address, deployer) + // Set the config keyring to 'test' since we're using the key added to test from here. + owner = await setupAccountWithMnemonic("steak-owner", accounts.mnemonic, deployer) + } + + await execute(`seid config keyring-backend test`); + + // Store and deploy contracts + const { hubAddress, tokenAddress, tokenPointer } = await deploySteakContracts( + owner.address, + testChain, + ); + + return {hubAddress, tokenAddress, tokenPointer, owner} +} + +async function deploySteakContracts(ownerAddress, testChain) { + // Store CW20 token wasm + const STEAK_TOKEN_WASM = (await isDocker()) ? '../integration_test/dapp_tests/steak/contracts/steak_token.wasm' : path.resolve(__dirname, 'steak/contracts/steak_token.wasm') + const tokenCodeId = await storeWasm(STEAK_TOKEN_WASM, ownerAddress); + + // Store Hub contract + const STEAK_HUB_WASM = (await isDocker()) ? '../integration_test/dapp_tests/steak/contracts/steak_hub.wasm' : path.resolve(__dirname, 'steak/contracts/steak_hub.wasm') + const hubCodeId = await storeWasm(STEAK_HUB_WASM, ownerAddress); + + // Instantiate hub and token contracts + const validators = await getValidators(); + const instantiateMsg = { + cw20_code_id: parseInt(tokenCodeId), + owner: ownerAddress, + name: "Steak", + symbol: "STEAK", + decimals: 6, + epoch_period: 259200, + unbond_period: 1814400, + validators: validators.slice(0, 3), + }; + const contractAddresses = await instantiateHubContract( + hubCodeId, + ownerAddress, + instantiateMsg, + "steakhub" + ); + + // Deploy pointer for token contract + const pointerAddr = await deployErc20PointerForCw20( + hre.ethers.provider, + contractAddresses.tokenContract, + 10, + ownerAddress, + evmRpcUrls[testChain] + ); + + const tokenPointer = new hre.ethers.Contract( + pointerAddr, + ABI.ERC20, + hre.ethers.provider + ); + + return { + hubAddress: contractAddresses.hubContract, + tokenAddress: contractAddresses.tokenContract, + tokenPointer, + }; +} + +async function deployAndReturnContractsForNftTests(deployer, testChain, accounts){ + let contracts; + // Check the test chain type and retrieve or write the contract configuration + if (testChain === 'devnetFastTrack') { + console.log('Using already deployed contracts on arctic 1'); + return returnContractsForFastTrackNftTests(deployer, devnetNftConfig, testChain); + } else if (testChain === 'seiClusterFastTrack') { + // Set chain ID and node configuration for the cluster fast track + if (clusterConfigExists('nftConfigCluster.json')) { + const contractConfigPath = path.join(__dirname, 'configs', 'nftConfigCluster.json'); + const clusterConfig = JSON.parse(readFileSync(contractConfigPath, 'utf8')); + contracts = await returnContractsForFastTrackNftTests(deployer, clusterConfig, testChain); + } else { + contracts = await writeAddressesIntoNftConfig(deployer, testChain, accounts); + } + } else { + contracts = await deployContractsForNftTests(deployer, testChain, accounts); + } + return contracts; +} + +async function deployContractsForNftTests(deployer, testChain, accounts){ + if (testChain === 'seilocal') { + await fundAddress(deployer.address, amount="2000000000000000000000"); + } + + await execute(`seid config keyring-backend test`) + + await sendFunds('0.01', deployer.address, deployer) + await setupAccountWithMnemonic("dapptest", accounts.mnemonic, deployer); + + // Deploy MockNFT + const erc721ContractArtifact = await hre.artifacts.readArtifact("MockERC721"); + const erc721token = await deployEthersContract("MockERC721", erc721ContractArtifact.abi, erc721ContractArtifact.bytecode, deployer, ["MockERC721", "MKTNFT"]) + + const numNftsToMint = 50 + await estimateAndCall(erc721token, "batchMint", [deployer.address, numNftsToMint]); + + // Deploy CW721 token with ERC721 pointer + const time = Date.now().toString(); + const deployerSeiAddr = await getSeiAddress(deployer.address); + const cw721Details = await deployCw721WithPointer(deployerSeiAddr, deployer, time, evmRpcUrls[testChain]) + const erc721PointerToken = cw721Details.pointerContract; + const cw721Address = cw721Details.cw721Address; + const numCwNftsToMint = 2; + for (let i = 1; i <= numCwNftsToMint; i++) { + await mintCw721(cw721Address, deployerSeiAddr, i) + } + const cwbal = await erc721PointerToken.balanceOf(deployer.address); + expect(cwbal).to.equal(numCwNftsToMint) + + const nftMarketplaceArtifact = await hre.artifacts.readArtifact("NftMarketplace"); + const marketplace = await deployEthersContract("NftMarketplace", nftMarketplaceArtifact.abi, nftMarketplaceArtifact.bytecode, deployer) + return {marketplace, erc721token, cw721Address, erc721PointerToken} +} + +async function returnContractsForFastTrackNftTests(deployer, clusterConfig, testChain) { + await setupAccountWithMnemonic("dapptest", deployer.mnemonic.phrase, deployer); + const nftMarketplaceArtifact = await hre.artifacts.readArtifact("NftMarketplace"); + const erc721ContractArtifact = await hre.artifacts.readArtifact("MockERC721"); + return { + marketplace: new hre.ethers.Contract(clusterConfig.marketplace, nftMarketplaceArtifact.abi, deployer), + erc721token: new hre.ethers.Contract(clusterConfig.erc721token, erc721ContractArtifact.abi, deployer), + erc721PointerToken: new hre.ethers.Contract(clusterConfig.erc721PointerToken, ABI.ERC721, deployer), + cw721Address: clusterConfig.cw721Address, + } +} + +async function queryLatestNftIds(contractAddress){ + return Number( + await execute(`seid q wasm contract-state smart ${contractAddress} '{"num_tokens": {}}' -o json | jq ".data.count"`)); +} + +async function setDaemonConfig(testChain) { + const seidConfig = await execute('seid config'); + const originalSeidConfig = JSON.parse(seidConfig); + await execute(`seid config chain-id ${chainIds[testChain]}`) + await execute(`seid config node ${rpcUrls[testChain]}`); + return originalSeidConfig; +} + module.exports = { getValidators, + returnContractsForFastTrackUniswap, instantiateHubContract, bond, unbond, @@ -375,6 +752,7 @@ module.exports = { queryTokenBalance, addAccount, estimateAndCall, + deployAndReturnUniswapContracts, addDeployerAccount, setupAccountWithMnemonic, transferTokens, @@ -386,5 +764,15 @@ module.exports = { doesTokenFactoryDenomExist, pollBalance, sendFunds, - mintCw721 + mintCw721, + returnContractsForFastTrackSteak, + deployContractsForSteakTests, + setupAccount, + returnContractsForFastTrackNftTests, + deployContractsForNftTests, + deployAndReturnContractsForSteakTests, + deployAndReturnContractsForNftTests, + waitFor, + queryLatestNftIds, + setDaemonConfig, }; \ No newline at end of file