Merge pull request #123 from Instadapp/typescript-support

Enables typescript support to project.
This commit is contained in:
Thrilok kumar 2021-12-11 14:33:46 +05:30 committed by GitHub
commit 593fb86367
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
87 changed files with 9354 additions and 6121 deletions

1
.gitignore vendored
View File

@ -63,3 +63,4 @@ build/contracts
# buidler
artifacts
cache
typechain

View File

@ -1,100 +0,0 @@
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-ethers");
require("@tenderly/hardhat-tenderly");
require("@nomiclabs/hardhat-etherscan");
require("@nomiclabs/hardhat-web3");
require("hardhat-deploy");
require("hardhat-deploy-ethers");
require("dotenv").config();
const { utils } = require("ethers");
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const ALCHEMY_ID = process.env.ALCHEMY_ID;
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY;
if (!process.env.ALCHEMY_ID) {
throw new Error("ENV Variable ALCHEMY_ID not set!");
}
/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: {
compilers: [
{
version: "0.7.6",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
{
version: "0.6.0",
},
{
version: "0.6.2",
},
{
version: "0.6.5",
},
],
},
networks: {
kovan: {
url: `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_ID}`,
accounts: [`0x${PRIVATE_KEY}`],
},
mainnet: {
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
accounts: [`0x${PRIVATE_KEY}`],
timeout: 150000,
gasPrice: parseInt(utils.parseUnits("30", "gwei")),
},
rinkeby: {
url: `https://eth-rinkeby.alchemyapi.io/v2/${ALCHEMY_ID}`,
accounts: [`0x${PRIVATE_KEY}`],
timeout: 150000,
},
hardhat: {
forking: {
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
blockNumber: 12696000,
},
blockGasLimit: 12000000,
},
matic: {
url: "https://polygon-rpc.com/",
accounts: [`0x${PRIVATE_KEY}`],
timeout: 150000,
gasPrice: parseInt(utils.parseUnits("50", "gwei")),
},
arbitrum: {
chainId: 42161,
url: `https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_ID}`,
accounts: [`0x${PRIVATE_KEY}`],
timeout: 150000,
gasPrice: parseInt(utils.parseUnits("2", "gwei")),
},
avax: {
url: "https://api.avax.network/ext/bc/C/rpc",
chainId: 43114,
accounts: [`0x${PRIVATE_KEY}`],
timeout: 150000,
gasPrice: parseInt(utils.parseUnits("225", "gwei")),
},
},
etherscan: {
apiKey: ETHERSCAN_API_KEY,
},
tenderly: {
project: process.env.TENDERLY_PROJECT,
username: process.env.TENDERLY_USERNAME,
},
mocha: {
timeout: 100 * 1000,
},
};

130
hardhat.config.ts Normal file
View File

@ -0,0 +1,130 @@
import "@nomiclabs/hardhat-waffle";
import "@nomiclabs/hardhat-ethers";
import "@tenderly/hardhat-tenderly";
import "@nomiclabs/hardhat-etherscan";
import "@nomiclabs/hardhat-web3";
import "hardhat-deploy";
import "hardhat-deploy-ethers";
import "@typechain/hardhat";
import { resolve } from "path";
import { config as dotenvConfig } from "dotenv";
import { HardhatUserConfig } from "hardhat/config";
import { NetworkUserConfig } from "hardhat/types";
import { utils } from "ethers";
import Web3 from "web3";
dotenvConfig({ path: resolve(__dirname, "./.env") });
const chainIds = {
ganache: 1337,
hardhat: 31337,
mainnet: 1,
avalanche: 43114,
polygon: 137,
arbitrum: 42161,
};
const alchemyApiKey = process.env.ALCHEMY_API_KEY;
if (!alchemyApiKey) {
throw new Error("Please set your ALCHEMY_API_KEY in a .env file");
}
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const ETHERSCAN_API = process.env.ETHERSCAN_API_KEY;
const POLYGONSCAN_API = process.env.POLYGON_API_KEY;
const ARBISCAN_API = process.env.ARBISCAN_API_KEY;
const SNOWTRACE_API = process.env.SNOWTRACE_API_KEY;
const mnemonic =
process.env.MNEMONIC ??
"test test test test test test test test test test test junk";
function createConfig(network: string) {
return {
url: getNetworkUrl(network),
accounts: !!PRIVATE_KEY ? [`0x${PRIVATE_KEY}`] : { mnemonic },
};
}
function getNetworkUrl(networkType: string) {
//console.log(process.env);
if (networkType === "avalanche")
return "https://api.avax.network/ext/bc/C/rpc";
else if (networkType === "polygon")
return `https://polygon-mainnet.g.alchemy.com/v2/${alchemyApiKey}`;
else if (networkType === "arbitrum")
return `https://arb-mainnet.g.alchemy.com/v2/${alchemyApiKey}`;
else return `https://eth-mainnet.alchemyapi.io/v2/${alchemyApiKey}`;
}
function getScanApiKey(networkType: string) {
if (networkType === "avalanche") return SNOWTRACE_API;
else if (networkType === "polygon") return POLYGONSCAN_API;
else if (networkType === "arbitrum") return ARBISCAN_API;
else return ETHERSCAN_API;
}
/**
* @type import('hardhat/config').HardhatUserConfig
*/
const config: HardhatUserConfig = {
solidity: {
compilers: [
{
version: "0.7.6",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
{
version: "0.6.0",
},
{
version: "0.6.2",
},
{
version: "0.6.5",
},
],
},
networks: {
hardhat: {
accounts: {
mnemonic,
},
chainId: chainIds.hardhat,
forking: {
url: String(getNetworkUrl(String(process.env.networkType))),
},
},
mainnet: createConfig("mainnet"),
polygon: createConfig("polygon"),
avalanche: createConfig("avalanche"),
arbitrum: createConfig("arbitrum"),
},
paths: {
artifacts: "./artifacts",
cache: "./cache",
sources: "./contracts",
tests: "./test",
},
etherscan: {
apiKey: getScanApiKey(getNetworkUrl(String(process.env.networkType))),
},
typechain: {
outDir: "typechain",
target: "ethers-v5",
},
mocha: {
timeout: 10000 * 1000, // 10,000 seconds
},
// tenderly: {
// project: process.env.TENDERLY_PROJECT,
// username: process.env.TENDERLY_USERNAME,
// },
};
export default config;

6125
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,11 +4,14 @@
"description": "",
"directories": {},
"scripts": {
"test": "hardhat test",
"test": "hardhat run scripts/tests/global-test.ts",
"coverage": "./node_modules/.bin/solidity-coverage",
"check": "node status-checks/huskyCheck.js",
"check-husky": "node status-checks/huskyCheck.js",
"deploy": "node scripts/deployConnectorsFromCmd.js"
"deploy": "node scripts/deployConnectorsFromCmd.js",
"test:runner": "hardhat run scripts/tests/run-tests.ts",
"typechain": "hardhat typechain",
"compile": "hardhat compile"
},
"repository": {
"type": "git",
@ -22,30 +25,42 @@
"homepage": "https://github.com/InstaDApp/dsa-connectors-new#readme",
"dependencies": {
"@openzeppelin/contracts": "^3.4.0-solc-0.7",
"@typechain/ethers-v5": "^8.0.5",
"@typechain/hardhat": "^3.0.0",
"@uniswap/v3-core": "^1.0.0",
"@uniswap/v3-periphery": "^1.2.1",
"chalk": "^4.1.2",
"@uniswap/v3-periphery": "^1.3.0",
"chalk": "^5.0.0",
"dotenv": "^10.0.0",
"hardhat-docgen": "^1.1.2",
"hardhat-docgen": "^1.2.0",
"inquirer": "^8.2.0",
"minimist": "^1.2.5",
"solc": "^0.7.0"
"solc": "^0.8.10",
"typechain": "^6.0.5"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@nomiclabs/hardhat-etherscan": "^2.1.7",
"@nomiclabs/hardhat-ethers": "^2.0.3",
"@nomiclabs/hardhat-etherscan": "^2.1.8",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@nomiclabs/hardhat-web3": "^2.0.0",
"@openzeppelin/test-helpers": "^0.5.15",
"@studydefi/money-legos": "^2.4.2",
"@tenderly/hardhat-tenderly": "^1.0.12",
"@tenderly/hardhat-tenderly": "^1.0.13",
"@types/chai": "^4.2.22",
"@types/chai-as-promised": "^7.1.4",
"@types/inquirer": "^8.1.3",
"@types/mocha": "^9.0.0",
"@types/node": "^16.11.11",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"ethereum-waffle": "^3.4.0",
"ethers": "^5.5.1",
"hardhat": "^2.6.7",
"hardhat-deploy": "^0.9.4",
"ethers": "^5.5.2",
"hardhat": "^2.7.0",
"hardhat-deploy": "^0.9.14",
"hardhat-deploy-ethers": "^0.3.0-beta.11",
"husky": "^7.0.4",
"solidity-coverage": "0.5.11",
"web3": "^1.5.2"
"solidity-coverage": "0.7.17",
"ts-node": "^10.4.0",
"typescript": "^4.5.2",
"web3": "^1.6.1"
}
}

View File

@ -1,15 +0,0 @@
const hre = require("hardhat");
const { ethers } = hre;
const addresses = require("./constant/addresses");
const abis = require("./constant/abis");
const instaImplementations_m1 = require("../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json")
module.exports = async function (owner) {
const instaIndex = await ethers.getContractAt(abis.core.instaIndex, addresses.core.instaIndex)
const tx = await instaIndex.build(owner, 2, owner);
const receipt = await tx.wait()
const event = receipt.events.find(a => a.event === "LogAccountCreated")
return await ethers.getContractAt(instaImplementations_m1.abi, event.args.account)
};

View File

@ -1,4 +1,4 @@
module.exports = {
export const abis: Record<string, any> = {
core: {
connectorsV2: require("./abi/core/connectorsV2.json"),
instaIndex: require("./abi/core/instaIndex.json"),

View File

@ -1,11 +0,0 @@
module.exports = {
connectors: {
basic: "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6",
auth: "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9",
"INSTAPOOL-A": "0x5806af7ab22e2916fa582ff05731bf7c682387b2",
},
core: {
connectorsV2: "0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11",
instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723",
},
};

View File

@ -1,6 +0,0 @@
module.exports = {
address_zero: "0x0000000000000000000000000000000000000000",
eth_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
max_value: "115792089237316195423570985008687907853269984665640564039457584007913129639935"
};

View File

@ -0,0 +1,6 @@
export const constants = {
address_zero: "0x0000000000000000000000000000000000000000",
native_address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
max_value:
"115792089237316195423570985008687907853269984665640564039457584007913129639935",
};

View File

@ -1,23 +0,0 @@
module.exports = {
"eth": {
"type": "token",
"symbol": "ETH",
"name": "Ethereum",
"address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"decimals": 18
},
"dai": {
"type": "token",
"symbol": "DAI",
"name": "DAI Stable",
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"decimals": 18
},
"usdc": {
"type": "token",
"symbol": "USDC",
"name": "USD Coin",
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"decimals": 6
}
}

View File

@ -1,38 +0,0 @@
const hre = require("hardhat");
const { ethers } = hre;
const deployConnector = require("./deployConnector");
async function main() {
const accounts = await hre.ethers.getSigners()
const wallet = accounts[0]
const connectMapping = {
'1INCH-A': 'ConnectV2OneInch',
'1INCH-B': 'ConnectV2OneProto',
'AAVE-V1-A': 'ConnectV2AaveV1',
'AAVE-V2-A': 'ConnectV2AaveV2',
'AUTHORITY-A': 'ConnectV2Auth',
'BASIC-A': 'ConnectV2Basic',
'COMP-A': 'ConnectV2COMP',
'COMPOUND-A': 'ConnectV2Compound',
'DYDX-A': 'ConnectV2Dydx',
'FEE-A': 'ConnectV2Fee',
'GELATO-A': 'ConnectV2Gelato',
'MAKERDAO-A': 'ConnectV2Maker',
'UNISWAP-A': 'ConnectV2UniswapV2'
}
const addressMapping = {}
for (const key in connectMapping) {
addressMapping[key] = await deployConnector(connectMapping[key])
}
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});

View File

@ -1,19 +0,0 @@
const abis = require("./constant/abis");
const addresses = require("./constant/addresses");
const hre = require("hardhat");
const { ethers, waffle } = hre;
const { deployContract } = waffle;
const fs = require("fs")
module.exports = async function ({connectorName, contractArtifact, signer, connectors}) {
const connectorInstanace = await deployContract(signer, contractArtifact, []);
await connectors.connect(signer).addConnectors([connectorName], [connectorInstanace.address])
addresses.connectors[connectorName] = connectorInstanace.address
abis.connectors[connectorName] = contractArtifact.abi;
return connectorInstanace;
};

View File

@ -1,27 +0,0 @@
const hre = require("hardhat");
const { ethers, deployments, getUnnamedAccounts } = hre;
const { deploy } = deployments;
async function main() {
const deployer = (await getUnnamedAccounts())[0]
const connector = "ConnectV2InstaPoolV3Avalanche"
const connectorInstance = await deploy(connector, {
from: deployer,
})
console.log(`${connector} deployed: `, connectorInstance.address);
await hre.run("sourcify", {
address: connectorInstance.address,
})
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});

View File

@ -1,24 +0,0 @@
const hre = require("hardhat");
const { ethers } = hre;
module.exports = async (connectorName) => {
const Connector = await ethers.getContractFactory(connectorName);
const connector = await Connector.deploy();
await connector.deployed();
console.log(`${connectorName} Deployed: ${connector.address}`);
try {
await hre.run("verify:verify", {
address: connector.address,
constructorArguments: []
}
)
} catch (error) {
console.log(`Failed to verify: ${connectorName}@${connector.address}`)
console.log(error)
console.log()
}
return connector.address
}

View File

@ -1,105 +0,0 @@
const fs = require("fs");
const hre = require("hardhat");
const { ethers } = hre;
let args = process.argv;
args = args.splice(2, args.length);
let params = {};
for (let i = 0; i < args.length; i += 2) {
if (args[i][0] !== "-" || args[i][1] !== "-") {
console.log("Please add '--' for the key");
process.exit(-1);
}
let key = args[i].slice(2, args[i].length);
params[key] = args[i + 1];
}
if (!params.hasOwnProperty('connector')) {
console.error("Should include connector params")
process.exit(-1);
}
if (!params.hasOwnProperty('network')) {
console.error("Should include network params")
process.exit(-1);
}
if (!params.hasOwnProperty('gasPrice')) {
console.error("Should include gas params")
process.exit(-1);
}
let privateKey = process.env.PRIVATE_KEY;
let provider = new ethers.providers.JsonRpcProvider(hre.config.networks[params['network']].url);
let wallet = new ethers.Wallet(privateKey, provider);
hre.network.name = params['networkName'];
hre.network.config = hre.config.networks[params['networkName']];
hre.network.provider = provider;
let contracts = [];
const parseFile = async (filePath) => {
const data = fs.readFileSync(filePath, "utf-8");
let parsedData = data.split("contract ");
parsedData = parsedData[parsedData.length - 1].split(" ");
parsedData = parsedData[0];
return parsedData;
}
const parseDir = async (root, basePath, addPath) => {
for(let i = 0; i < root.length; i++) {
addPath = "/" + root[i];
const dir = fs.readdirSync(basePath + addPath);
if(dir.indexOf("main.sol") !== -1) {
const fileData = await parseFile(basePath + addPath + "/main.sol");
contracts.push(fileData)
} else {
await parseDir(dir, basePath + addPath, "");
}
}
}
const main = async () => {
const mainnet = fs.readdirSync("./contracts/mainnet/connectors/");
const polygon = fs.readdirSync("./contracts/polygon/connectors/");
let basePathMainnet = "./contracts/mainnet/connectors/";
let basePathPolygon = "./contracts/polygon/connectors/";
const connectorName = params['connector'];
await parseDir(mainnet, basePathMainnet, "");
await parseDir(polygon, basePathPolygon, "");
if(contracts.indexOf(connectorName) === -1) {
throw new Error("can not find the connector!\n" + "supported connector names are:\n" + contracts.join("\n"));
}
const Connector = await ethers.getContractFactory(connectorName);
const connector = await Connector.connect(wallet).deploy({ gasPrice: ethers.utils.parseUnits(params['gasPrice'], "gwei") });
await connector.deployed();
console.log(`${connectorName} Deployed: ${connector.address}`);
try {
await hre.run("verify:verify", {
address: connector.address,
constructorArguments: []
}
)
} catch (error) {
console.log(`Failed to verify: ${connectorName}@${connector.address}`)
console.log(error)
}
return connector.address
}
main()
.then(() => {
console.log("Done successfully");
process.exit(0)
})
.catch(err => {
console.log("error:", err);
process.exit(1);
})

View File

@ -1,36 +0,0 @@
const hre = require('hardhat')
const { ethers } = hre
async function main () {
if (hre.network.name === 'mainnet') {
console.log(
'\n\n Deploying Contracts to mainnet. Hit ctrl + c to abort'
)
} else if (hre.network.name === 'hardhat') {
console.log(
'\n\n Deploying Contracts to hardhat.'
)
}
const InstaMappingController = await ethers.getContractFactory('InstaMappingController')
const instaMappingController = await InstaMappingController.deploy()
await instaMappingController.deployed()
console.log('InstaMappingController deployed: ', instaMappingController.address)
if (hre.network.name === 'mainnet') {
await hre.run('verify:verify', {
address: instaMappingController.address,
constructorArguments: []
})
} else if (hre.network.name === 'hardhat') {
console.log("Contracts deployed.")
}
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error)
process.exit(1)
})

View File

@ -1,38 +0,0 @@
const hre = require('hardhat')
const { ethers } = hre
async function main () {
if (hre.network.name === 'mainnet') {
console.log(
'\n\n Deploying Contracts to mainnet. Hit ctrl + c to abort'
)
} else if (hre.network.name === 'hardhat') {
console.log(
'\n\n Deploying Contracts to hardhat.'
)
}
const mappingContract = "CONTRACT_NAME"
const InstaProtocolMapping = await ethers.getContractFactory(mappingContract)
const instaProtocolMapping = await InstaProtocolMapping.deploy()
await instaProtocolMapping.deployed()
console.log(`${mappingContract} deployed: `, instaProtocolMapping.address)
if (hre.network.name === 'mainnet') {
await hre.run('verify:verify', {
address: instaProtocolMapping.address,
constructorArguments: []
})
} else if (hre.network.name === 'hardhat') {
console.log("Contracts deployed.")
}
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error)
process.exit(1)
})

View File

@ -1,23 +0,0 @@
const hre = require("hardhat");
const { ethers } = hre;
const deployConnector = require("./deployConnector");
async function main() {
const address = await deployConnector("ConnectOne") // Example
const connectorsAbi = [
"function addConnectors(string[] _connectorNames, address[] _connectors)"
]
const connectorsContract = new ethers.Contract("0x84b457c6D31025d56449D5A01F0c34bF78636f67", connectorsAbi, ethers.provider);
await connectorsContract.addConnectors(['1inch'], [address])
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});

View File

@ -0,0 +1,35 @@
import { ethers } from "hardhat";
import { deployConnector } from "./deployConnector";
async function main() {
const accounts = await ethers.getSigners();
const connectMapping: Record<string, string> = {
"1INCH-A": "ConnectV2OneInch",
"1INCH-B": "ConnectV2OneProto",
"AAVE-V1-A": "ConnectV2AaveV1",
"AAVE-V2-A": "ConnectV2AaveV2",
"AUTHORITY-A": "ConnectV2Auth",
"BASIC-A": "ConnectV2Basic",
"COMP-A": "ConnectV2COMP",
"COMPOUND-A": "ConnectV2Compound",
"DYDX-A": "ConnectV2Dydx",
"FEE-A": "ConnectV2Fee",
"GELATO-A": "ConnectV2Gelato",
"MAKERDAO-A": "ConnectV2Maker",
"UNISWAP-A": "ConnectV2UniswapV2",
};
const addressMapping: Record<string, string> = {};
for (const key in connectMapping) {
addressMapping[key] = await deployConnector(connectMapping[key]);
}
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@ -0,0 +1,24 @@
import hre from "hardhat";
const { ethers, deployments, getUnnamedAccounts } = hre;
const { deploy } = deployments;
async function main() {
const deployer = (await getUnnamedAccounts())[0];
const connector = "// Add connector name over here Eg: ConnectV2InstaPoolV3Avalanche"
const connectorInstance = await deploy(connector, {
from: deployer,
});
console.log(`${connector} deployed: `, connectorInstance.address);
await hre.run("sourcify", {
address: connectorInstance.address,
});
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@ -1,8 +1,6 @@
const hre = require("hardhat");
import hre from "hardhat";
const { ethers } = hre;
async function main() {
const CONNECTORS_V2 = "0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11";
const ctokenMapping = {
@ -23,7 +21,7 @@ async function main() {
"AAVE-A": "0xe65cdb6479bac1e22340e4e755fae7e509ecd06c",
"TUSD-A": "0x12392f67bdf24fae0af363c24ac620a2f67dad86",
"LINK-A": "0xface851a4921ce59e912d19329929ce6da6eb0c7",
}
};
const tokenMapping = {
"ETH-A": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
@ -43,7 +41,7 @@ async function main() {
"AAVE-A": "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9",
"TUSD-A": "0x0000000000085d4780B73119b644AE5ecd22b376",
"LINK-A": "0x514910771af9ca656af840dff83e8264ecf986ca",
}
};
const Mapping = await ethers.getContractFactory("InstaCompoundMapping");
const mapping = await Mapping.deploy(
@ -58,25 +56,24 @@ async function main() {
try {
await hre.run("verify:verify", {
address: mapping.address,
constructorArguments: [
CONNECTORS_V2,
Object.keys(ctokenMapping),
Object.values(tokenMapping),
Object.values(ctokenMapping)
]
}
)
} catch (error) {
console.log(`Failed to verify: InstaCompoundMapping@${mapping.address}`)
console.log(error)
console.log()
}
address: mapping.address,
constructorArguments: [
CONNECTORS_V2,
Object.keys(ctokenMapping),
Object.values(tokenMapping),
Object.values(ctokenMapping),
],
});
} catch (error) {
console.log(`Failed to verify: InstaCompoundMapping@${mapping.address}`);
console.log(error);
console.log();
}
}
main()
.then(() => process.exit(0))
.catch(error => {
.catch((error) => {
console.error(error);
process.exit(1);
});
});

View File

@ -0,0 +1,10 @@
import { ethers } from "hardhat";
export const deployConnector = async (connectorName: string) => {
const Connector = await ethers.getContractFactory(connectorName);
const connector = await Connector.deploy();
await connector.deployed();
console.log(`${connectorName} Deployed: ${connector.address}`);
return connector.address;
};

View File

@ -0,0 +1,111 @@
import fs from "fs";
import hre from "hardhat"
const { ethers, network, config } = hre;
let args = process.argv;
args = args.splice(2, args.length);
let params: Record<string, string> = {};
for (let i = 0; i < args.length; i += 2) {
if (args[i][0] !== "-" || args[i][1] !== "-") {
console.log("Please add '--' for the key");
process.exit(-1);
}
let key = args[i].slice(2, args[i].length);
params[key] = args[i + 1];
}
if (!params.hasOwnProperty("connector")) {
console.error("Should include connector params");
process.exit(-1);
}
if (!params.hasOwnProperty("network")) {
console.error("Should include network params");
process.exit(-1);
}
if (!params.hasOwnProperty("gasPrice")) {
console.error("Should include gas params");
process.exit(-1);
}
let privateKey = String(process.env.PRIVATE_KEY);
let provider = new ethers.providers.JsonRpcProvider(
config.networks[params["network"]].url
);
let wallet = new ethers.Wallet(privateKey, provider);
network.name = params["networkName"];
network.config = config.networks[params["networkName"]];
network.provider = provider;
let contracts: (string | string[])[] = [];
const parseFile = async (filePath: fs.PathOrFileDescriptor) => {
const data = fs.readFileSync(filePath, "utf-8");
let parsedData = data.split("contract ");
parsedData = parsedData[parsedData.length - 1].split(" ");
return parsedData[0];
};
const parseDir = async (root: string | any[], basePath: string, addPath: string) => {
for (let i = 0; i < root.length; i++) {
addPath = "/" + root[i];
const dir = fs.readdirSync(basePath + addPath);
if (dir.indexOf("main.sol") !== -1) {
const fileData = await parseFile(basePath + addPath + "/main.sol");
contracts.push(fileData);
} else {
await parseDir(dir, basePath + addPath, "");
}
}
};
const main = async () => {
const mainnet = fs.readdirSync("./contracts/mainnet/connectors/");
const polygon = fs.readdirSync("./contracts/polygon/connectors/");
let basePathMainnet = "./contracts/mainnet/connectors/";
let basePathPolygon = "./contracts/polygon/connectors/";
const connectorName = params["connector"];
await parseDir(mainnet, basePathMainnet, "");
await parseDir(polygon, basePathPolygon, "");
if (contracts.indexOf(connectorName) === -1) {
throw new Error(
"can not find the connector!\n" +
"supported connector names are:\n" +
contracts.join("\n")
);
}
const Connector = await ethers.getContractFactory(connectorName);
const connector = await Connector.connect(wallet).deploy({
gasPrice: ethers.utils.parseUnits(params["gasPrice"], "gwei"),
});
await connector.deployed();
console.log(`${connectorName} Deployed: ${connector.address}`);
try {
await hre.run("verify:verify", {
address: connector.address,
constructorArguments: [],
});
} catch (error) {
console.log(`Failed to verify: ${connectorName}@${connector.address}`);
console.log(error);
}
return connector.address;
};
main()
.then(() => {
console.log("Done successfully");
process.exit(0);
})
.catch((err) => {
console.log("error:", err);
process.exit(1);
});

View File

@ -0,0 +1,37 @@
import hre from "hardhat";
const { ethers } = hre;
async function main() {
if (hre.network.name === "mainnet") {
console.log("\n\n Deploying Contracts to mainnet. Hit ctrl + c to abort");
} else if (hre.network.name === "hardhat") {
console.log("\n\n Deploying Contracts to hardhat.");
}
const InstaMappingController = await ethers.getContractFactory(
"InstaMappingController"
);
const instaMappingController = await InstaMappingController.deploy();
await instaMappingController.deployed();
console.log(
"InstaMappingController deployed: ",
instaMappingController.address
);
if (hre.network.name === "mainnet") {
await hre.run("verify:verify", {
address: instaMappingController.address,
constructorArguments: [],
});
} else if (hre.network.name === "hardhat") {
console.log("Contracts deployed.");
}
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@ -0,0 +1,34 @@
import hre from "hardhat";
const { ethers } = hre;
async function main() {
if (hre.network.name === "mainnet") {
console.log("\n\n Deploying Contracts to mainnet. Hit ctrl + c to abort");
} else if (hre.network.name === "hardhat") {
console.log("\n\n Deploying Contracts to hardhat.");
}
const mappingContract = "CONTRACT_NAME";
const InstaProtocolMapping = await ethers.getContractFactory(mappingContract);
const instaProtocolMapping = await InstaProtocolMapping.deploy();
await instaProtocolMapping.deployed();
console.log(`${mappingContract} deployed: `, instaProtocolMapping.address);
if (hre.network.name === "mainnet") {
await hre.run("verify:verify", {
address: instaProtocolMapping.address,
constructorArguments: [],
});
} else if (hre.network.name === "hardhat") {
console.log("Contracts deployed.");
}
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});

View File

@ -1,16 +0,0 @@
const abis = require("./constant/abis");
const addresses = require("./constant/addresses");
const { web3 } = hre;
const encodeSpells = require("./encodeSpells.js")
module.exports = function (spells) {
const encodeSpellsData = encodeSpells(spells);
const targetType = "string[]";
let argTypes = [targetType, "bytes[]"];
return web3.eth.abi.encodeParameters(argTypes, [
encodeSpellsData[0],
encodeSpellsData[1],
]);
};

View File

@ -1,18 +0,0 @@
const abis = require("./constant/abis");
const addresses = require("./constant/addresses");
const { web3 } = hre;
module.exports = function (spells) {
const targets = spells.map(a => a.connector)
const calldatas = spells.map(a => {
const functionName = a.method;
// console.log(functionName)
const abi = abis.connectors[a.connector].find(b => {
return b.name === functionName
});
// console.log(functionName)
if (!abi) throw new Error("Couldn't find function")
return web3.eth.abi.encodeFunctionCall(abi, a.args)
})
return [targets, calldatas]
};

View File

@ -1,25 +0,0 @@
const hre = require("hardhat");
const { ethers } = hre;
const addresses = require("./constant/addresses");
const abis = require("./constant/abis");
module.exports = async function() {
const [_, __, ___, wallet3] = await ethers.getSigners();
const instaIndex = new ethers.Contract(
addresses.core.instaIndex,
abis.core.instaIndex,
wallet3
);
const masterAddress = await instaIndex.master(); // TODO: make it constant?
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [masterAddress],
});
await wallet3.sendTransaction({
to: masterAddress,
value: ethers.utils.parseEther("10"),
});
return await ethers.getSigner(masterAddress);
};

View File

@ -1,15 +0,0 @@
const hre = require("hardhat");
const { ethers } = hre;
const addresses = require("./constant/addresses");
const abis = require("../constant/abis");
const instaImplementations_m1 = require("../../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json")
module.exports = async function (owner) {
const instaIndex = await ethers.getContractAt(abis.core.instaIndex, addresses.core.instaIndex)
const tx = await instaIndex.build(owner, 2, owner);
const receipt = await tx.wait()
const event = receipt.events.find(a => a.event === "LogAccountCreated")
return await ethers.getContractAt(instaImplementations_m1.abi, event.args.account)
};

View File

@ -1,7 +0,0 @@
module.exports = {
address_zero: "0x0000000000000000000000000000000000000000",
eth_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
matic_addr: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
max_value: "115792089237316195423570985008687907853269984665640564039457584007913129639935"
};

View File

@ -1,30 +0,0 @@
module.exports = {
"matic": {
"type": "token",
"symbol": "MATIC",
"name": "Matic",
"address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"decimals": 18
},
"eth": {
"type": "token",
"symbol": "ETH",
"name": "Ethereum",
"address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"decimals": 18
},
"dai": {
"type": "token",
"symbol": "DAI",
"name": "DAI Stable",
"address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
"decimals": 18
},
"usdc": {
"type": "token",
"symbol": "USDC",
"name": "USD Coin",
"address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
"decimals": 6
}
}

View File

@ -1,19 +0,0 @@
const abis = require("../constant/abis");
const addresses = require("./constant/addresses");
const hre = require("hardhat");
const { ethers, waffle } = hre;
const { deployContract } = waffle;
const fs = require("fs")
module.exports = async function ({connectorName, contractArtifact, signer, connectors}) {
const connectorInstanace = await deployContract(signer, contractArtifact, []);
await connectors.connect(signer).addConnectors([connectorName], [connectorInstanace.address])
addresses.connectors[connectorName] = connectorInstanace.address
abis.connectors[connectorName] = contractArtifact.abi;
return connectorInstanace;
};

View File

@ -1,18 +0,0 @@
const abis = require("../constant/abis");
const addresses = require("./constant/addresses");
const { web3 } = hre;
module.exports = function (spells) {
const targets = spells.map(a => a.connector)
const calldatas = spells.map(a => {
const functionName = a.method;
// console.log(functionName)
const abi = abis.connectors[a.connector].find(b => {
return b.name === functionName
});
// console.log(functionName)
if (!abi) throw new Error("Couldn't find function")
return web3.eth.abi.encodeFunctionCall(abi, a.args)
})
return [targets, calldatas]
};

View File

@ -1,25 +0,0 @@
const hre = require("hardhat");
const { ethers } = hre;
const addresses = require("./constant/addresses");
const abis = require("../constant/abis");
module.exports = async function() {
const [_, __, ___, wallet3] = await ethers.getSigners();
const instaIndex = new ethers.Contract(
addresses.core.instaIndex,
abis.core.instaIndex,
wallet3
);
const masterAddress = await instaIndex.master(); // TODO: make it constant?
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [masterAddress],
});
await wallet3.sendTransaction({
to: masterAddress,
value: ethers.utils.parseEther("10"),
});
return await ethers.getSigner(masterAddress);
};

View File

@ -1,18 +1,20 @@
const { ethers } = require("hardhat");
const impersonateAccounts = require("./impersonate");
import { Provider } from "@ethersproject/abstract-provider";
import { Signer } from "@ethersproject/abstract-signer";
import { ethers } from "hardhat";
import { impersonateAccounts } from "./impersonate";
const mineTx = async (tx) => {
const mineTx = async (tx: any) => {
await (await tx).wait();
};
const tokenMapping = {
const tokenMapping: Record<string, any> = {
usdc: {
impersonateSigner: "0xfcb19e6a322b27c06842a71e8c725399f049ae3a",
address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
abi: [
"function mint(address _to, uint256 _amount) external returns (bool);",
],
process: async function(owner, to, amt) {
process: async function(owner: Signer | Provider, to: any, amt: any) {
const contract = new ethers.Contract(this.address, this.abi, owner);
await mineTx(contract.mint(to, amt));
@ -22,7 +24,7 @@ const tokenMapping = {
impersonateSigner: "0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503",
abi: ["function transfer(address to, uint value)"],
address: "0x6b175474e89094c44da98b954eedeac495271d0f",
process: async function(owner, to, amt) {
process: async function(owner: Signer | Provider, to: any, amt: any) {
const contract = new ethers.Contract(this.address, this.abi, owner);
await mineTx(contract.transfer(to, amt));
},
@ -34,7 +36,7 @@ const tokenMapping = {
"function issue(uint amount)",
"function transfer(address to, uint value)",
],
process: async function(owner, address, amt) {
process: async function(owner: Signer | Provider, address: any, amt: any) {
const contract = new ethers.Contract(this.address, this.abi, owner);
await mineTx(contract.issue(amt));
@ -45,7 +47,7 @@ const tokenMapping = {
impersonateSigner: "0xCA06411bd7a7296d7dbdd0050DFc846E95fEBEB7",
address: "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",
abi: ["function mint(address _to, uint256 _amount) public returns (bool)"],
process: async function(owner, address, amt) {
process: async function(owner: Signer | Provider, address: any, amt: any) {
const contract = new ethers.Contract(this.address, this.abi, owner);
await mineTx(contract.mint(address, amt));
},
@ -54,20 +56,19 @@ const tokenMapping = {
impersonateSigner: "0x75e89d5979E4f6Fba9F97c104c2F0AFB3F1dcB88",
address: "0x6f40d4a6237c257fff2db00fa0510deeecd303eb",
abi: ["function transfer(address to, uint value)"],
process: async function(owner, address, amt) {
process: async function(owner: Signer | Provider, address: any, amt: any) {
const contract = new ethers.Contract(this.address, this.abi, owner);
await mineTx(contract.transfer(address, amt));
},
}
},
};
module.exports = async (tokenName, address, amt) => {
export async function addLiquidity(tokenName: string, address: any, amt: any) {
const [signer] = await ethers.getSigners();
tokenName = tokenName.toLowerCase();
if (!tokenMapping[tokenName]) {
throw new Error(
"Add liquidity doesn't support the following token: ",
tokenName
`Add liquidity doesn't support the following token: ${tokenName}`
);
}
@ -84,4 +85,4 @@ module.exports = async (tokenName, address, amt) => {
});
await token.process(impersonatedSigner, address, amt);
};
}

View File

@ -0,0 +1,11 @@
export const addresses: Record<string, any> = {
connectors: {
// basic: "0x6214f9c4F9700fc7a50B5f9aEEB819d647406Ac7",
// auth: "0xD6daA927ad756a4022858dddcc4E26137b30DB4D",
// "INSTAPOOL-A": "0x8f1e38c53af7bD2b2bE01b9580911b7Cca504F1b",
},
core: {
connectorsV2: "0x67fCE99Dd6d8d659eea2a1ac1b8881c57eb6592B",
instaIndex: "0x1eE00C305C51Ff3bE60162456A9B533C07cD9288",
},
};

View File

@ -0,0 +1,23 @@
export const tokens = {
eth: {
type: "token",
symbol: "ETH",
name: "Ethereum",
address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
decimals: 18,
},
dai: {
type: "token",
symbol: "DAI",
name: "DAI Stable",
address: "0xd586e7f844cea2f87f50152665bcbc2c279d8d70",
decimals: 18,
},
usdc: {
type: "token",
symbol: "USDC",
name: "USD Coin",
address: "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664",
decimals: 6,
},
};

View File

@ -0,0 +1,11 @@
export const addresses: Record<string, any> = {
connectors: {
// basic: "0x6214f9c4F9700fc7a50B5f9aEEB819d647406Ac7",
// auth: "0xD6daA927ad756a4022858dddcc4E26137b30DB4D",
// "INSTAPOOL-A": "0x8f1e38c53af7bD2b2bE01b9580911b7Cca504F1b",
},
core: {
connectorsV2: "0x67fCE99Dd6d8d659eea2a1ac1b8881c57eb6592B",
instaIndex: "0x1eE00C305C51Ff3bE60162456A9B533C07cD9288",
},
};

View File

@ -0,0 +1,23 @@
export const tokens = {
eth: {
type: "token",
symbol: "ETH",
name: "Ethereum",
address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
decimals: 18,
},
dai: {
type: "token",
symbol: "DAI",
name: "DAI Stable",
address: "0xd586e7f844cea2f87f50152665bcbc2c279d8d70",
decimals: 18,
},
usdc: {
type: "token",
symbol: "USDC",
name: "USD Coin",
address: "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664",
decimals: 6,
},
};

View File

@ -0,0 +1,29 @@
import { ethers } from "hardhat";
import { addresses as addressesPolygon } from "./polygon/addresses";
import { addresses as addressesArbitrum } from "./arbitrum/addresses";
import { addresses as addressesAvalanche } from "./avalanche/addresses";
import { addresses } from "./mainnet/addresses";
import { abis } from "../constant/abis";
import { abi } from "../../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json";
function getAddress(network: string | undefined) {
if (network === "polygon") return addressesPolygon.core.instaIndex;
else if (network === "arbitrum") return addressesArbitrum.core.instaIndex;
else if (network === "avalanche") return addressesAvalanche.core.instaIndex;
else return addresses.core.instaIndex;
}
export async function buildDSAv2(owner: any) {
const instaIndex = await ethers.getContractAt(
abis.core.instaIndex,
getAddress(String(process.env.networkType))
);
const tx = await instaIndex.build(owner, 2, owner);
const receipt = await tx.wait();
const event = receipt.events.find(
(a: { event: string }) => a.event === "LogAccountCreated"
);
return await ethers.getContractAt(abi, event.args.account);
}

33
scripts/tests/command.ts Normal file
View File

@ -0,0 +1,33 @@
import { execFile, spawn } from "child_process";
interface ICommand {
readonly cmd: string;
readonly args: string[];
readonly env: {
[param: string]: string;
};
}
export async function execScript(input: ICommand): Promise<number> {
return new Promise((resolve, reject) => {
let cmdEnv = Object.create(process.env);
for (let param in input.env) {
cmdEnv[param] = input.env[param];
}
const proc = spawn(input.cmd, [...input.args], {
env: cmdEnv,
shell: true,
stdio: "inherit",
});
proc.on("exit", (code) => {
if (code !== 0) {
reject(code);
return;
}
resolve(code);
});
});
}

View File

@ -0,0 +1,47 @@
import { addresses as addressesPolygon } from "./polygon/addresses";
import { addresses } from "./mainnet/addresses";
import { abis } from "../constant/abis";
import { addresses as addressesArbitrum } from "./arbitrum/addresses";
import { addresses as addressesAvalanche } from "./avalanche/addresses";
import hre from "hardhat";
import type { Signer, Contract } from "ethers";
import type { ContractJSON } from "ethereum-waffle/dist/esm/ContractJSON";
const { ethers, waffle } = hre;
const { deployContract } = waffle;
interface DeployInterface {
connectorName: string;
contractArtifact: ContractJSON;
signer: Signer;
connectors: Contract;
}
function getAddress(network: string | undefined) {
if (network === "polygon") return addressesPolygon;
else if (network === "arbitrum") return addressesArbitrum;
else if (network === "avalanche") return addressesAvalanche;
else return addresses;
}
export async function deployAndEnableConnector(
{
connectorName,
contractArtifact,
signer,
connectors
} : DeployInterface
) {
const connectorInstanace: Contract = await deployContract(signer, contractArtifact);
await connectors
.connect(signer)
.addConnectors([connectorName], [connectorInstanace.address]);
getAddress(String(process.env.networkType)).connectors[connectorName] =
connectorInstanace.address;
abis.connectors[connectorName] = contractArtifact.abi;
return connectorInstanace;
}

View File

@ -0,0 +1,13 @@
import hre from "hardhat";
const { web3 } = hre;
import { encodeSpells } from "./encodeSpells";
export default function encodeFlashcastData(spells: any) {
const encodeSpellsData = encodeSpells(spells);
let argTypes = ["string[]", "bytes[]"];
return web3.eth.abi.encodeParameters(argTypes, [
encodeSpellsData[0],
encodeSpellsData[1],
]);
};

View File

@ -0,0 +1,17 @@
import { web3 } from "hardhat";
import { abis } from "../constant/abis";
export function encodeSpells(spells: any[]) {
const targets = spells.map((a) => a.connector);
const calldatas = spells.map((a) => {
const functionName = a.method;
// console.log(functionName)
const abi = abis.connectors[a.connector].find((b: { name: any }) => {
return b.name === functionName;
});
// console.log(functionName)
if (!abi) throw new Error("Couldn't find function");
return web3.eth.abi.encodeFunctionCall(abi, a.args);
});
return [targets, calldatas];
}

View File

@ -0,0 +1,35 @@
import { ethers, network } from "hardhat";
import { addresses } from "./mainnet/addresses";
import { addresses as addressesPolygon } from "./polygon/addresses";
import { addresses as addressesArbitrum } from "./arbitrum/addresses";
import { addresses as addressesAvalanche } from "./avalanche/addresses";
import { abis } from "../constant/abis";
function getAddress(network: string | undefined) {
if (network === "polygon") return addressesPolygon.core.instaIndex;
else if (network === "arbitrum") return addressesArbitrum.core.instaIndex;
else if (network === "avalanche") return addressesAvalanche.core.instaIndex;
else return addresses.core.instaIndex;
}
export async function getMasterSigner() {
const [_, __, ___, wallet3] = await ethers.getSigners();
const instaIndex = new ethers.Contract(
getAddress(String(process.env.networkType)),
abis.core.instaIndex,
wallet3
);
const masterAddress = await instaIndex.master();
await network.provider.request({
method: "hardhat_impersonateAccount",
params: [masterAddress],
});
await network.provider.send("hardhat_setBalance", [
masterAddress,
"0x8ac7230489e80000", // 1e19 wei
]);
return await ethers.getSigner(masterAddress);
}

View File

@ -0,0 +1,44 @@
import { promises as fs } from "fs";
import { join } from "path";
import { execScript } from "./command";
let start: number, end: number;
async function testRunner() {
const chain = ["avalanche", "mainnet", "polygon"];
start = Date.now();
for (let ch of chain) {
console.log(`📗Running test for %c${ch}: `, "blue");
let path: string;
const testsPath = join(__dirname, "../../test", ch);
await fs.access(testsPath);
const availableTests = await fs.readdir(testsPath);
if (availableTests.length !== 0) {
for (let test of availableTests) {
path = join(testsPath, test);
path += "/*";
await execScript({
cmd: "npx",
args: ["hardhat", "test", path],
env: {
networkType: ch,
},
});
}
}
}
end = Date.now();
}
testRunner()
.then(() =>
console.log(
`🙌 finished running the test, total time taken ${(end - start) /
1000} sec`
)
)
.catch((err) => console.error("❌ failed due to error: ", err));

View File

@ -1,6 +1,6 @@
const { ethers, network } = require("hardhat");
import { ethers, network } from "hardhat";
module.exports = async (accounts) => {
export const impersonateAccounts = async (accounts: any) => {
const signers = [];
for (const account of accounts) {
await network.provider.request({
@ -10,6 +10,5 @@ module.exports = async (accounts) => {
signers.push(await ethers.getSigner(account));
}
return signers;
};

View File

@ -0,0 +1,11 @@
export const addresses: Record<string, any> = {
connectors: {
"basic": "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6",
"auth": "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9",
"INSTAPOOL-A": "0x5806af7ab22e2916fa582ff05731bf7c682387b2",
},
core: {
"connectorsV2": "0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11",
"instaIndex": "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723",
},
};

View File

@ -0,0 +1,23 @@
export const tokens = {
eth: {
type: "token",
symbol: "ETH",
name: "Ethereum",
address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
decimals: 18,
},
dai: {
type: "token",
symbol: "DAI",
name: "DAI Stable",
address: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
decimals: 18,
},
usdc: {
type: "token",
symbol: "USDC",
name: "USD Coin",
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
decimals: 6,
},
};

View File

@ -1,4 +1,4 @@
module.exports = {
export const addresses: Record<string, any> = {
connectors: {
basic: "0x1cAF5EC802ca602E98139AD96A8f2B7BC524264E",
auth: "0xf6474aD0dA75A0dE15D2c915e601D9f754B9e6fe",
@ -7,4 +7,4 @@ module.exports = {
connectorsV2: "0x2A00684bFAb9717C21271E0751BCcb7d2D763c88",
instaIndex: "0xA9B99766E6C676Cf1975c0D3166F96C0848fF5ad",
},
};
};

View File

@ -0,0 +1,30 @@
export const tokens = {
matic: {
type: "token",
symbol: "MATIC",
name: "Matic",
address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
decimals: 18,
},
eth: {
type: "token",
symbol: "ETH",
name: "Ethereum",
address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
decimals: 18,
},
dai: {
type: "token",
symbol: "DAI",
name: "DAI Stable",
address: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
decimals: 18,
},
usdc: {
type: "token",
symbol: "USDC",
name: "USD Coin",
address: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
decimals: 6,
},
};

View File

@ -0,0 +1,68 @@
import inquirer from "inquirer";
import { promises as fs } from "fs";
import { join } from "path";
import { execScript } from "./command";
let start: number, end: number;
async function testRunner() {
const { chain } = await inquirer.prompt([
{
name: "chain",
message: "What chain do you want to run tests on?",
type: "list",
choices: ["mainnet", "polygon", "avalanche", "arbitrum"],
},
]);
const testsPath = join(__dirname, "../../test", chain);
await fs.access(testsPath);
const availableTests = await fs.readdir(testsPath);
if (availableTests.length === 0) {
throw new Error(`No tests available for ${chain}`);
}
const { testName } = await inquirer.prompt([
{
name: "testName",
message: "For which resolver you want to run the tests?",
type: "list",
choices: ["all", ...availableTests],
},
]);
start = Date.now();
let path: string;
if (testName === "all") {
for (let test of availableTests) {
path = join(testsPath, test);
path += "/*";
await execScript({
cmd: "npx",
args: ["hardhat", "test", path],
env: {
networkType: chain,
},
});
}
} else {
path = join(testsPath, testName);
path += "/*";
await execScript({
cmd: "npx",
args: ["hardhat", "test", path],
env: {
networkType: chain,
},
});
}
end = Date.now();
}
testRunner()
.then(() =>
console.log(
`🙌 finished the test runner, time taken ${(end - start) / 1000} sec`
)
)
.catch((err) => console.error("❌ failed due to error: ", err));

View File

@ -1,370 +0,0 @@
const fs = require('fs')
const path = require('path')
const forbiddenStrings = ['selfdestruct']
const getConnectorsList = async (connectorsRootsDirs) => {
try {
const connectors = []
for (let index = 0; index < connectorsRootsDirs.length; index++) {
const dirs = [connectorsRootsDirs[index]]
while (dirs.length) {
const currentDir = dirs.pop()
const subs = fs.readdirSync(currentDir, { withFileTypes: true })
for (let index = 0; index < subs.length; index++) {
const sub = subs[index]
if (sub.isFile() && sub.name === 'main.sol') {
connectors.push(currentDir)
} else if (sub.isDirectory()) {
dirs.push(`${currentDir}/${sub.name}`)
}
}
}
}
return connectors.map(dir => ({ path: dir }))
} catch (error) {
return Promise.reject(error)
}
}
const checkCodeForbidden = async (code, codePath) => {
try {
const forbidden = []
for (let i1 = 0; i1 < forbiddenStrings.length; i1++) {
const forbiddenStr = forbiddenStrings[i1]
const strs = code.split('\n')
for (let i2 = 0; i2 < strs.length; i2++) {
if (strs[i2].includes(forbiddenStr)) {
forbidden.push(`found '${forbiddenStr}' in ${codePath}:${i2 + 1}`)
}
}
}
return forbidden
} catch (error) {
return Promise.reject(error)
}
}
const checkForbidden = async (parentPath, codePath = './main.sol') => {
try {
if (codePath.startsWith('@')) {
codePath = path.resolve('node_modules', `./${codePath}`)
} else {
codePath = path.resolve(parentPath, codePath)
}
const code = fs.readFileSync(codePath, { encoding: 'utf8' })
const forbidden = await checkCodeForbidden(code, codePath)
if (code.includes('import')) {
const importsPathes = code
.split('\n')
.filter(str => str.includes('import') && str.includes('from') && str.includes('.sol'))
.map(str => str.split('from')[1].replace(/["; ]/gi, ''))
for (let index = 0; index < importsPathes.length; index++) {
const forbiddenErrors = await checkForbidden(
path.parse(codePath).dir,
importsPathes[index]
)
forbidden.push(...forbiddenErrors)
}
}
return codePath.endsWith('main.sol') ? { forbiddenErrors: forbidden, code } : forbidden
} catch (error) {
return Promise.reject(error)
}
}
const checkEvents = async (connector) => {
try {
const errors = []
const warnings = []
const eventsPath = `${connector.path}/events.sol`
const mainPath = `${connector.path}/main.sol`
if (connector.events.length) {
const eventNames = []
for (let i1 = 0; i1 < connector.mainEvents.length; i1++) {
const mainEvent = connector.mainEvents[i1]
const name = mainEvent.split('(')[0]
eventNames.push(name)
const event = connector.events.find(e => e.split('(')[0].split(' ')[1] === name)
if (event) {
const mainEventArgs = mainEvent.split('(')[1].split(')')[0].split(',').map(a => a.trim())
const eventArgs = event.split('(')[1].split(')')[0].split(',').map(a => a.trim())
if (mainEventArgs.length !== eventArgs.length) {
errors.push(`arguments amount don't match for ${name} at ${mainPath}:${connector.mainEventsLines[i1]}`)
continue
}
for (let i2 = 0; i2 < mainEventArgs.length; i2++) {
if (!mainEventArgs[i2].startsWith(eventArgs[i2].split(' ')[0])) {
errors.push(`invalid argument #${i2 + 1} for ${name} at ${mainPath}:${connector.mainEventsLines[i1]}`)
}
}
} else {
errors.push(`event ${name} missing at ${eventsPath}`)
}
}
if (connector.mainEvents.length < connector.events.length) {
const deprecatedEvents = connector.events.filter(e => {
let used = false
for (let index = 0; index < eventNames.length; index++) {
if (e.split('(')[0].split(' ')[1] === eventNames[index]) used = true
}
return !used
})
warnings.push(`${deprecatedEvents.map(e => e.split('(')[0].split(' ')[1]).join(', ')} event(s) not used at ${connector.path}/main.sol`)
}
} else {
warnings.push(`missing events file for ${connector.path}/main.sol`)
}
return { eventsErrors: errors, eventsWarnings: warnings }
} catch (error) {
return Promise.reject(error)
}
}
const getCommments = async (strs) => {
try {
const comments = []
let type
for (let index = strs.length - 1; index >= 0; index--) {
const str = strs[index]
if (!type) {
if (str.trim().startsWith('//')) {
type = 'single'
} else if (str.trim().startsWith('*/')) {
type = 'multiple'
}
}
if (type === 'single' && str.trim().startsWith('//')) {
comments.push(str.replace(/[/]/gi, '').trim())
} else if (type === 'multiple' && !str.trim().startsWith('/**') && !str.trim().startsWith('*/')) {
comments.push(str.replace(/[*]/gi, '').trim())
} else if (type === 'single' && !str.trim().startsWith('//')) {
break
} else if (type === 'multiple' && str.trim().startsWith('/**')) {
break
}
}
return comments
} catch (error) {
return Promise.reject(error)
}
}
const parseCode = async (connector) => {
try {
const strs = connector.code.split('\n')
const events = []
const eventsFirstLines = []
let func = []
let funcs = []
let event = []
let mainEvents = []
let firstLine
let mainEventsLines = []
for (let index = 0; index < strs.length; index++) {
const str = strs[index]
if (str.includes('function') && !str.trim().startsWith('//')) {
func = [str]
firstLine = index + 1
} else if (func.length && !str.trim().startsWith('//')) {
func.push(str)
}
if (func.length && str.startsWith(`${func[0].split('function')[0]}}`)) {
funcs.push({
raw: func.map(str => str.trim()).join(' '),
comments: await getCommments(strs.slice(0, firstLine)),
firstLine
})
func = []
}
}
const allPublicFuncs = funcs
.filter(({ raw }) => {
return raw.includes('external') || raw.includes('public')
})
.map(f => {
const name = f.raw.split('(')[0].split('function')[1].trim()
return {
...f,
name
}
})
funcs = allPublicFuncs
.filter(({ raw }) => {
if (raw.includes('returns')) {
const returns = raw.split('returns')[1].split('(')[1].split(')')[0]
return returns.includes('string') && returns.includes('bytes')
}
return false
})
.map(f => {
const args = f.raw.split('(')[1].split(')')[0].split(',')
.map(arg => arg.trim())
.filter(arg => arg !== '')
return {
...f,
args
}
})
const eventsPath = `${connector.path}/events.sol`
if (fs.existsSync(eventsPath)) {
mainEvents = funcs
.map(({ raw }) => raw.split('_eventName')[2].trim().split('"')[1])
.filter(raw => !!raw)
mainEventsLines = mainEvents.map(me => strs.findIndex(str => str.includes(me)) + 1)
const eventsCode = fs.readFileSync(eventsPath, { encoding: 'utf8' })
const eventsStrs = eventsCode.split('\n')
for (let index = 0; index < eventsStrs.length; index++) {
const str = eventsStrs[index]
if (str.includes('event')) {
event = [str]
firstLine = index + 1
} else if (event.length && !str.trim().startsWith('//')) {
event.push(str)
}
if (event.length && str.includes(')')) {
events.push(event.map(str => str.trim()).join(' '))
eventsFirstLines.push(firstLine)
event = []
}
}
}
return {
...connector,
events,
eventsFirstLines,
mainEvents,
mainEventsLines,
funcs,
allPublicFuncs
}
} catch (error) {
return Promise.reject(error)
}
}
const checkComments = async (connector) => {
try {
const errors = []
for (let i1 = 0; i1 < connector.funcs.length; i1++) {
const func = connector.funcs[i1]
for (let i2 = 0; i2 < func.args.length; i2++) {
const argName = func.args[i2].split(' ').pop()
if (!func.comments.some(
comment => comment.startsWith('@param') && comment.split(' ')[1] === argName
)) {
errors.push(`argument ${argName} has no @param for function ${func.name} at ${connector.path}/main.sol:${func.firstLine}`)
}
}
const reqs = ['@dev', '@notice']
for (let i3 = 0; i3 < reqs.length; i3++) {
if (!func.comments.some(comment => comment.startsWith(reqs[i3]))) {
errors.push(`no ${reqs[i3]} for function ${func.name} at ${connector.path}/main.sol:${func.firstLine}`)
}
}
}
return errors
} catch (error) {
return Promise.reject(error)
}
}
const checkPublicFuncs = async (connector) => {
try {
const errors = []
for (let i1 = 0; i1 < connector.allPublicFuncs.length; i1++) {
const { raw, firstLine, name } = connector.allPublicFuncs[i1]
if (!raw.includes('payable')) {
errors.push(`public function ${name} is not payable at ${connector.path}/main.sol:${firstLine}`)
}
}
return errors
} catch (error) {
return Promise.reject(error)
}
}
const checkName = async (connector) => {
try {
const strs = connector.code.split('\n')
let haveName = false
for (let index = strs.length - 1; index > 0; index--) {
const str = strs[index]
if (str.includes('string') && str.includes('public') && str.includes('name = ')) {
haveName = true
}
}
return haveName ? [] : [`name variable missing in ${connector.path}/main.sol`]
} catch (error) {
return Promise.reject(error)
}
}
const checkHeadComments = async (connector) => {
try {
const errors = []
const strs = connector.code.split('\n')
let haveTitle = false
let haveDev = false
for (let index = 0; index < strs.length; index++) {
if (!strs[index].includes('{')) {
if (strs[index].includes('@title')) haveTitle = true
if (strs[index].includes('@dev')) haveDev = true
} else {
break
}
}
if (!haveTitle) errors.push(`@title missing in ${connector.path}/main.sol`)
if (!haveDev) errors.push(`@dev missing in ${connector.path}/main.sol`)
return errors
} catch (error) {
return Promise.reject(error)
}
}
async function checkMain () {
try {
const connectorsRootsDirsDefault = ['mainnet', 'polygon'].map(v=> `contracts/${v}/connectors`)
const customPathArg = process.argv.find(a => a.startsWith('connector='))
const connectorsRootsDirs = customPathArg
? [customPathArg.slice(10)]
: connectorsRootsDirsDefault
const errors = []
const warnings = []
const connectors = await getConnectorsList(connectorsRootsDirs)
for (let index = 0; index < connectors.length; index++) {
const { forbiddenErrors, code } = await checkForbidden(connectors[index].path)
connectors[index].code = code
connectors[index] = await parseCode(connectors[index])
const { eventsErrors, eventsWarnings } = await checkEvents(connectors[index])
const commentsErrors = await checkComments(connectors[index])
const nameErrors = await checkName(connectors[index])
const headCommentsErrors = await checkHeadComments(connectors[index])
const publicFuncsErrors = await checkPublicFuncs(connectors[index])
errors.push(...forbiddenErrors)
errors.push(...eventsErrors)
errors.push(...commentsErrors)
errors.push(...nameErrors)
errors.push(...headCommentsErrors)
errors.push(...publicFuncsErrors)
warnings.push(...eventsWarnings)
}
if (errors.length) {
console.log('\x1b[31m%s\x1b[0m', `Total errors: ${errors.length}`)
errors.forEach(error => console.log('\x1b[31m%s\x1b[0m', error))
} else {
console.log('\x1b[32m%s\x1b[0m', 'No Errors Found')
}
if (warnings.length) {
console.log('\x1b[33m%s\x1b[0m', `Total warnings: ${warnings.length}`)
warnings.forEach(warning => console.log('\x1b[33m%s\x1b[0m', warning))
} else {
console.log('\x1b[32m%s\x1b[0m', 'No Warnings Found')
}
if (errors.length) return Promise.reject(errors.join('\n'))
} catch (error) {
console.error('check execution error:', error)
}
}
module.exports = checkMain

448
status-checks/check.ts Normal file
View File

@ -0,0 +1,448 @@
import * as fs from "fs";
import * as path from "path";
const forbiddenStrings: any = ["selfdestruct"];
const getConnectorsList= async (connectorsRootsDirs: string | any[]): Promise<Record<string, any>> => {
try {
const connectors = [];
for (let index = 0; index < connectorsRootsDirs.length; index++) {
const dirs = [connectorsRootsDirs[index]];
while (dirs.length) {
const currentDir = dirs.pop();
const subs = fs.readdirSync(currentDir, { withFileTypes: true });
for (let index = 0; index < subs.length; index++) {
const sub = subs[index];
if (sub.isFile() && sub.name === "main.sol") {
connectors.push(currentDir);
} else if (sub.isDirectory()) {
dirs.push(`${currentDir}/${sub.name}`);
}
}
}
}
return connectors.map((dir) => ({ path: dir }));
} catch (error) {
return Promise.reject(error);
}
};
const checkCodeForbidden = async (code: string, codePath: string) => {
try {
const forbidden = [];
for (let i1 = 0; i1 < forbiddenStrings.length; i1++) {
const forbiddenStr = forbiddenStrings[i1];
const strs = code.split("\n");
for (let i2 = 0; i2 < strs.length; i2++) {
if (strs[i2].includes(forbiddenStr)) {
forbidden.push(`found '${forbiddenStr}' in ${codePath}:${i2 + 1}`);
}
}
}
return forbidden;
} catch (error) {
return Promise.reject(error);
}
};
const checkForbidden = async (parentPath: string, codePath = "./main.sol") => {
try {
if (codePath.startsWith("@")) {
codePath = path.resolve("node_modules", `./${codePath}`);
} else {
codePath = path.resolve(parentPath, codePath);
}
const code = fs.readFileSync(codePath, { encoding: "utf8" });
const forbidden: any = await checkCodeForbidden(code, codePath);
if (code.includes("import")) {
const importsPathes = code
.split("\n")
.filter(
(str) =>
str.includes("import") &&
str.includes("from") &&
str.includes(".sol")
)
.map((str) => str.split("from")[1].replace(/["; ]/gi, ""));
for (let index = 0; index < importsPathes.length; index++) {
const forbiddenErrors = await checkForbidden(
path.parse(codePath).dir,
importsPathes[index]
);
forbidden.push(...forbiddenErrors);
}
}
return codePath.endsWith("main.sol")
? { forbiddenErrors: forbidden, code }
: forbidden;
} catch (error) {
return Promise.reject(error);
}
};
const checkEvents = async (connector: {
path: any;
events?: any;
mainEvents?: any;
mainEventsLines?: any;
}) => {
try {
const errors = [];
const warnings = [];
const eventsPath = `${connector.path}/events.sol`;
const mainPath = `${connector.path}/main.sol`;
if (connector.events.length) {
const eventNames = [];
for (let i1 = 0; i1 < connector.mainEvents.length; i1++) {
const mainEvent = connector.mainEvents[i1];
const name = mainEvent.split("(")[0];
eventNames.push(name);
const event = connector.events.find(
(e: string) => e.split("(")[0].split(" ")[1] === name
);
if (event) {
const mainEventArgs = mainEvent
.split("(")[1]
.split(")")[0]
.split(",")
.map((a: string) => a.trim());
const eventArgs = event
.split("(")[1]
.split(")")[0]
.split(",")
.map((a: string) => a.trim());
if (mainEventArgs.length !== eventArgs.length) {
errors.push(
`arguments amount don't match for ${name} at ${mainPath}:${connector.mainEventsLines[i1]}`
);
continue;
}
for (let i2 = 0; i2 < mainEventArgs.length; i2++) {
if (!mainEventArgs[i2].startsWith(eventArgs[i2].split(" ")[0])) {
errors.push(
`invalid argument #${i2 + 1} for ${name} at ${mainPath}:${
connector.mainEventsLines[i1]
}`
);
}
}
} else {
errors.push(`event ${name} missing at ${eventsPath}`);
}
}
if (connector.mainEvents.length < connector.events.length) {
const deprecatedEvents = connector.events.filter((e) => {
let used = false;
for (let index = 0; index < eventNames.length; index++) {
if (e.split("(")[0].split(" ")[1] === eventNames[index])
used = true;
}
return !used;
});
warnings.push(
`${deprecatedEvents
.map((e: string) => e.split("(")[0].split(" ")[1])
.join(", ")} event(s) not used at ${connector.path}/main.sol`
);
}
} else {
warnings.push(`missing events file for ${connector.path}/main.sol`);
}
return { eventsErrors: errors, eventsWarnings: warnings };
} catch (error) {
return Promise.reject(error);
}
};
const getCommments = async (strs: string | any[]) => {
try {
const comments = [];
let type: string;
for (let index = strs.length - 1; index >= 0; index--) {
const str = strs[index];
if (!type) {
if (str.trim().startsWith("//")) {
type = "single";
} else if (str.trim().startsWith("*/")) {
type = "multiple";
}
}
if (type === "single" && str.trim().startsWith("//")) {
comments.push(str.replace(/[/]/gi, "").trim());
} else if (
type === "multiple" &&
!str.trim().startsWith("/**") &&
!str.trim().startsWith("*/")
) {
comments.push(str.replace(/[*]/gi, "").trim());
} else if (type === "single" && !str.trim().startsWith("//")) {
break;
} else if (type === "multiple" && str.trim().startsWith("/**")) {
break;
}
}
return comments;
} catch (error) {
return Promise.reject(error);
}
};
const parseCode = async (connector: { path: any; code?: any }) => {
try {
const strs = connector.code.split("\n");
const events = [];
const eventsFirstLines = [];
let func = [];
let funcs = [];
let event = [];
let mainEvents = [];
let firstLine: number;
let mainEventsLines = [];
for (let index = 0; index < strs.length; index++) {
const str = strs[index];
if (str.includes("function") && !str.trim().startsWith("//")) {
func = [str];
firstLine = index + 1;
} else if (func.length && !str.trim().startsWith("//")) {
func.push(str);
}
if (func.length && str.startsWith(`${func[0].split("function")[0]}}`)) {
funcs.push({
raw: func.map((str) => str.trim()).join(" "),
comments: await getCommments(strs.slice(0, firstLine)),
firstLine,
});
func = [];
}
}
const allPublicFuncs = funcs
.filter(({ raw }) => {
return raw.includes("external") || raw.includes("public");
})
.map((f) => {
const name = f.raw
.split("(")[0]
.split("function")[1]
.trim();
return {
...f,
name,
};
});
funcs = allPublicFuncs
.filter(({ raw }) => {
if (raw.includes("returns")) {
const returns = raw
.split("returns")[1]
.split("(")[1]
.split(")")[0];
return returns.includes("string") && returns.includes("bytes");
}
return false;
})
.map((f) => {
const args = f.raw
.split("(")[1]
.split(")")[0]
.split(",")
.map((arg) => arg.trim())
.filter((arg) => arg !== "");
return {
...f,
args,
};
});
const eventsPath = `${connector.path}/events.sol`;
if (fs.existsSync(eventsPath)) {
mainEvents = funcs
.map(
({ raw }) =>
raw
.split("_eventName")[2]
.trim()
.split('"')[1]
)
.filter((raw) => !!raw);
mainEventsLines = mainEvents.map(
(me) => strs.findIndex((str: string | any[]) => str.includes(me)) + 1
);
const eventsCode = fs.readFileSync(eventsPath, { encoding: "utf8" });
const eventsStrs = eventsCode.split("\n");
for (let index = 0; index < eventsStrs.length; index++) {
const str = eventsStrs[index];
if (str.includes("event")) {
event = [str];
firstLine = index + 1;
} else if (event.length && !str.trim().startsWith("//")) {
event.push(str);
}
if (event.length && str.includes(")")) {
events.push(event.map((str) => str.trim()).join(" "));
eventsFirstLines.push(firstLine);
event = [];
}
}
}
return {
...connector,
events,
eventsFirstLines,
mainEvents,
mainEventsLines,
funcs,
allPublicFuncs,
};
} catch (error) {
return Promise.reject(error);
}
};
const checkComments = async (connector) => {
try {
const errors = [];
for (let i1 = 0; i1 < connector.funcs.length; i1++) {
const func = connector.funcs[i1];
for (let i2 = 0; i2 < func.args.length; i2++) {
const argName = func.args[i2].split(" ").pop();
if (
!func.comments.some(
(comment: string) =>
comment.startsWith("@param") && comment.split(" ")[1] === argName
)
) {
errors.push(
`argument ${argName} has no @param for function ${func.name} at ${connector.path}/main.sol:${func.firstLine}`
);
}
}
const reqs = ["@dev", "@notice"];
for (let i3 = 0; i3 < reqs.length; i3++) {
if (!func.comments.some((comment) => comment.startsWith(reqs[i3]))) {
errors.push(
`no ${reqs[i3]} for function ${func.name} at ${connector.path}/main.sol:${func.firstLine}`
);
}
}
}
return errors;
} catch (error) {
return Promise.reject(error);
}
};
const checkPublicFuncs = async (connector: {
path: any;
allPublicFuncs?: any;
}) => {
try {
const errors = [];
for (let i1 = 0; i1 < connector.allPublicFuncs.length; i1++) {
const { raw, firstLine, name } = connector.allPublicFuncs[i1];
if (!raw.includes("payable")) {
errors.push(
`public function ${name} is not payable at ${connector.path}/main.sol:${firstLine}`
);
}
}
return errors;
} catch (error) {
return Promise.reject(error);
}
};
const checkName = async (connector: { path: any; code?: any }) => {
try {
const strs = connector.code.split("\n");
let haveName = false;
for (let index = strs.length - 1; index > 0; index--) {
const str = strs[index];
if (
str.includes("string") &&
str.includes("public") &&
str.includes("name = ")
) {
haveName = true;
}
}
return haveName
? []
: [`name variable missing in ${connector.path}/main.sol`];
} catch (error) {
return Promise.reject(error);
}
};
const checkHeadComments = async (connector: { path: any; code?: any }) => {
try {
const errors = [];
const strs = connector.code.split("\n");
let haveTitle = false;
let haveDev = false;
for (let index = 0; index < strs.length; index++) {
if (!strs[index].includes("{")) {
if (strs[index].includes("@title")) haveTitle = true;
if (strs[index].includes("@dev")) haveDev = true;
} else {
break;
}
}
if (!haveTitle) errors.push(`@title missing in ${connector.path}/main.sol`);
if (!haveDev) errors.push(`@dev missing in ${connector.path}/main.sol`);
return errors;
} catch (error) {
return Promise.reject(error);
}
};
async function checkMain() {
try {
const connectorsRootsDirsDefault = ["mainnet", "polygon"].map(
(v) => `contracts/${v}/connectors`
);
const customPathArg = process.argv.find((a) => a.startsWith("connector="));
const connectorsRootsDirs = customPathArg
? [customPathArg.slice(10)]
: connectorsRootsDirsDefault;
const errors = [];
const warnings = [];
const connectors = await getConnectorsList(connectorsRootsDirs);
for (let index = 0; index < connectors.length; index++) {
const { forbiddenErrors, code } = await checkForbidden(
connectors[index].path
);
connectors[index].code = code;
connectors[index] = await parseCode(connectors[index]);
const { eventsErrors, eventsWarnings } = await checkEvents(
connectors[index]
);
const commentsErrors = await checkComments(connectors[index]);
const nameErrors = await checkName(connectors[index]);
const headCommentsErrors = await checkHeadComments(connectors[index]);
const publicFuncsErrors = await checkPublicFuncs(connectors[index]);
errors.push(...forbiddenErrors);
errors.push(...eventsErrors);
errors.push(...commentsErrors);
errors.push(...nameErrors);
errors.push(...headCommentsErrors);
errors.push(...publicFuncsErrors);
warnings.push(...eventsWarnings);
}
if (errors.length) {
console.log("\x1b[31m%s\x1b[0m", `Total errors: ${errors.length}`);
errors.forEach((error) => console.log("\x1b[31m%s\x1b[0m", error));
} else {
console.log("\x1b[32m%s\x1b[0m", "No Errors Found");
}
if (warnings.length) {
console.log("\x1b[33m%s\x1b[0m", `Total warnings: ${warnings.length}`);
warnings.forEach((warning) => console.log("\x1b[33m%s\x1b[0m", warning));
} else {
console.log("\x1b[32m%s\x1b[0m", "No Warnings Found");
}
if (errors.length) return Promise.reject(errors.join("\n"));
} catch (error) {
console.error("check execution error:", error);
}
}
export default checkMain;

View File

@ -1,13 +0,0 @@
const checkMain = require('./check')
module.exports = [{
name: 'Solidity check',
callback: async () => {
try {
await checkMain()
return 'Check passed!'
} catch (error) {
throw new Error('Check failed!')
}
}
}]

15
status-checks/checks.ts Normal file
View File

@ -0,0 +1,15 @@
import checkMain from "./check";
export default [
{
name: "Solidity check",
callback: async () => {
try {
await checkMain();
return "Check passed!";
} catch (error) {
throw new Error("Check failed!");
}
},
},
];

View File

@ -1,9 +0,0 @@
const checkMain = require('./check');
(async function runHusky () {
try {
await checkMain()
} catch (error) {
process.exit(1)
}
})()

View File

@ -0,0 +1,9 @@
import checkMain from "./check";
(async function runHusky() {
try {
await checkMain();
} catch (error) {
process.exit(1);
}
})();

View File

@ -1,54 +0,0 @@
const cp = require('child_process')
const fetch = require('node-fetch')
const checks = require('./checks')
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
function getCurrentCommitSha () {
return cp
.execSync('git rev-parse HEAD')
.toString()
.trim()
}
// The SHA provied by GITHUB_SHA is the merge (PR) commit.
// We need to get the current commit sha ourself.
const sha = getCurrentCommitSha()
async function setStatus (context, state, description) {
return fetch(`https://api.github.com/repos/${owner}/${repo}/statuses/${sha}`, {
method: 'POST',
body: JSON.stringify({
state,
description,
context
}),
headers: {
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
'Content-Type': 'application/json'
}
})
}
(async () => {
console.log(`Starting status checks for commit ${sha}`)
// Run in parallel
await Promise.all(
checks.map(async check => {
const { name, callback } = check
await setStatus(name, 'pending', 'Running check..')
try {
const response = await callback()
await setStatus(name, 'success', response)
} catch (err) {
const message = err ? err.message : 'Something went wrong'
await setStatus(name, 'failure', message)
}
})
)
console.log('Finished status checks')
})()

56
status-checks/index.ts Normal file
View File

@ -0,0 +1,56 @@
import * as cp from "child_process";
import fetch from "node-fetch";
import checks from "./checks";
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
function getCurrentCommitSha() {
return cp
.execSync("git rev-parse HEAD")
.toString()
.trim();
}
// The SHA provied by GITHUB_SHA is the merge (PR) commit.
// We need to get the current commit sha ourself.
const sha = getCurrentCommitSha();
async function setStatus(context: any, state: string, description: string) {
return fetch(
`https://api.github.com/repos/${owner}/${repo}/statuses/${sha}`,
{
method: "POST",
body: JSON.stringify({
state,
description,
context,
}),
headers: {
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
"Content-Type": "application/json",
},
}
);
}
(async () => {
console.log(`Starting status checks for commit ${sha}`);
// Run in parallel
await Promise.all(
checks.map(async (check: { name: any; callback: any }) => {
const { name, callback } = check;
await setStatus(name, "pending", "Running check..");
try {
const response = await callback();
await setStatus(name, "success", response);
} catch (err) {
const message = err ? err.message : "Something went wrong";
await setStatus(name, "failure", message);
}
})
);
console.log("Finished status checks");
})();

View File

@ -1,4 +1,3 @@
# Check run
use

View File

@ -1,22 +1,23 @@
const { expect } = require("chai");
const hre = require("hardhat");
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle;
import { BigNumberish } from "@ethersproject/bignumber";
import { Contract } from "@ethersproject/contracts";
import { expect } from "chai";
import hre, { artifacts } from "hardhat";
const { ethers } = hre;
const USDC_ADDR = "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8";
const WETH_ADDR = "0x82af49447d8a07e3bd95bd0d56f35241523fbab1";
describe("Uniswap-sell-beta", function() {
let UniswapSellBeta, uniswapSellBeta;
describe("Uniswap-sell-beta", function () {
let UniswapSellBeta, uniswapSellBeta: Contract;
async function setBalance(address) {
await network.provider.send("hardhat_setBalance", [
async function setBalance(address: string) {
await hre.network.provider.send("hardhat_setBalance", [
address,
ethers.utils.parseEther("10.0").toHexString(),
]);
}
async function impersonate(owner, account, token0, decimals) {
async function impersonate(owner: string, account: any, token0: string, decimals: BigNumberish | undefined) {
const tokenArtifact = await artifacts.readArtifact(
"@openzeppelin/contracts/token/ERC20/IERC20.sol:IERC20"
);
@ -50,8 +51,8 @@ describe("Uniswap-sell-beta", function() {
}
beforeEach(async () => {
const account0 = "0x36cc7B13029B5DEe4034745FB4F24034f3F2ffc6";
const account1 = "0xce2cc46682e9c6d5f174af598fb4931a9c0be68e";
const account0 = "0xa067668661c84476afcdc6fa5d758c4c01c34352";
const account1 = "0x0db3fe3b770c95a0b99d1ed6f2627933466c0dd8";
const [owner, add1, add2] = await ethers.getSigners();
await impersonate(owner.address, account1, USDC_ADDR, 6);
@ -64,7 +65,7 @@ describe("Uniswap-sell-beta", function() {
await uniswapSellBeta.deployed();
});
it("Should have contracts deployed.", async function() {
it("Should have contracts deployed.", async function () {
expect(uniswapSellBeta.address).to.exist;
});

View File

@ -1,139 +0,0 @@
const { expect } = require("chai");
const hre = require("hardhat");
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/constant/constant");
const tokens = require("../../scripts/constant/tokens");
const connectV2CompoundArtifacts = require("../../artifacts/contracts/mainnet/connectors/b.protocol/compound/main.sol/ConnectV2BCompound.json")
describe("B.Compound", function () {
const connectorName = "B.COMPOUND-TEST-A"
let dsaWallet0
let masterSigner;
let instaConnectorsV2;
let connector;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 13300000,
},
},
],
});
masterSigner = await getMasterSigner(wallet3)
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectV2CompoundArtifacts,
signer: masterSigner,
connectors: instaConnectorsV2
})
console.log("Connector address", connector.address)
})
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(await connector.name()).to.be.equal("B.Compound-v1.0");
});
describe("DSA wallet setup", function () {
it("Should build DSA v2", async function () {
dsaWallet0 = await buildDSAv2(wallet0.address)
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("10")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
});
});
describe("Main", function () {
it("Should deposit ETH in Compound", async function () {
const amount = ethers.utils.parseEther("1") // 1 ETH
const spells = [
{
connector: connectorName,
method: "deposit",
args: ["ETH-A", amount, 0, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9"));
});
it("Should borrow and payback DAI from Compound", async function () {
const amount = ethers.utils.parseEther("100") // 100 DAI
const setId = "83478237"
const spells = [
{
connector: connectorName,
method: "borrow",
args: ["DAI-A", amount, 0, setId]
},
{
connector: connectorName,
method: "payback",
args: ["DAI-A", 0, setId, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9"));
});
it("Should deposit all ETH in Compound", async function () {
const spells = [
{
connector: connectorName,
method: "deposit",
args: ["ETH-A", constants.max_value, 0, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("0"));
});
it("Should withdraw all ETH from Compound", async function () {
const spells = [
{
connector: connectorName,
method: "withdraw",
args: ["ETH-A", constants.max_value, 0, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
});
})
})

View File

@ -1,28 +1,27 @@
const { expect } = require("chai");
const hre = require("hardhat");
const abis = require("../../scripts/constant/abis");
const addresses = require("../../scripts/constant/addresses");
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector");
const getMasterSigner = require("../../scripts/getMasterSigner");
const buildDSAv2 = require("../../scripts/buildDSAv2");
const ConnectV2AaveV1 = require("../../artifacts/contracts/mainnet/connectors/aave/v1/main.sol/ConnectV2AaveV1.json");
const { parseEther } = require("@ethersproject/units");
const encodeSpells = require("../../scripts/encodeSpells");
const tokens = require("../../scripts/constant/tokens");
const constants = require("../../scripts/constant/constant");
const addLiquidity = require("../../scripts/addLiquidity");
import hre from "hardhat";
import { expect } from "chai";
import { abis } from "../../../scripts/constant/abis";
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { ConnectV2AaveV1, ConnectV2AaveV1__factory } from "../../../typechain";
import { parseEther } from "@ethersproject/units";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { tokens } from "../../../scripts/tests/mainnet/tokens";
import { constants } from "../../../scripts/constant/constant";
import { addLiquidity } from "../../../scripts/tests/addLiquidity";
const { ethers } = hre;
import type { Signer, Contract } from "ethers";
const ALCHEMY_ID = process.env.ALCHEMY_ID;
describe("Aave V1", function() {
describe("Aave V1", function () {
const connectorName = "AAVEV1-TEST-A";
let wallet0, wallet1;
let dsaWallet0;
let instaConnectorsV2;
let connector;
let masterSigner;
let wallet0: Signer, wallet1: Signer;
let dsaWallet0: Contract;
let instaConnectorsV2: Contract;
let connector: any;
let masterSigner: Signer;
before(async () => {
try {
@ -31,6 +30,7 @@ describe("Aave V1", function() {
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 12796965,
},
@ -45,7 +45,7 @@ describe("Aave V1", function() {
);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2AaveV1,
contractArtifact: ConnectV2AaveV1__factory,
signer: masterSigner,
connectors: instaConnectorsV2,
});
@ -58,16 +58,16 @@ describe("Aave V1", function() {
it("should have contracts deployed", async () => {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("DSA wallet setup", function() {
it("Should build DSA v2", async function() {
dsaWallet0 = await buildDSAv2(wallet0.address);
describe("DSA wallet setup", function () {
it("Should build DSA v2", async function () {
dsaWallet0 = await buildDSAv2(wallet0.getAddress());
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function() {
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: parseEther("10"),
@ -78,8 +78,8 @@ describe("Aave V1", function() {
});
});
describe("Main", function() {
it("should deposit ETH in Aave V1", async function() {
describe("Main", function () {
it("should deposit ETH in Aave V1", async function () {
const amt = parseEther("1");
const spells = [
{
@ -91,7 +91,7 @@ describe("Aave V1", function() {
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
@ -100,7 +100,7 @@ describe("Aave V1", function() {
);
});
it("Should borrow and payback DAI from Aave V1", async function() {
it("Should borrow and payback DAI from Aave V1", async function () {
const amt = parseEther("100"); // 100 DAI
// add a little amount of dai to cover any shortfalls
@ -122,14 +122,14 @@ describe("Aave V1", function() {
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
ethers.utils.parseEther("9")
);
});
it("Should deposit all ETH in Aave V1", async function() {
it("Should deposit all ETH in Aave V1", async function () {
const spells = [
{
connector: connectorName,
@ -140,14 +140,14 @@ describe("Aave V1", function() {
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
ethers.utils.parseEther("0")
);
});
it("Should withdraw all ETH from Aave V1", async function() {
it("Should withdraw all ETH from Aave V1", async function () {
const spells = [
{
connector: connectorName,
@ -158,7 +158,7 @@ describe("Aave V1", function() {
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
ethers.utils.parseEther("10")

View File

@ -1,33 +1,34 @@
const { expect } = require("chai");
const hre = require("hardhat");
const abis = require("../../scripts/constant/abis");
const addresses = require("../../scripts/constant/addresses");
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector");
const getMasterSigner = require("../../scripts/getMasterSigner");
const buildDSAv2 = require("../../scripts/buildDSAv2");
const ConnectV2AaveV2 = require("../../artifacts/contracts/mainnet/connectors/aave/v2/main.sol/ConnectV2AaveV2.json");
const { parseEther } = require("@ethersproject/units");
const encodeSpells = require("../../scripts/encodeSpells");
const tokens = require("../../scripts/constant/tokens");
const constants = require("../../scripts/constant/constant");
const addLiquidity = require("../../scripts/addLiquidity");
import { expect } from "chai";
import hre from "hardhat";
import { abis } from "../../../scripts/constant/abis";
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { ConnectV2AaveV2, ConnectV2AaveV2__factory } from "../../../typechain";
import { parseEther } from "@ethersproject/units";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { tokens } from "../../../scripts/tests/mainnet/tokens";
import { constants } from "../../../scripts/constant/constant";
import { addLiquidity } from "../../../scripts/tests/addLiquidity";
const { ethers } = hre;
import type { Signer, Contract } from "ethers";
describe("Aave V2", function() {
describe("Aave V2", function () {
const connectorName = "AAVEV2-TEST-A";
let connector: any;
let wallet0, wallet1;
let dsaWallet0;
let instaConnectorsV2;
let connector;
let masterSigner;
let wallet0: Signer, wallet1:Signer;
let dsaWallet0: any;
let instaConnectorsV2: Contract;
let masterSigner: Signer;
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 12796965,
},
@ -42,7 +43,7 @@ describe("Aave V2", function() {
);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2AaveV2,
contractArtifact: ConnectV2AaveV2__factory,
signer: masterSigner,
connectors: instaConnectorsV2,
});
@ -52,16 +53,16 @@ describe("Aave V2", function() {
it("should have contracts deployed", async () => {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("DSA wallet setup", function() {
it("Should build DSA v2", async function() {
dsaWallet0 = await buildDSAv2(wallet0.address);
describe("DSA wallet setup", function () {
it("Should build DSA v2", async function () {
dsaWallet0 = await buildDSAv2(wallet0.getAddress());
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function() {
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: parseEther("10"),
@ -72,8 +73,8 @@ describe("Aave V2", function() {
});
});
describe("Main", function() {
it("should deposit ETH in Aave V2", async function() {
describe("Main", function () {
it("should deposit ETH in Aave V2", async function () {
const amt = parseEther("1");
const spells = [
{
@ -85,7 +86,7 @@ describe("Aave V2", function() {
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
@ -94,7 +95,7 @@ describe("Aave V2", function() {
);
});
it("Should borrow and payback DAI from Aave V2", async function() {
it("Should borrow and payback DAI from Aave V2", async function () {
const amt = parseEther("100"); // 100 DAI
const setId = "83478237";
const spells = [
@ -112,14 +113,14 @@ describe("Aave V2", function() {
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
ethers.utils.parseEther("9")
);
});
it("Should borrow and payback half DAI from Aave V2", async function() {
it("Should borrow and payback half DAI from Aave V2", async function () {
const amt = parseEther("100"); // 100 DAI
// const setId = "83478237";
await addLiquidity("dai", dsaWallet0.address, parseEther("1"));
@ -138,7 +139,7 @@ describe("Aave V2", function() {
let tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
ethers.utils.parseEther("9")
@ -154,14 +155,14 @@ describe("Aave V2", function() {
tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
ethers.utils.parseEther("9")
);
});
it("Should deposit all ETH in Aave V2", async function() {
it("Should deposit all ETH in Aave V2", async function () {
const spells = [
{
connector: connectorName,
@ -172,14 +173,14 @@ describe("Aave V2", function() {
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
ethers.utils.parseEther("0")
);
});
it("Should withdraw all ETH from Aave V2", async function() {
it("Should withdraw all ETH from Aave V2", async function () {
const spells = [
{
connector: connectorName,
@ -190,7 +191,7 @@ describe("Aave V2", function() {
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
ethers.utils.parseEther("10")
@ -215,7 +216,7 @@ describe("Aave V2", function() {
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
.cast(...encodeSpells(spells), wallet1.getAddress());
await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
ethers.utils.parseEther("10")

View File

@ -0,0 +1,138 @@
import { expect } from "chai";
import hre from "hardhat";
const { web3, deployments, waffle, ethers } = hre; //check
const { provider, deployContract } = waffle
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"
import { encodeSpells } from "../../../scripts/tests/encodeSpells"
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { abis } from "../../../scripts/constant/abis";
import { constants } from "../../../scripts/constant/constant";
import { ConnectV2BCompound__factory } from "../../../typechain";
import type { Signer, Contract } from "ethers";
describe("B.Compound", function () {
const connectorName = "B.COMPOUND-TEST-A"
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: Contract;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 13300000,
},
},
],
});
masterSigner = await getMasterSigner()
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2BCompound__factory,
signer: masterSigner,
connectors: instaConnectorsV2
})
console.log("Connector address", connector.address)
})
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
expect(await connector.name()).to.be.equal("B.Compound-v1.0");
});
describe("DSA wallet setup", function () {
it("Should build DSA v2", async function () {
dsaWallet0 = await buildDSAv2(wallet0.address)
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("10")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
});
});
describe("Main", function () {
it("Should deposit ETH in Compound", async function () {
const amount = ethers.utils.parseEther("1") // 1 ETH
const spells = [
{
connector: connectorName,
method: "deposit",
args: ["ETH-A", amount, 0, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9"));
});
it("Should borrow and payback DAI from Compound", async function () {
const amount = ethers.utils.parseEther("100") // 100 DAI
const setId = "83478237"
const spells = [
{
connector: connectorName,
method: "borrow",
args: ["DAI-A", amount, 0, setId]
},
{
connector: connectorName,
method: "payback",
args: ["DAI-A", 0, setId, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9"));
});
it("Should deposit all ETH in Compound", async function () {
const spells = [
{
connector: connectorName,
method: "deposit",
args: ["ETH-A", constants.max_value, 0, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("0"));
});
it("Should withdraw all ETH from Compound", async function () {
const spells = [
{
connector: connectorName,
method: "withdraw",
args: ["ETH-A", constants.max_value, 0, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
});
})
})

View File

@ -1,37 +1,33 @@
const { expect } = require("chai");
const hre = require("hardhat");
const { web3, deployments, waffle, ethers } = hre;
import { expect } from "chai";
import hre from "hardhat";
const { web3, deployments, waffle, ethers } = hre; //check
const { provider, deployContract } = waffle
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/constant/constant");
const tokens = require("../../scripts/constant/tokens");
const connectorLiquityArtifacts = require("../../artifacts/contracts/mainnet/connectors/b.protocol/liquity/main.sol/ConnectV2BLiquity.json")
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"
import { encodeSpells } from "../../../scripts/tests/encodeSpells"
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"
import { abis } from "../../../scripts/constant/abis";
import { ConnectV2BLiquity__factory } from "../../../typechain";
import type { Signer, Contract } from "ethers";
import { addresses } from "../../../scripts/tests/mainnet/addresses";
const LUSD_WHALE = "0x66017D22b0f8556afDd19FC67041899Eb65a21bb" // stability pool
const BAMM_ADDRESS = "0x0d3AbAA7E088C2c82f54B2f47613DA438ea8C598"
describe("B.Liquity", function () {
const connectorName = "B.LIQUITY-TEST-A"
let dsaWallet0;
let dsaWallet1;
let masterSigner;
let instaConnectorsV2;
let connector;
let manager;
let vat;
let lusd;
let bammToken;
let stabilityPool;
let dsaWallet0: any;
let dsaWallet1: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: Contract;
let manager: Contract;
let vat: Contract;
let lusd: Contract;
let bammToken: Contract;
let stabilityPool: Contract;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
@ -41,17 +37,18 @@ describe("B.Liquity", function () {
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 12996875,
},
},
],
});
masterSigner = await getMasterSigner(wallet3)
masterSigner = await getMasterSigner()
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectorLiquityArtifacts,
contractArtifact: ConnectV2BLiquity__factory,
signer: masterSigner,
connectors: instaConnectorsV2
})
@ -73,7 +70,7 @@ describe("B.Liquity", function () {
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
expect(await connector.name()).to.be.equal("B.Liquity-v1");
});
@ -178,12 +175,12 @@ describe("B.Liquity", function () {
})
})
function veryClose(n1, n2) {
function veryClose(n1: any, n2: any) {
n1 = web3.utils.toBN(n1)
n2 = web3.utils.toBN(n2)
_10000 = web3.utils.toBN(10000)
_9999 = web3.utils.toBN(9999)
let _10000 = web3.utils.toBN(10000)
let _9999 = web3.utils.toBN(9999)
if (n1.mul(_10000).lt(n2.mul(_9999))) return false
if (n2.mul(_10000).lt(n1.mul(_9999))) return false

View File

@ -1,31 +1,29 @@
const { expect } = require("chai");
const hre = require("hardhat");
import { expect } from "chai";
import hre from "hardhat";
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/constant/constant");
const tokens = require("../../scripts/constant/tokens");
const connectorMakerArtifacts = require("../../artifacts/contracts/mainnet/connectors/b.protocol/makerdao/main.sol/ConnectV2BMakerDAO.json")
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"
import { encodeSpells } from "../../../scripts/tests/encodeSpells"
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { abis } from "../../../scripts/constant/abis";
import { tokens } from "../../../scripts/tests/mainnet/tokens";
import { ConnectV2BMakerDAO__factory } from "../../../typechain";
import type { Signer, Contract } from "ethers";
describe("B.Maker", function () {
const connectorName = "B.MAKER-TEST-A"
let dsaWallet0;
let dsaWallet1;
let masterSigner;
let instaConnectorsV2;
let connector;
let manager;
let vat;
let dai;
let dsaWallet0: any;
let dsaWallet1: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
let manager: any;
let vat: any;
let dai: any;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
@ -35,17 +33,18 @@ describe("B.Maker", function () {
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 12696000,
},
},
],
});
masterSigner = await getMasterSigner(wallet3)
masterSigner = await getMasterSigner()
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectorMakerArtifacts,
contractArtifact: ConnectV2BMakerDAO__factory,
signer: masterSigner,
connectors: instaConnectorsV2
})
@ -67,7 +66,7 @@ describe("B.Maker", function () {
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
expect(await connector.name()).to.be.equal("B.MakerDAO-v1.0");
});
@ -96,9 +95,9 @@ describe("B.Maker", function () {
});
describe("Main", function () {
let vault
let ilk
let urn
let vault: any;
let ilk: any;
let urn: any;
it("Should open ETH-A vault Maker", async function () {
vault = Number(await manager.cdpi()) + 1
@ -314,7 +313,7 @@ describe("B.Maker", function () {
})
})
async function daiToArt(vat, ilk, dai) {
async function daiToArt(vat: any, ilk: any, dai: any) {
const ilks = await vat.ilks(ilk)
const rate = ilks[1] // second parameter
const _1e27 = ethers.utils.parseEther("1000000000") // 1e9 * 1e18
@ -323,12 +322,12 @@ async function daiToArt(vat, ilk, dai) {
return art.add(1)
}
function veryClose(n1, n2) {
function veryClose(n1: any, n2: any) {
n1 = web3.utils.toBN(n1)
n2 = web3.utils.toBN(n2)
_10000 = web3.utils.toBN(10000)
_9999 = web3.utils.toBN(9999)
let _10000 = web3.utils.toBN(10000)
let _9999 = web3.utils.toBN(9999)
if (n1.mul(_10000).lt(n2.mul(_9999))) return false
if (n2.mul(_10000).lt(n1.mul(_9999))) return false

View File

@ -1,21 +1,18 @@
const { expect } = require("chai");
const hre = require("hardhat");
import { expect } from "chai"
import hre from "hardhat"
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle
const { abi: implementationsABI } = require("../../scripts/constant/abi/core/InstaImplementations.json")
import { abi } from "../../../scripts/constant/abi/core/InstaImplementations.json"
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"
import { encodeSpells } from "../../../scripts/tests/encodeSpells"
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"
import { addresses } from "../../../scripts/tests/mainnet/addresses"
import { abis } from "../../../scripts/constant/abis"
import type { Signer, Contract } from "ethers";
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/constant/constant");
const tokens = require("../../scripts/constant/tokens");
const connectV2BasicERC1155Artifacts = require("../../artifacts/contracts/mainnet/connectors/basic-ERC1155/main.sol/ConnectV2BasicERC1155.json")
const erc1155Artifacts = require("../../artifacts/@openzeppelin/contracts/token/ERC1155/IERC1155.sol/IERC1155.json")
import { ConnectV2BasicERC1155__factory, IERC1155__factory } from "../../../typechain";
const TOKEN_CONTRACT_ADDR = "0x1ca3262009b21F944e6b92a2a88D039D06F1acFa";
const TOKEN_OWNER_ADDR = "0x1ca3262009b21F944e6b92a2a88D039D06F1acFa";
@ -26,13 +23,15 @@ const implementationsMappingAddr = "0xCBA828153d3a85b30B5b912e1f2daCac5816aE9D"
describe("BASIC-ERC1155", function () {
const connectorName = "BASIC-ERC1155-A"
let dsaWallet0
let masterSigner;
let instaConnectorsV2;
let connector;
let nftContract;
let tokenOwner;
let instaImplementationsMapping;
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: Contract;
let nftContract: Contract;
let tokenOwner: any;
let instaImplementationsMapping: any;
let InstaAccountV2DefaultImpl: any;
let instaAccountV2DefaultImpl: any;
const wallets = provider.getWallets()
@ -43,6 +42,7 @@ describe("BASIC-ERC1155", function () {
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 13300000,
},
@ -54,26 +54,25 @@ describe("BASIC-ERC1155", function () {
params: [TOKEN_OWNER_ADDR],
});
await network.provider.send("hardhat_setBalance", [
await hre.network.provider.send("hardhat_setBalance", [
TOKEN_OWNER_ADDR,
"0x1000000000000000",
"0x10000000000000000",
]);
// get tokenOwner
tokenOwner = await ethers.getSigner(
TOKEN_OWNER_ADDR
);
nftContract = await ethers.getContractAt(erc1155Artifacts.abi, TOKEN_CONTRACT_ADDR)
masterSigner = await getMasterSigner(wallet3)
nftContract = await ethers.getContractAt(IERC1155__factory.abi, TOKEN_CONTRACT_ADDR)
masterSigner = await getMasterSigner()
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
instaImplementationsMapping = await ethers.getContractAt(implementationsABI, implementationsMappingAddr);
instaImplementationsMapping = await ethers.getContractAt(abi, implementationsMappingAddr);
InstaAccountV2DefaultImpl = await ethers.getContractFactory("InstaDefaultImplementation")
instaAccountV2DefaultImpl = await InstaAccountV2DefaultImpl.deploy(addresses.core.instaIndex);
await instaAccountV2DefaultImpl.deployed()
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectV2BasicERC1155Artifacts,
contractArtifact: ConnectV2BasicERC1155__factory,
signer: masterSigner,
connectors: instaConnectorsV2
})
@ -83,17 +82,15 @@ describe("BASIC-ERC1155", function () {
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("Implementations", function () {
it("Should add default implementation to mapping.", async function () {
const tx = await instaImplementationsMapping.connect(masterSigner).setDefaultImplementation(instaAccountV2DefaultImpl.address);
await tx.wait()
expect(await instaImplementationsMapping.defaultImplementation()).to.be.equal(instaAccountV2DefaultImpl.address);
});
});
describe("DSA wallet setup", function () {

View File

@ -1,21 +1,18 @@
const { expect } = require("chai");
const hre = require("hardhat");
import { expect } from "chai";
import hre, { network } from "hardhat";
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle
const { abi: implementationsABI } = require("../../scripts/constant/abi/core/InstaImplementations.json")
import { abi } from "../../../scripts/constant/abi/core/InstaImplementations.json"
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"
import { encodeSpells } from "../../../scripts/tests/encodeSpells"
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"
import { addresses } from "../../../scripts/tests/mainnet/addresses"
import { abis } from "../../../scripts/constant/abis"
import type { Signer, Contract } from "ethers";
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/constant/constant");
const tokens = require("../../scripts/constant/tokens");
const connectV2BasicERC721Artifacts = require("../../artifacts/contracts/mainnet/connectors/basic-ERC721/main.sol/ConnectV2BasicERC721.json")
const erc721Artifacts = require("../../artifacts/@openzeppelin/contracts/token/ERC721/IERC721.sol/IERC721.json")
import { ConnectV2BasicERC721__factory, IERC721__factory } from "../../../typechain";
const TOKEN_CONTRACT_ADDR = "0x4d695c615a7aacf2d7b9c481b66045bb2457dfde";
const TOKEN_OWNER_ADDR = "0x8c6b10d42ff08e56133fca0dac75e1931b1fcc23";
@ -26,14 +23,15 @@ const implementationsMappingAddr = "0xCBA828153d3a85b30B5b912e1f2daCac5816aE9D"
describe("BASIC-ERC721", function () {
const connectorName = "BASIC-ERC721-A"
let dsaWallet0
let masterSigner;
let instaConnectorsV2;
let connector;
let nftContract;
let tokenOwner;
let instaImplementationsMapping;
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
let nftContract: any;
let tokenOwner: any;
let instaImplementationsMapping: any;
let InstaAccountV2DefaultImpl: any;
let instaAccountV2DefaultImpl: any;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
@ -43,6 +41,7 @@ describe("BASIC-ERC721", function () {
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 13300000,
},
@ -56,24 +55,24 @@ describe("BASIC-ERC721", function () {
await network.provider.send("hardhat_setBalance", [
TOKEN_OWNER_ADDR,
"0x1000000000000000",
"0x10000000000000000",
]);
// get tokenOwner
tokenOwner = await ethers.getSigner(
TOKEN_OWNER_ADDR
);
nftContract = await ethers.getContractAt(erc721Artifacts.abi, TOKEN_CONTRACT_ADDR)
masterSigner = await getMasterSigner(wallet3)
nftContract = await ethers.getContractAt(IERC721__factory.abi, TOKEN_CONTRACT_ADDR)
masterSigner = await getMasterSigner()
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
instaImplementationsMapping = await ethers.getContractAt(implementationsABI, implementationsMappingAddr);
instaImplementationsMapping = await ethers.getContractAt(abi, implementationsMappingAddr);
InstaAccountV2DefaultImpl = await ethers.getContractFactory("InstaDefaultImplementation")
instaAccountV2DefaultImpl = await InstaAccountV2DefaultImpl.deploy(addresses.core.instaIndex);
await instaAccountV2DefaultImpl.deployed()
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectV2BasicERC721Artifacts,
contractArtifact: ConnectV2BasicERC721__factory,
signer: masterSigner,
connectors: instaConnectorsV2
})
@ -83,11 +82,10 @@ describe("BASIC-ERC721", function () {
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("Implementations", function () {
it("Should add default implementation to mapping.", async function () {
const tx = await instaImplementationsMapping.connect(masterSigner).setDefaultImplementation(instaAccountV2DefaultImpl.address);
await tx.wait()

View File

@ -1,27 +1,26 @@
const { expect } = require("chai");
const hre = require("hardhat");
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle
import { expect } from "chai";
import hre from "hardhat";
const { waffle, ethers } = hre;
const { provider, deployContract} = waffle
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
import type { Signer, Contract } from "ethers";
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/constant/constant");
const tokens = require("../../scripts/constant/tokens");
const connectV2CompoundArtifacts = require("../../artifacts/contracts/mainnet/connectors/compound/main.sol/ConnectV2Compound.json")
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { abis } from "../../../scripts/constant/abis";
import { constants } from "../../../scripts/constant/constant";
import { ConnectV2Compound__factory } from "../../../typechain";
describe("Compound", function () {
const connectorName = "COMPOUND-TEST-A"
let dsaWallet0
let masterSigner;
let instaConnectorsV2;
let connector;
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
@ -31,17 +30,18 @@ describe("Compound", function () {
params: [
{
forking: {
//@ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 13300000,
},
},
],
});
masterSigner = await getMasterSigner(wallet3)
masterSigner = await getMasterSigner()
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectV2CompoundArtifacts,
contractArtifact: ConnectV2Compound__factory,
signer: masterSigner,
connectors: instaConnectorsV2
})
@ -51,7 +51,7 @@ describe("Compound", function () {
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("DSA wallet setup", function () {

View File

@ -1,28 +1,26 @@
const { expect } = require("chai");
const hre = require("hardhat");
import { expect } from "chai";
import hre from "hardhat";
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const encodeFlashcastData = require("../../scripts/encodeFlashcastData.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"
import { encodeSpells } from "../../../scripts/tests/encodeSpells"
import encodeFlashcastData from "../../../scripts/tests/encodeFlashcastData"
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/constant/constant");
const tokens = require("../../scripts/constant/tokens");
const connectV2CompoundArtifacts = require("../../artifacts/contracts/mainnet/connectors/compound/main.sol/ConnectV2Compound.json")
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { abis } from "../../../scripts/constant/abis";
import type { Signer, Contract } from "ethers";
import { ConnectV2Compound__factory } from "../../../typechain";
describe("Instapool", function () {
const connectorName = "COMPOUND-TEST-A"
let dsaWallet0
let masterSigner;
let instaConnectorsV2;
let connector;
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
@ -32,17 +30,18 @@ describe("Instapool", function () {
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 13300000,
},
},
],
});
masterSigner = await getMasterSigner(wallet3)
masterSigner = await getMasterSigner()
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectV2CompoundArtifacts,
contractArtifact: ConnectV2Compound__factory,
signer: masterSigner,
connectors: instaConnectorsV2
})
@ -52,7 +51,7 @@ describe("Instapool", function () {
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("DSA wallet setup", function () {

View File

@ -69,7 +69,7 @@ const COLL_SURPLUS_ABI = [
"function getCollateral(address _account) external view returns (uint)",
];
module.exports = {
export default {
TROVE_MANAGER_ADDRESS,
TROVE_MANAGER_ABI,
BORROWER_OPERATIONS_ADDRESS,

View File

@ -1,45 +1,43 @@
const hre = require("hardhat");
const hardhatConfig = require("../../hardhat.config");
import hre from "hardhat";
import { ethers } from "hardhat";
import hardhatConfig from "../../../hardhat.config";
// Instadapp deployment and testing helpers
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js");
const encodeSpells = require("../../scripts/encodeSpells.js");
const getMasterSigner = require("../../scripts/getMasterSigner");
const buildDSAv2 = require("../../scripts/buildDSAv2");
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"
import { encodeSpells } from "../../../scripts/tests/encodeSpells"
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"
// Instadapp instadappAddresses/ABIs
const instadappAddresses = require("../../scripts/constant/addresses");
const instadappAbi = require("../../scripts/constant/abis");
// Instadapp addresses/ABIs
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { abis } from "../../../scripts/constant/abis";
// Instadapp Liquity Connector artifacts
const connectV2LiquityArtifacts = require("../../artifacts/contracts/mainnet/connectors/liquity/main.sol/ConnectV2Liquity.json");
const connectV2BasicV1Artifacts = require("../../artifacts/contracts/mainnet/connectors/basic/main.sol/ConnectV2Basic.json");
const { ethers } = require("hardhat");
import { ConnectV2Liquity__factory, ConnectV2Basic__factory } from "../../../typechain";
// Instadapp uses a fake address to represent native ETH
const { eth_addr: ETH_ADDRESS } = require("../../scripts/constant/constant");
import { constants } from "../../../scripts/constant/constant";
import type { Signer, Contract, BigNumber } from "ethers";
const LIQUITY_CONNECTOR = "LIQUITY-v1-TEST";
const LUSD_GAS_COMPENSATION = hre.ethers.utils.parseUnits("200", 18); // 200 LUSD gas compensation repaid after loan repayment
const LIQUIDATABLE_TROVES_BLOCK_NUMBER = 12478159; // Deterministic block number for tests to run against, if you change this, tests will break.
const JUSTIN_SUN_ADDRESS = "0x903d12bf2c57a29f32365917c706ce0e1a84cce3"; // LQTY whale address
const LIQUIDATABLE_TROVE_ADDRESS = "0xafbeb4cb97f3b08ec2fe07ef0dac15d37013a347"; // Trove which is liquidatable at blockNumber: LIQUIDATABLE_TROVES_BLOCK_NUMBER
const MAX_GAS = hardhatConfig.networks.hardhat.blockGasLimit; // Maximum gas limit (12000000)
// @ts-ignore
const MAX_GAS = hardhatConfig.networks.hardhat.blockGasLimit ?? 12000000; // Maximum gas limit (12000000)
const INSTADAPP_BASIC_V1_CONNECTOR = "Basic-v1";
const ETH = constants.native_address
const openTroveSpell = async (
dsa,
signer,
depositAmount,
borrowAmount,
upperHint,
lowerHint,
maxFeePercentage
dsa: any,
signer: Signer,
depositAmount: any,
borrowAmount: any,
upperHint: any,
lowerHint: any,
maxFeePercentage: any
) => {
let address = signer.address;
if (signer.address === undefined) {
address = await signer.getAddress();
}
let address = await signer.getAddress();
const openTroveSpell = {
connector: LIQUITY_CONNECTOR,
@ -63,9 +61,9 @@ const openTroveSpell = async (
};
const createDsaTrove = async (
dsa,
signer,
liquity,
dsa: any,
signer: any,
liquity: any,
depositAmount = hre.ethers.utils.parseEther("5"),
borrowAmount = hre.ethers.utils.parseUnits("2000", 18)
) => {
@ -86,32 +84,31 @@ const createDsaTrove = async (
);
};
const sendToken = async (token, amount, from, to) => {
const sendToken = async (token: any, amount: any, from: any, to: any) => {
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [from],
});
const signer = await hre.ethers.provider.getSigner(from);
const signer = hre.ethers.provider.getSigner(from);
return await token.connect(signer).transfer(to, amount, {
gasPrice: 0,
});
return await token.connect(signer).transfer(to, amount);
};
const resetInitialState = async (walletAddress, contracts, isDebug = false) => {
const resetInitialState = async (walletAddress: any, contracts: any, isDebug = false) => {
const liquity = await deployAndConnect(contracts, isDebug);
const dsa = await buildDSAv2(walletAddress);
return [liquity, dsa];
};
const resetHardhatBlockNumber = async (blockNumber) => {
const resetHardhatBlockNumber = async (blockNumber: number) => {
return await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: hardhatConfig.networks.hardhat.forking.url,
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber,
},
},
@ -119,31 +116,33 @@ const resetHardhatBlockNumber = async (blockNumber) => {
});
};
const deployAndConnect = async (contracts, isDebug = false) => {
const deployAndConnect = async (contracts: any, isDebug = false) => {
// Pin Liquity tests to a particular block number to create deterministic state (Ether price etc.)
await resetHardhatBlockNumber(LIQUIDATABLE_TROVES_BLOCK_NUMBER);
const liquity = {
troveManager: null,
borrowerOperations: null,
stabilityPool: null,
lusdToken: null,
lqtyToken: null,
activePool: null,
priceFeed: null,
hintHelpers: null,
sortedTroves: null,
staking: null,
collSurplus: null,
type Liquidity = {
troveManager: Contract,
borrowerOperations: Contract,
stabilityPool: Contract,
lusdToken: Contract,
lqtyToken: Contract,
activePool: Contract,
priceFeed: Contract,
hintHelpers: Contract,
sortedTroves: Contract,
staking: Contract,
collSurplus: Contract,
};
const liquity = {} as Liquidity
const masterSigner = await getMasterSigner();
const instaConnectorsV2 = await ethers.getContractAt(
instadappAbi.core.connectorsV2,
instadappAddresses.core.connectorsV2
abis.core.connectorsV2,
addresses.core.connectorsV2
);
const connector = await deployAndEnableConnector({
connectorName: LIQUITY_CONNECTOR,
contractArtifact: connectV2LiquityArtifacts,
contractArtifact: ConnectV2Liquity__factory,
signer: masterSigner,
connectors: instaConnectorsV2,
});
@ -152,7 +151,7 @@ const deployAndConnect = async (contracts, isDebug = false) => {
const basicConnector = await deployAndEnableConnector({
connectorName: "Basic-v1",
contractArtifact: connectV2BasicV1Artifacts,
contractArtifact: ConnectV2Basic__factory,
signer: masterSigner,
connectors: instaConnectorsV2,
});
@ -226,7 +225,7 @@ const deployAndConnect = async (contracts, isDebug = false) => {
return liquity;
};
const getTroveInsertionHints = async (depositAmount, borrowAmount, liquity) => {
const getTroveInsertionHints = async (depositAmount: BigNumber, borrowAmount: BigNumber, liquity: any) => {
const nominalCR = await liquity.hintHelpers.computeNominalCR(
depositAmount,
borrowAmount
@ -260,7 +259,7 @@ const getTroveInsertionHints = async (depositAmount, borrowAmount, liquity) => {
let randomSeed = 4223;
const getRedemptionHints = async (amount, liquity) => {
const getRedemptionHints = async (amount: any, liquity: any) => {
const ethPrice = await liquity.priceFeed.callStatic.fetchPrice();
const [
firstRedemptionHint,
@ -300,7 +299,7 @@ const getRedemptionHints = async (amount, liquity) => {
};
};
const redeem = async (amount, from, wallet, liquity) => {
const redeem = async (amount: any, from: any, wallet: { address: any; }, liquity: any) => {
await sendToken(liquity.lusdToken, amount, from, wallet.address);
const {
partialRedemptionHintNicr,
@ -326,7 +325,7 @@ const redeem = async (amount, from, wallet, liquity) => {
);
};
module.exports = {
export default {
deployAndConnect,
resetInitialState,
createDsaTrove,
@ -340,5 +339,5 @@ module.exports = {
LIQUIDATABLE_TROVE_ADDRESS,
MAX_GAS,
INSTADAPP_BASIC_V1_CONNECTOR,
ETH_ADDRESS,
ETH,
};

View File

@ -1,21 +1,22 @@
const { ethers, network } = require("hardhat");
const chai = require("chai");
const chaiPromise = require("chai-as-promised");
const { solidity } = require("ethereum-waffle");
import hre, { ethers, network } from "hardhat";
import chai from "chai";
import chaiPromise from "chai-as-promised";
import { solidity } from "ethereum-waffle";
import type { Signer, Contract } from "ethers";
chai.use(chaiPromise);
chai.use(solidity);
const { expect } = chai;
const getMapping = (address, signer) => {
const getMapping = (address: string, signer: Signer) => {
return ethers.getContractAt("InstaMappingController", address, signer);
};
describe("Test InstaMapping contract", () => {
let account, instaMaster;
let mappingAddress;
let masterMapping;
let account: any, instaMaster: any;
let mappingAddress: any;
let masterMapping: any;
const indexInterfaceAddress = "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723";
const testRoleAddress = "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723";
@ -25,6 +26,7 @@ describe("Test InstaMapping contract", () => {
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 12796965,
},

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +1,19 @@
const { expect } = require("chai");
const hre = require("hardhat");
import { expect } from "chai";
import hre from "hardhat";
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle;
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js");
const buildDSAv2 = require("../../scripts/buildDSAv2");
const encodeSpells = require("../../scripts/encodeSpells.js");
const encodeFlashcastData = require("../../scripts/encodeFlashcastData.js");
const getMasterSigner = require("../../scripts/getMasterSigner");
const addLiquidity = require("../../scripts/addLiquidity");
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { addLiquidity } from "../../../scripts/tests/addLiquidity";
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { abis } from "../../../scripts/constant/abis";
import type { Signer, Contract } from "ethers";
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/constant/constant");
const tokens = require("../../scripts/constant/tokens");
const {
abi: nftManagerAbi,
} = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json");
const connectV2UniswapV3Artifacts = require("../../artifacts/contracts/mainnet/connectors/uniswap/v3/main.sol/ConnectV2UniswapV3.json");
const { eth } = require("../../scripts/constant/tokens");
const { BigNumber } = require("ethers");
import { abi } from "@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json";
import { ConnectV2UniswapV3__factory } from "../../../typechain";
const FeeAmount = {
LOW: 500,
@ -28,7 +21,7 @@ const FeeAmount = {
HIGH: 10000,
};
const TICK_SPACINGS = {
const TICK_SPACINGS: Record<number, number> = {
500: 10,
3000: 60,
10000: 200,
@ -37,18 +30,18 @@ const TICK_SPACINGS = {
const USDT_ADDR = "0xdac17f958d2ee523a2206206994597c13d831ec7";
const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f";
let tokenIds = [];
let liquidities = [];
let tokenIds: any[] = [];
let liquidities: any[] = [];
const abiCoder = ethers.utils.defaultAbiCoder;
describe("UniswapV3", function() {
const connectorName = "UniswapV3-v1";
let dsaWallet0;
let masterSigner;
let instaConnectorsV2;
let connector;
let nftManager;
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: Contract;
let nftManager: Contract;
const wallets = provider.getWallets();
const [wallet0, wallet1, wallet2, wallet3] = wallets;
@ -58,24 +51,25 @@ describe("UniswapV3", function() {
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 13005785,
},
},
],
});
masterSigner = await getMasterSigner(wallet3);
masterSigner = await getMasterSigner();
instaConnectorsV2 = await ethers.getContractAt(
abis.core.connectorsV2,
addresses.core.connectorsV2
);
nftManager = await ethers.getContractAt(
nftManagerAbi,
abi,
"0xC36442b4a4522E871399CD717aBDD847Ab11FE88"
);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectV2UniswapV3Artifacts,
contractArtifact: ConnectV2UniswapV3__factory,
signer: masterSigner,
connectors: instaConnectorsV2,
});
@ -85,7 +79,7 @@ describe("UniswapV3", function() {
it("Should have contracts deployed.", async function() {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("DSA wallet setup", function() {
@ -131,7 +125,7 @@ describe("UniswapV3", function() {
it("Should mint successfully", async function() {
const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH
const daiAmount = ethers.utils.parseEther("400"); // 1 ETH
const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12); // 1 ETH
const usdtAmount = Number(ethers.utils.parseEther("400")) / Math.pow(10, 12); // 1 ETH
const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
const getIds = ["0", "0"];
@ -196,14 +190,14 @@ describe("UniswapV3", function() {
dsaWallet0.on(
"LogCast",
(
origin,
sender,
value,
targetNames,
targets,
eventNames,
eventParams,
event
origin: any,
sender: any,
value: any,
targetNames: any,
targets: any,
eventNames: any,
eventParams: any,
event: any
) => {
const params = abiCoder.decode(
["uint256", "uint256", "uint256", "uint256", "int24", "int24"],
@ -239,8 +233,6 @@ describe("UniswapV3", function() {
it("Should deposit successfully", async function() {
const daiAmount = ethers.utils.parseEther("400"); // 1 ETH
const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH
const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12); // 1 ETH
const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
const getIds = ["0", "0"];
const setId = "0";
@ -269,14 +261,14 @@ describe("UniswapV3", function() {
dsaWallet0.on(
"LogCast",
(
origin,
sender,
value,
targetNames,
targets,
eventNames,
eventParams,
event
origin: any,
sender: any,
value: any,
targetNames: any,
targets: any,
eventNames: any,
eventParams: any,
event: any
) => {
const params = abiCoder.decode(
["uint256", "uint256", "uint256", "uint256"],
@ -368,7 +360,7 @@ describe("UniswapV3", function() {
});
});
const getMinTick = (tickSpacing) =>
const getMinTick = (tickSpacing: number) =>
Math.ceil(-887272 / tickSpacing) * tickSpacing;
const getMaxTick = (tickSpacing) =>
const getMaxTick = (tickSpacing: number) =>
Math.floor(887272 / tickSpacing) * tickSpacing;

View File

@ -1,20 +1,20 @@
const { expect } = require("chai");
const hre = require("hardhat");
const { waffle, ethers } = hre;
import { expect } from "chai";
import hre from "hardhat";
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
const addLiquidity = require("../../scripts/addLiquidity");
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { addLiquidity } from "../../../scripts/tests/addLiquidity";
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const { abi: nftManagerAbi } = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json")
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { abis } from "../../../scripts/constant/abis";
import { abi } from "@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json"
import type { Signer, Contract } from "ethers";
const connectV2UniswapStakerArtifacts = require("../../artifacts/contracts/mainnet/connectors/uniswap/v3_staker/main.sol/ConnectV2UniswapV3Staker.json");
const connectV2UniswapV3Artifacts = require("../../artifacts/contracts/mainnet/connectors/uniswap/v3/main.sol/ConnectV2UniswapV3.json");
import { ConnectV2UniswapV3Staker__factory, ConnectV2UniswapV3__factory } from "../../../typechain";
const FeeAmount = {
LOW: 500,
@ -22,7 +22,7 @@ const FeeAmount = {
HIGH: 10000,
}
const TICK_SPACINGS = {
const TICK_SPACINGS: Record<number, number> = {
500: 10,
3000: 60,
10000: 200
@ -32,18 +32,19 @@ const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f"
const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
const INST_ADDR = "0x6f40d4a6237c257fff2db00fa0510deeecd303eb"
let tokenIds = []
let tokenIds: any[] = []
const abiCoder = ethers.utils.defaultAbiCoder
describe("UniswapV3", function () {
const connectorStaker = "UniswapStaker-v1"
const connectorUniswap = "UniswapV3-v1"
let dsaWallet0
let masterSigner;
let instaConnectorsV2;
let connector;
let startTime, endTime;
let dsaWallet0: any
let masterSigner: Signer;
let instaConnectorsV2: any;
let connector: any;
let startTime: any, endTime: any;
let nftManager: Contract;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
@ -53,26 +54,27 @@ describe("UniswapV3", function () {
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 13300000,
},
},
],
});
masterSigner = await getMasterSigner(wallet3)
masterSigner = await getMasterSigner()
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
nftManager = await ethers.getContractAt(nftManagerAbi, "0xC36442b4a4522E871399CD717aBDD847Ab11FE88");
nftManager = await ethers.getContractAt(abi, "0xC36442b4a4522E871399CD717aBDD847Ab11FE88");
connector = await deployAndEnableConnector({
connectorName: connectorStaker,
contractArtifact: connectV2UniswapStakerArtifacts,
contractArtifact: ConnectV2UniswapV3Staker__factory,
signer: masterSigner,
connectors: instaConnectorsV2
})
console.log("Connector address", connector.address)
uniswapConnector = await deployAndEnableConnector({
let uniswapConnector = await deployAndEnableConnector({
connectorName: connectorUniswap,
contractArtifact: connectV2UniswapV3Artifacts,
contractArtifact: ConnectV2UniswapV3__factory,
signer: masterSigner,
connectors: instaConnectorsV2
});
@ -81,7 +83,7 @@ describe("UniswapV3", function () {
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("DSA wallet setup", function () {
@ -161,7 +163,7 @@ describe("UniswapV3", function () {
let receipt = await tx.wait()
let castEvent = new Promise((resolve, reject) => {
dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => {
dsaWallet0.on('LogCast', (origin: any, sender: any, value: any, targetNames: any, targets: any, eventNames: any, eventParams: any, event: any) => {
const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[0]);
const params1 = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[1]);
tokenIds.push(params[0]);
@ -181,7 +183,7 @@ describe("UniswapV3", function () {
let event = await castEvent
let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address)
console.log("Balance", balance)
console.log("Balance", balance.toString())
});
it("Should create incentive successfully", async function () {
@ -213,9 +215,9 @@ describe("UniswapV3", function () {
let receipt = await tx.wait()
let castEvent = new Promise((resolve, reject) => {
dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => {
const params = abiCoder.decode(["bytes32","address","address","uint256","uint256","uint256"], eventParams[0]);
const params1 = abiCoder.decode(["bytes32","address","address","uint256","uint256","uint256"], eventParams[1]);
dsaWallet0.on('LogCast', (origin: any, sender: any, value: any, targetNames: any, targets: any, eventNames: any, eventParams: any, event: any) => {
const params = abiCoder.decode(["bytes32", "address", "address", "uint256", "uint256", "uint256"], eventParams[0]);
const params1 = abiCoder.decode(["bytes32", "address", "address", "uint256", "uint256", "uint256"], eventParams[1]);
event.removeListener();
resolve({ start: [params[3], params1[3]], end: [params[4], params1[4]] });
@ -226,7 +228,7 @@ describe("UniswapV3", function () {
}, 60000)
});
let event = await castEvent
let event: any = await castEvent
startTime = event.start;
endTime = event.end;
});
@ -275,7 +277,7 @@ describe("UniswapV3", function () {
let receipt = await tx.wait()
let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address)
console.log("Balance", balance)
console.log("Balance", balance.toString())
});
it("Should claim rewards successfully", async function () {
@ -287,6 +289,8 @@ describe("UniswapV3", function () {
ethAddress,
"1000",
],
},
{
connector: connectorStaker,
method: "claimRewards",
args: [
@ -344,10 +348,10 @@ describe("UniswapV3", function () {
let receipt = await tx.wait()
let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address)
console.log("Balance", balance)
console.log("Balance", balance.toString())
});
})
})
const getMinTick = (tickSpacing) => Math.ceil(-887272 / tickSpacing) * tickSpacing
const getMaxTick = (tickSpacing) => Math.floor(887272 / tickSpacing) * tickSpacing
const getMinTick = (tickSpacing: number) => Math.ceil(-887272 / tickSpacing) * tickSpacing
const getMaxTick = (tickSpacing: number) => Math.floor(887272 / tickSpacing) * tickSpacing

View File

@ -0,0 +1,189 @@
import { expect } from "chai";
import hre from "hardhat";
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle;
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { addresses } from "../../../scripts/tests/mainnet/addresses";
import { abis } from "../../../scripts/constant/abis";
import { tokens } from "../../../scripts/tests/mainnet/tokens";
import { Signer, Contract, BigNumber } from "ethers";
import { ConnectV2YearnV2__factory } from "../../../typechain";
const toBytes32 = (bn: BigNumber) => {
return ethers.utils.hexlify(ethers.utils.zeroPad(bn.toHexString(), 32));
};
const setStorageAt = async (address: string, index: string, value: string) => {
await ethers.provider.send("hardhat_setStorageAt", [address, index, value]);
await ethers.provider.send("evm_mine", []); // Just mines to the next block
};
describe("Yearn", function() {
const connectorName = "YEARN-TEST-A";
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: Contract;
const wallets = provider.getWallets();
const [wallet0, wallet1, wallet2, wallet3] = wallets;
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 12996975,
},
},
],
});
masterSigner = await getMasterSigner();
instaConnectorsV2 = await ethers.getContractAt(
abis.core.connectorsV2,
addresses.core.connectorsV2
);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2YearnV2__factory,
signer: masterSigner,
connectors: instaConnectorsV2,
});
console.log("Connector address", connector.address);
});
it("Should have contracts deployed.", async function() {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("DSA wallet setup", function() {
it("Should build DSA v2", async function() {
dsaWallet0 = await buildDSAv2(wallet0.address);
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function() {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("10"),
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
ethers.utils.parseEther("10")
);
});
});
describe("Main", function() {
it("Should increase the DAI balance to 100 DAI", async function() {
const DAI = new ethers.Contract(
tokens.dai.address,
abis.basic.erc20,
ethers.provider
);
const DAI_SLOT = 2;
const locallyManipulatedBalance = ethers.utils.parseEther("100");
// Get storage slot index
const index = ethers.utils.solidityKeccak256(
["uint256", "uint256"],
[dsaWallet0.address, DAI_SLOT]
);
// Manipulate local balance (needs to be bytes32 string)
await setStorageAt(
tokens.dai.address,
index.toString(),
toBytes32(locallyManipulatedBalance).toString()
);
// Get DAI balance
const balance = await DAI.balanceOf(dsaWallet0.address);
expect(
await ethers.BigNumber.from(balance).eq(ethers.utils.parseEther("100"))
);
});
it("Should deposit and withdraw 50 DAI in/out the Yearn Vault", async function() {
const DAI = new ethers.Contract(
tokens.dai.address,
abis.basic.erc20,
ethers.provider
);
const DAI_VAULT = "0xdA816459F1AB5631232FE5e97a05BBBb94970c95";
const amount = ethers.utils.parseEther("50"); // 50 DAI
const setId = "132456";
const spells = [
{
connector: connectorName,
method: "deposit",
args: [DAI_VAULT, amount, 0, setId],
},
{
connector: connectorName,
method: "withdraw",
args: [DAI_VAULT, amount, setId, 0],
},
];
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet0.address);
await tx.wait();
// Get DAI balance
const balance = await DAI.balanceOf(dsaWallet0.address);
expect(
await ethers.BigNumber.from(balance).eq(ethers.utils.parseEther("100"))
);
});
it("Should deposit 70 DAI in the Yearn Vault", async function() {
const DAI_VAULT = "0xdA816459F1AB5631232FE5e97a05BBBb94970c95";
const DAI = new ethers.Contract(
tokens.dai.address,
abis.basic.erc20,
ethers.provider
);
const YVDAI = new ethers.Contract(
DAI_VAULT,
abis.basic.erc20,
ethers.provider
);
const amount = ethers.utils.parseEther("70"); // 70 DAI
const setId = "568445";
const spells = [
{
connector: connectorName,
method: "deposit",
args: [DAI_VAULT, amount, 0, setId],
},
];
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet0.address);
await tx.wait();
// Get DAI balance
const yvDAIBalance = await YVDAI.balanceOf(dsaWallet0.address);
const daiBalance = await DAI.balanceOf(dsaWallet0.address);
const correctDaiBalance = ethers.BigNumber.from(daiBalance).eq(
ethers.utils.parseEther("30")
);
const correctYVDaiBalance = ethers.BigNumber.from(yvDAIBalance).lte(
ethers.utils.parseEther("70")
);
expect(correctDaiBalance && correctYVDaiBalance);
});
});
});

View File

@ -0,0 +1,561 @@
import { expect } from "chai";
import hre from "hardhat";
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle;
const ALCHEMY_ID = process.env.ALCHEMY_ID;
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
import { addresses } from "../../../scripts/tests/polygon/addresses";
import { abis } from "../../../scripts/constant/abis";
import { tokens } from "../../../scripts/tests/polygon/tokens";
import type { Signer, Contract } from "ethers";
import { ConnectV2AaveV2Polygon__factory, ConnectV2PoolTogetherPolygon__factory } from "../../../typechain";
const DAI_TOKEN_ADDR = tokens.dai.address; // DAI Token
// PoolTogether Address: https://docs.pooltogether.com/resources/networks/matic
const USDC_PRIZE_POOL_ADDR = "0xEE06AbE9e2Af61cabcb13170e01266Af2DEFa946"; // USDC Prize Pool
const PT_USDC_TICKET_ADDR = "0x473E484c722EF9ec6f63B509b07Bb9cfB258820b"; // PT USDC Ticket
const PT_USDC_SPONGSOR_TICKET_ADDR =
"0x19c0e557ee5a9b456f613ba3d025a4dc45b52c35"; // PT USDC Sponsor Ticket
const USDC_POOL_FAUCET_ADDR = "0x6cbc003fE015D753180f072d904bA841b2415498"; // USDC POOL Faucet
const POOL_TOKEN_ADDRESS = "0x25788a1a171ec66Da6502f9975a15B609fF54CF6"; // POOL Tocken
const TOKEN_FAUCET_PROXY_FACTORY_ADDR =
"0xeaa636304a7C8853324B6b603dCdE55F92dfbab1"; // TokenFaucetProxyFactory for claimAll
// Community WETH Prize Pool (Rari): https://reference-app.pooltogether.com/pools/mainnet/0xa88ca010b32a54d446fc38091ddbca55750cbfc3/manage#stats
const WETH_PRIZE_POOL_ADDR = "0xa88ca010b32a54d446fc38091ddbca55750cbfc3"; // Community WETH Prize Pool (Rari)
const WETH_POOL_TICKET_ADDR = "0x9b5c30aeb9ce2a6a121cea9a85bc0d662f6d9b40"; // Community WETH Prize Pool Ticket (Rari)
const prizePoolABI = [
"function calculateEarlyExitFee( address from, address controlledToken, uint256 amount) external returns ( uint256 exitFee, uint256 burnedCredit)",
"function creditPlanOf( address controlledToken) external view returns ( uint128 creditLimitMantissa, uint128 creditRateMantissa)",
];
const connectorsABI = [
"function isConnectors(string[] calldata connectorNames) external view returns (bool, address[] memory)",
];
describe("PoolTogether", function() {
const connectorName = "AAVEV2-TEST-A";
const ptConnectorName = "POOLTOGETHER-TEST-A";
let dsaWallet0: any;
let masterSigner: Signer;
let instaConnectorsV2: Contract;
let connector: any;
let ptConnector: Contract;
const wallets = provider.getWallets();
const [wallet0, wallet1, wallet2, wallet3] = wallets;
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: `https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_ID}`,
blockNumber: 18717337,
},
},
],
});
masterSigner = await getMasterSigner();
instaConnectorsV2 = await ethers.getContractAt(
abis.core.connectorsV2,
addresses.core.connectorsV2
);
// Deploy and enable Compound Connector
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: ConnectV2AaveV2Polygon__factory,
signer: masterSigner,
connectors: instaConnectorsV2,
});
// Deploy and enable Pool Together Connector
ptConnector = await deployAndEnableConnector({
connectorName: ptConnectorName,
contractArtifact: ConnectV2PoolTogetherPolygon__factory,
signer: masterSigner,
connectors: instaConnectorsV2,
});
});
it("Should have contracts deployed.", async function() {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!ptConnector.address).to.be.true;
expect(!!(await masterSigner.getAddress())).to.be.true;
});
describe("DSA wallet setup", function() {
it("Should build DSA v2", async function() {
dsaWallet0 = await buildDSAv2(wallet0.address);
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit 1000 MATIC into DSA wallet", async function() {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("1000"),
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(
ethers.utils.parseEther("1000")
);
});
});
describe("Main - USDC Prize Pool Test", function() {
it("Should deposit 100 MATIC in AAVE V2", async function() {
const amount = ethers.utils.parseEther("100"); // 100 MATIC
const spells = [
{
connector: connectorName,
method: "deposit",
args: [tokens.eth.address, amount, 0, 0],
},
];
const tx = await dsaWallet0.cast(
...encodeSpells(spells),
wallet1.address
);
const receipt = await tx.wait();
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
ethers.utils.parseEther("900")
);
});
it("Should borrow 10 USDC from AAVE V2 and deposit USDC into USDC Prize Pool", async function() {
const amount = ethers.utils.parseUnits("10", 6); // 10 USDC
const setId = "83478237";
const spells = [
{
connector: connectorName,
method: "borrow",
args: [tokens.usdc.address, amount, 2, 0, setId],
},
{
connector: ptConnectorName,
method: "depositTo",
args: [
USDC_PRIZE_POOL_ADDR,
amount,
PT_USDC_SPONGSOR_TICKET_ADDR,
setId,
0,
],
},
];
// Before Spell
let usdcToken = await ethers.getContractAt(
abis.basic.erc20,
tokens.usdc.address
);
let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC balance is 0`).to.be.eq(
ethers.utils.parseUnits("0", 6)
);
let cToken = await ethers.getContractAt(
abis.basic.erc20,
PT_USDC_SPONGSOR_TICKET_ADDR
);
const balance = await cToken.balanceOf(dsaWallet0.address);
expect(balance, `PoolTogether USDC Ticket balance is 0`).to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
const receipt = await tx.wait();
// After spell
usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(
usdcBalance,
`Expect USDC balance to still equal 0 since it was deposited into Prize Pool`
).to.be.eq(0);
const balanceAfter = await cToken.balanceOf(dsaWallet0.address);
expect(
balanceAfter,
`PoolTogether USDC Ticket balance equals 10`
).to.be.eq(ethers.utils.parseUnits("10", 6));
// ETH used for transaction
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
ethers.utils.parseEther("900")
);
});
it("Should wait 11 days, withdraw all PrizePool, get back 10 USDC, and claim POOL", async function() {
const amount = ethers.utils.parseUnits("10", 6); // 10 USDC
let prizePoolContract = new ethers.Contract(
USDC_PRIZE_POOL_ADDR,
prizePoolABI,
ethers.provider
);
// const { creditLimitMantissa, creditRateMantissa } = await prizePoolContract.creditPlanOf(PT_USDC_TICKET_ADDR);
// console.log("CreditLimitMantiss: ", creditLimitMantissa.toString());
// console.log("CreditRateMantiss: ", creditRateMantissa.toString());
let earlyExitFee = await prizePoolContract.callStatic[
"calculateEarlyExitFee"
](dsaWallet0.address, PT_USDC_SPONGSOR_TICKET_ADDR, amount);
expect(
earlyExitFee.exitFee,
"Exit Fee equal to 0 USDC because 0% fee for sponsorship ticket"
).to.be.eq(ethers.utils.parseUnits("0", 6));
const spells = [
{
connector: ptConnectorName,
method: "claim",
args: [USDC_POOL_FAUCET_ADDR, 0],
},
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [
USDC_PRIZE_POOL_ADDR,
amount,
PT_USDC_SPONGSOR_TICKET_ADDR,
earlyExitFee.exitFee,
0,
0,
],
},
];
// Before spell
let usdcToken = await ethers.getContractAt(
abis.basic.erc20,
tokens.usdc.address
);
let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC balance equals 0`).to.be.eq(
ethers.utils.parseEther("0")
);
let cToken = await ethers.getContractAt(
abis.basic.erc20,
PT_USDC_SPONGSOR_TICKET_ADDR
);
const balance = await cToken.balanceOf(dsaWallet0.address);
expect(balance, `PoolTogether USDC Ticket is 10`).to.be.eq(
ethers.utils.parseUnits("10", 6)
);
let poolToken = await ethers.getContractAt(
abis.basic.erc20,
POOL_TOKEN_ADDRESS
);
const poolBalance = await poolToken.balanceOf(dsaWallet0.address);
expect(poolBalance, `POOL Token equals 0`).to.be.eq(
ethers.utils.parseEther("0")
);
// Increase time by 11 days so we get back all USDC without early withdrawal fee
await ethers.provider.send("evm_increaseTime", [15 * 24 * 60 * 60]);
earlyExitFee = await prizePoolContract.callStatic[
"calculateEarlyExitFee"
](dsaWallet0.address, PT_USDC_SPONGSOR_TICKET_ADDR, amount);
expect(
earlyExitFee.exitFee,
"Exit Fee equal to 0 DAI because past 14 days"
).to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
const receipt = await tx.wait();
// After spell
usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
console.log("USDC BALANCE: ", usdcBalance.toString());
console.log(
"USDC BALANCE: ",
ethers.utils.parseUnits("10", 6).toString()
);
expect(
usdcBalance,
`USDC balance to be equal to 10, because of no early withdrawal fee`
).to.be.eq(ethers.utils.parseUnits("10", 6));
const balanceAfter = await cToken.balanceOf(dsaWallet0.address);
expect(balanceAfter, `PoolTogether USDC Ticket to equal 0`).to.be.eq(0);
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address);
console.log("POOL BALANCE AFTER:", poolBalanceAfter.toString());
expect(
poolBalanceAfter,
`POOL Token Balance to be greater than 0`
).to.be.gt(ethers.utils.parseEther("0"));
});
it("Should deposit and withdraw all PrizePool, get back less than 10 USDC", async function() {
const amount = ethers.utils.parseUnits("10", 6); // 10 USDC
const exitFee = ethers.utils.parseUnits(".1", 6); // 1 USDC is 1% of 100 USDC
const spells = [
{
connector: ptConnectorName,
method: "depositTo",
args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_TICKET_ADDR, 0, 0],
},
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [
USDC_PRIZE_POOL_ADDR,
amount,
PT_USDC_TICKET_ADDR,
exitFee,
0,
0,
],
},
];
// Before spell
let usdcToken = await ethers.getContractAt(
abis.basic.erc20,
tokens.usdc.address
);
let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC Balance equals 100`).to.be.eq(
ethers.utils.parseUnits("10", 6)
);
let cToken = await ethers.getContractAt(
abis.basic.erc20,
PT_USDC_TICKET_ADDR
);
const balance = await cToken.balanceOf(dsaWallet0.address);
expect(balance, `PoolTogether USDC Ticket equals 0`).to.be.eq(0);
let poolToken = await ethers.getContractAt(
abis.basic.erc20,
POOL_TOKEN_ADDRESS
);
const poolBalance = await poolToken.balanceOf(dsaWallet0.address);
expect(poolBalance, `PoolTogether Token greater than 0`).to.be.gt(0);
// Run spell transaction
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(spells), wallet1.address);
const receipt = await tx.wait();
// After spell
usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(
usdcBalance,
`USDC balance to be less than 10, because of early withdrawal fee`
).to.be.lt(ethers.utils.parseUnits("10", 6));
console.log("USDC BALANCE AFTER:", usdcBalance.toString());
const balanceAfter = await cToken.balanceOf(dsaWallet0.address);
expect(balanceAfter, `PoolTogether USDC Ticket to equal 0`).to.be.eq(0);
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address);
expect(poolBalanceAfter, `POOL Token Balance to greater than 0`).to.be.gt(
ethers.utils.parseEther("0")
);
});
it("Should deposit, wait 11 days, and withdraw all PrizePool, get 10 USDC, and claim all POOL using claimAll", async function() {
const amount = ethers.utils.parseUnits("9.9", 6); // 9 USDC
const depositSpells = [
{
connector: ptConnectorName,
method: "depositTo",
args: [
USDC_PRIZE_POOL_ADDR,
amount,
PT_USDC_SPONGSOR_TICKET_ADDR,
0,
0,
],
},
];
// Before spell
let usdcToken = await ethers.getContractAt(
abis.basic.erc20,
tokens.usdc.address
);
let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC balance less than 10`).to.be.lt(
ethers.utils.parseUnits("10", 6)
);
let cToken = await ethers.getContractAt(
abis.basic.erc20,
PT_USDC_SPONGSOR_TICKET_ADDR
);
const balance = await cToken.balanceOf(dsaWallet0.address);
expect(balance, `PoolTogether USDC Ticket equal 0`).to.be.eq(0);
let poolToken = await ethers.getContractAt(
abis.basic.erc20,
POOL_TOKEN_ADDRESS
);
const poolBalance = await poolToken.balanceOf(dsaWallet0.address);
expect(poolBalance, `POOL Token is greater than 0`).to.be.gt(
ethers.utils.parseEther("0")
);
// Run spell transaction
const tx = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(depositSpells), wallet1.address);
const receipt = await tx.wait();
const prizePoolContract = new ethers.Contract(
USDC_PRIZE_POOL_ADDR,
prizePoolABI,
ethers.provider
);
let earlyExitFee = await prizePoolContract.callStatic[
"calculateEarlyExitFee"
](dsaWallet0.address, PT_USDC_SPONGSOR_TICKET_ADDR, amount);
expect(
earlyExitFee.exitFee,
"Exit Fee equal to 0 USDC because fee 0%"
).to.be.eq(0);
// Increase time by 11 days so we get back all DAI without early withdrawal fee
await ethers.provider.send("evm_increaseTime", [11 * 24 * 60 * 60]);
const withdrawSpells = [
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [
USDC_PRIZE_POOL_ADDR,
amount,
PT_USDC_SPONGSOR_TICKET_ADDR,
earlyExitFee.exitFee,
0,
0,
],
},
{
connector: ptConnectorName,
method: "claimAll",
args: [TOKEN_FAUCET_PROXY_FACTORY_ADDR, [USDC_POOL_FAUCET_ADDR]],
},
];
// Run spell transaction
const tx2 = await dsaWallet0
.connect(wallet0)
.cast(...encodeSpells(withdrawSpells), wallet1.address);
const receipt2 = await tx2.wait();
// After spell
usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC balance equals 9.9`).to.be.eq(
ethers.utils.parseUnits("9.9", 6)
);
const balanceAfter = await cToken.balanceOf(dsaWallet0.address);
expect(balanceAfter, `PoolTogether USDC Ticket equal 0`).to.be.eq(0);
// Expect
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address);
console.log("POOL BALANCE AFTER:", poolBalanceAfter.toString());
expect(poolBalanceAfter, `Pool Token to be greater than before`).to.be.gt(
poolBalance
);
});
// })
// NO WMATIC POOLS: https://reference-app.pooltogether.com/pools/polygon
// describe("Main - WETH Prize Pool Test", function () {
// it("Deposit 1 ETH into WETH Prize Pool and withdraw immediately", async function () {
// const amount = ethers.utils.parseEther("1") // 1 ETH
// const setId = "83478237"
// const spells = [
// {
// connector: ptConnectorName,
// method: "depositTo",
// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, setId]
// },
// {
// connector: ptConnectorName,
// method: "withdrawInstantlyFrom",
// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, setId, 0]
// },
// ]
// // Before Spell
// const ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address);
// // Run spell transaction
// const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
// const receipt = await tx.wait()
// // After spell
// const ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
// // ETH used for transaction
// expect(ethBalanceAfter, `ETH Balance less than before spell because of early withdrawal fee`).to.be.lte(ethBalanceBefore);
// });
// it("Deposit 1 ETH into WETH Prize Pool, wait 14 days, then withdraw", async function () {
// const amount = ethers.utils.parseEther("1") // 1 ETH
// const depositSpell = [
// {
// connector: ptConnectorName,
// method: "depositTo",
// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, 0]
// }
// ]
// const withdrawSpell = [
// {
// connector: ptConnectorName,
// method: "withdrawInstantlyFrom",
// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, 0, 0]
// }
// ]
// // Before Deposit Spell
// let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address);
// // Run deposit spell transaction
// const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpell), wallet1.address)
// const receipt = await tx.wait()
// // After Deposit spell
// let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
// expect(ethBalanceAfter, `ETH Balance less than before spell`).to.be.lte(ethBalanceBefore);
// // Increase time by 11 days so we get back all ETH without early withdrawal fee
// await ethers.provider.send("evm_increaseTime", [14*24*60*60]);
// await ethers.provider.send("evm_mine");
// // Run withdraw spell transaction
// const tx2 = await dsaWallet0.connect(wallet0).cast(...encodeSpells(withdrawSpell), wallet1.address)
// const receipt2 = await tx.wait()
// // After Deposit spell
// ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
// expect(ethBalanceAfter, `ETH Balance equal to before spell because no early exit fee`).to.be.eq(ethBalanceBefore);
// });
});
});

View File

@ -1,420 +0,0 @@
const { expect } = require("chai");
const hre = require("hardhat");
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle
const ALCHEMY_ID = process.env.ALCHEMY_ID;
const deployAndEnableConnector = require("../../scripts/polygon/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/polygon/buildDSAv2")
const encodeSpells = require("../../scripts/polygon/encodeSpells.js")
const getMasterSigner = require("../../scripts/polygon/getMasterSigner")
const addresses = require("../../scripts/polygon/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/polygon/constant/constant");
const tokens = require("../../scripts/polygon/constant/tokens");
const connectV2AaveV2Artifacts = require("../../artifacts/contracts/polygon/connectors/aave/v2/main.sol/ConnectV2AaveV2Polygon.json")
const connectV2PoolTogetherArtifacts = require("../../artifacts/contracts/polygon/connectors/pooltogether/main.sol/ConnectV2PoolTogetherPolygon.json")
const DAI_TOKEN_ADDR = tokens.dai.address // DAI Token
// PoolTogether Address: https://docs.pooltogether.com/resources/networks/matic
const USDC_PRIZE_POOL_ADDR = "0xEE06AbE9e2Af61cabcb13170e01266Af2DEFa946" // USDC Prize Pool
const PT_USDC_TICKET_ADDR = "0x473E484c722EF9ec6f63B509b07Bb9cfB258820b" // PT USDC Ticket
const PT_USDC_SPONGSOR_TICKET_ADDR = "0x19c0e557ee5a9b456f613ba3d025a4dc45b52c35" // PT USDC Sponsor Ticket
const USDC_POOL_FAUCET_ADDR = "0x6cbc003fE015D753180f072d904bA841b2415498" // USDC POOL Faucet
const POOL_TOKEN_ADDRESS = "0x25788a1a171ec66Da6502f9975a15B609fF54CF6" // POOL Tocken
const TOKEN_FAUCET_PROXY_FACTORY_ADDR = "0xeaa636304a7C8853324B6b603dCdE55F92dfbab1" // TokenFaucetProxyFactory for claimAll
// Community WETH Prize Pool (Rari): https://reference-app.pooltogether.com/pools/mainnet/0xa88ca010b32a54d446fc38091ddbca55750cbfc3/manage#stats
const WETH_PRIZE_POOL_ADDR = "0xa88ca010b32a54d446fc38091ddbca55750cbfc3" // Community WETH Prize Pool (Rari)
const WETH_POOL_TICKET_ADDR = "0x9b5c30aeb9ce2a6a121cea9a85bc0d662f6d9b40" // Community WETH Prize Pool Ticket (Rari)
const prizePoolABI = [
"function calculateEarlyExitFee( address from, address controlledToken, uint256 amount) external returns ( uint256 exitFee, uint256 burnedCredit)",
"function creditPlanOf( address controlledToken) external view returns ( uint128 creditLimitMantissa, uint128 creditRateMantissa)"
]
const connectorsABI = [
"function isConnectors(string[] calldata connectorNames) external view returns (bool, address[] memory)"
]
describe("PoolTogether", function () {
const connectorName = "AAVEV2-TEST-A"
const ptConnectorName = "POOLTOGETHER-TEST-A"
let dsaWallet0
let masterSigner;
let instaConnectorsV2;
let connector;
let ptConnector;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: `https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_ID}`,
blockNumber: 18717337,
},
},
],
});
masterSigner = await getMasterSigner()
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
// Deploy and enable Compound Connector
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectV2AaveV2Artifacts,
signer: masterSigner,
connectors: instaConnectorsV2
})
// Deploy and enable Pool Together Connector
ptConnector = await deployAndEnableConnector({
connectorName: ptConnectorName,
contractArtifact: connectV2PoolTogetherArtifacts,
signer: masterSigner,
connectors: instaConnectorsV2
})
})
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!ptConnector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
});
describe("DSA wallet setup", function () {
it("Should build DSA v2", async function () {
dsaWallet0 = await buildDSAv2(wallet0.address)
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit 1000 MATIC into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("1000")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("1000"));
});
});
describe("Main - USDC Prize Pool Test", function () {
it("Should deposit 100 MATIC in AAVE V2", async function () {
const amount = ethers.utils.parseEther("100") // 100 MATIC
const spells = [
{
connector: connectorName,
method: "deposit",
args: [tokens.matic.address, amount, 0, 0]
}
]
const tx = await dsaWallet0.cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("900"));
});
it("Should borrow 10 USDC from AAVE V2 and deposit USDC into USDC Prize Pool", async function () {
const amount = ethers.utils.parseUnits("10", 6) // 10 USDC
const setId = "83478237"
const spells = [
{
connector: connectorName,
method: "borrow",
args: [tokens.usdc.address, amount, 2, 0, setId]
},
{
connector: ptConnectorName,
method: "depositTo",
args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_SPONGSOR_TICKET_ADDR, setId, 0]
}
]
// Before Spell
let usdcToken = await ethers.getContractAt(abis.basic.erc20, tokens.usdc.address)
let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC balance is 0`).to.be.eq(ethers.utils.parseUnits("0", 6));
let cToken = await ethers.getContractAt(abis.basic.erc20, PT_USDC_SPONGSOR_TICKET_ADDR)
const balance = await cToken.balanceOf(dsaWallet0.address)
expect(balance,`PoolTogether USDC Ticket balance is 0`).to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `Expect USDC balance to still equal 0 since it was deposited into Prize Pool`).to.be.eq(0);
const balanceAfter = await cToken.balanceOf(dsaWallet0.address)
expect(balanceAfter, `PoolTogether USDC Ticket balance equals 10`).to.be.eq(ethers.utils.parseUnits("10", 6));
// ETH used for transaction
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("900"));
});
it("Should wait 11 days, withdraw all PrizePool, get back 10 USDC, and claim POOL", async function () {
const amount = ethers.utils.parseUnits("10", 6) // 10 USDC
let prizePoolContract = new ethers.Contract(USDC_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider);
// const { creditLimitMantissa, creditRateMantissa } = await prizePoolContract.creditPlanOf(PT_USDC_TICKET_ADDR);
// console.log("CreditLimitMantiss: ", creditLimitMantissa.toString());
// console.log("CreditRateMantiss: ", creditRateMantissa.toString());
let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_USDC_SPONGSOR_TICKET_ADDR, amount);
expect(earlyExitFee.exitFee, "Exit Fee equal to 0 USDC because 0% fee for sponsorship ticket").to.be.eq(ethers.utils.parseUnits("0", 6));
const spells = [
{
connector: ptConnectorName,
method: "claim",
args: [USDC_POOL_FAUCET_ADDR, 0]
},
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_SPONGSOR_TICKET_ADDR, earlyExitFee.exitFee, 0, 0]
}
]
// Before spell
let usdcToken = await ethers.getContractAt(abis.basic.erc20, tokens.usdc.address)
let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC balance equals 0`).to.be.eq(ethers.utils.parseEther("0"));
let cToken = await ethers.getContractAt(abis.basic.erc20, PT_USDC_SPONGSOR_TICKET_ADDR)
const balance = await cToken.balanceOf(dsaWallet0.address)
expect(balance, `PoolTogether USDC Ticket is 10`).to.be.eq(ethers.utils.parseUnits("10", 6));
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token equals 0`).to.be.eq(ethers.utils.parseEther("0"));
// Increase time by 11 days so we get back all USDC without early withdrawal fee
await ethers.provider.send("evm_increaseTime", [15*24*60*60]);
await ethers.provider.send("evm_mine");
earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_USDC_SPONGSOR_TICKET_ADDR, amount);
expect(earlyExitFee.exitFee, "Exit Fee equal to 0 DAI because past 14 days").to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
console.log("USDC BALANCE: ", usdcBalance.toString());
console.log("USDC BALANCE: ", ethers.utils.parseUnits("10", 6).toString());
expect(usdcBalance,
`USDC balance to be equal to 10, because of no early withdrawal fee`
).to.be.eq(ethers.utils.parseUnits("10", 6));
const balanceAfter = await cToken.balanceOf(dsaWallet0.address)
expect(balanceAfter, `PoolTogether USDC Ticket to equal 0`).to.be.eq(0);
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
console.log("POOL BALANCE AFTER:" ,poolBalanceAfter.toString());
expect(poolBalanceAfter, `POOL Token Balance to be greater than 0`).to.be.gt(ethers.utils.parseEther("0"));
});
it("Should deposit and withdraw all PrizePool, get back less than 10 USDC", async function() {
const amount = ethers.utils.parseUnits("10", 6) // 10 USDC
const exitFee = ethers.utils.parseUnits(".1", 6) // 1 USDC is 1% of 100 USDC
const spells = [
{
connector: ptConnectorName,
method: "depositTo",
args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_TICKET_ADDR, 0, 0]
},
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_TICKET_ADDR, exitFee, 0, 0]
}
]
// Before spell
let usdcToken = await ethers.getContractAt(abis.basic.erc20, tokens.usdc.address)
let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC Balance equals 100`).to.be.eq(ethers.utils.parseUnits("10", 6));
let cToken = await ethers.getContractAt(abis.basic.erc20, PT_USDC_TICKET_ADDR)
const balance = await cToken.balanceOf(dsaWallet0.address)
expect(balance, `PoolTogether USDC Ticket equals 0`).to.be.eq(0);
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `PoolTogether Token greater than 0`).to.be.gt(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance,
`USDC balance to be less than 10, because of early withdrawal fee`
).to.be.lt(ethers.utils.parseUnits("10",6));
console.log("USDC BALANCE AFTER:", usdcBalance.toString());
const balanceAfter = await cToken.balanceOf(dsaWallet0.address)
expect(balanceAfter, `PoolTogether USDC Ticket to equal 0`).to.be.eq(0);
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalanceAfter, `POOL Token Balance to greater than 0`).to.be.gt(ethers.utils.parseEther("0"));
});
it("Should deposit, wait 11 days, and withdraw all PrizePool, get 10 USDC, and claim all POOL using claimAll", async function() {
const amount = ethers.utils.parseUnits("9.9", 6) // 9 USDC
const depositSpells = [
{
connector: ptConnectorName,
method: "depositTo",
args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_SPONGSOR_TICKET_ADDR, 0, 0]
}
]
// Before spell
let usdcToken = await ethers.getContractAt(abis.basic.erc20, tokens.usdc.address)
let usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC balance less than 10`).to.be.lt(ethers.utils.parseUnits("10", 6));
let cToken = await ethers.getContractAt(abis.basic.erc20, PT_USDC_SPONGSOR_TICKET_ADDR)
const balance = await cToken.balanceOf(dsaWallet0.address)
expect(balance, `PoolTogether USDC Ticket equal 0`).to.be.eq(0);
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token is greater than 0`).to.be.gt(ethers.utils.parseEther("0"));
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpells), wallet1.address)
const receipt = await tx.wait()
const prizePoolContract = new ethers.Contract(USDC_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider);
let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_USDC_SPONGSOR_TICKET_ADDR, amount);
expect(earlyExitFee.exitFee, "Exit Fee equal to 0 USDC because fee 0%").to.be.eq(0);
// Increase time by 11 days so we get back all DAI without early withdrawal fee
await ethers.provider.send("evm_increaseTime", [11*24*60*60]);
await ethers.provider.send("evm_mine");
const withdrawSpells = [
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [USDC_PRIZE_POOL_ADDR, amount, PT_USDC_SPONGSOR_TICKET_ADDR, earlyExitFee.exitFee, 0, 0]
},
{
connector: ptConnectorName,
method: "claimAll",
args: [TOKEN_FAUCET_PROXY_FACTORY_ADDR, [USDC_POOL_FAUCET_ADDR]]
}
]
// Run spell transaction
const tx2 = await dsaWallet0.connect(wallet0).cast(...encodeSpells(withdrawSpells), wallet1.address)
const receipt2 = await tx2.wait()
// After spell
usdcBalance = await usdcToken.balanceOf(dsaWallet0.address);
expect(usdcBalance, `USDC balance equals 9.9`).to.be.eq(ethers.utils.parseUnits("9.9", 6));
const balanceAfter = await cToken.balanceOf(dsaWallet0.address)
expect(balanceAfter, `PoolTogether USDC Ticket equal 0`).to.be.eq(0);
// Expect
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
console.log("POOL BALANCE AFTER:" ,poolBalanceAfter.toString());
expect(poolBalanceAfter, `Pool Token to be greater than before`).to.be.gt(poolBalance);
});
// })
// NO WMATIC POOLS: https://reference-app.pooltogether.com/pools/polygon
// describe("Main - WETH Prize Pool Test", function () {
// it("Deposit 1 ETH into WETH Prize Pool and withdraw immediately", async function () {
// const amount = ethers.utils.parseEther("1") // 1 ETH
// const setId = "83478237"
// const spells = [
// {
// connector: ptConnectorName,
// method: "depositTo",
// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, setId]
// },
// {
// connector: ptConnectorName,
// method: "withdrawInstantlyFrom",
// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, setId, 0]
// },
// ]
// // Before Spell
// const ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address);
// // Run spell transaction
// const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
// const receipt = await tx.wait()
// // After spell
// const ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
// // ETH used for transaction
// expect(ethBalanceAfter, `ETH Balance less than before spell because of early withdrawal fee`).to.be.lte(ethBalanceBefore);
// });
// it("Deposit 1 ETH into WETH Prize Pool, wait 14 days, then withdraw", async function () {
// const amount = ethers.utils.parseEther("1") // 1 ETH
// const depositSpell = [
// {
// connector: ptConnectorName,
// method: "depositTo",
// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, 0]
// }
// ]
// const withdrawSpell = [
// {
// connector: ptConnectorName,
// method: "withdrawInstantlyFrom",
// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, 0, 0]
// }
// ]
// // Before Deposit Spell
// let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address);
// // Run deposit spell transaction
// const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpell), wallet1.address)
// const receipt = await tx.wait()
// // After Deposit spell
// let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
// expect(ethBalanceAfter, `ETH Balance less than before spell`).to.be.lte(ethBalanceBefore);
// // Increase time by 11 days so we get back all ETH without early withdrawal fee
// await ethers.provider.send("evm_increaseTime", [14*24*60*60]);
// await ethers.provider.send("evm_mine");
// // Run withdraw spell transaction
// const tx2 = await dsaWallet0.connect(wallet0).cast(...encodeSpells(withdrawSpell), wallet1.address)
// const receipt2 = await tx.wait()
// // After Deposit spell
// ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
// expect(ethBalanceAfter, `ETH Balance equal to before spell because no early exit fee`).to.be.eq(ethBalanceBefore);
// });
});
})

View File

@ -1,811 +0,0 @@
const { expect } = require("chai");
const hre = require("hardhat");
const { web3, deployments, waffle, ethers } = hre;
const { provider, deployContract } = waffle
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const constants = require("../../scripts/constant/constant");
const tokens = require("../../scripts/constant/tokens");
const connectV2CompoundArtifacts = require("../../artifacts/contracts/mainnet/connectors/compound/main.sol/ConnectV2Compound.json")
const connectV2PoolTogetherArtifacts = require("../../artifacts/contracts/mainnet/connectors/pooltogether/main.sol/ConnectV2PoolTogether.json")
const connectV2UniswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/uniswap/main.sol/ConnectV2UniswapV2.json")
const DAI_TOKEN_ADDR = tokens.dai.address // DAI Token
// PoolTogether Address: https://docs.pooltogether.com/resources/networks/ethereum
const DAI_PRIZE_POOL_ADDR = "0xEBfb47A7ad0FD6e57323C8A42B2E5A6a4F68fc1a" // DAI Prize Pool
const PT_DAI_TICKET_ADDR = "0x334cBb5858417Aee161B53Ee0D5349cCF54514CF" // PT DAI Ticket
const DAI_POOL_FAUCET_ADDR = "0xF362ce295F2A4eaE4348fFC8cDBCe8d729ccb8Eb" // DAI POOL Faucet
const POOL_TOKEN_ADDRESS = "0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e" // POOL Tocken
const TOKEN_FAUCET_PROXY_FACTORY_ADDR = "0xE4E9cDB3E139D7E8a41172C20b6Ed17b6750f117" // TokenFaucetProxyFactory for claimAll
const DAI_POD_ADDR = "0x2f994e2E4F3395649eeE8A89092e63Ca526dA829" // DAI Pod
const UNISWAP_POOLETHLP_PRIZE_POOL_ADDR = "0x3AF7072D29Adde20FC7e173a7CB9e45307d2FB0A" // Uniswap Pool/ETH LP PrizePool
const UNISWAP_POOLETHLP_FAUCET_ADDR = "0x9A29401EF1856b669f55Ae5b24505b3B6fAEb370" // Uniswap Pool/ETH LP Faucet
const UNISWAP_POOLETHLP_TOKEN_ADDR = "0x85cb0bab616fe88a89a35080516a8928f38b518b" // Uniswap Pool/ETH Token
const PT_UNISWAP_POOLETHLP_TICKET_ADDR = "0xeb8928ee92efb06c44d072a24c2bcb993b61e543" // Pool Together Uniswap Pool/ETH LP Ticket
const POOL_PRIZE_POOL_ADDR = "0x396b4489da692788e327e2e4b2b0459a5ef26791" // POOL Prize Pool
const PT_POOL_TICKET_ADDR = "0x27d22a7648e955e510a40bdb058333e9190d12d4" // Pool Together POOL Ticket
const WETH_ADDR = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" // WETH
const DAI_POD_TOKEN_DROP = "0xc5209623E3dFdf9C0cCbe497c8012883C4147731"
// Community WETH Prize Pool (Rari): https://reference-app.pooltogether.com/pools/mainnet/0xa88ca010b32a54d446fc38091ddbca55750cbfc3/manage#stats
const WETH_PRIZE_POOL_ADDR = "0xa88ca010b32a54d446fc38091ddbca55750cbfc3" // Community WETH Prize Pool (Rari)
const WETH_POOL_TICKET_ADDR = "0x9b5c30aeb9ce2a6a121cea9a85bc0d662f6d9b40" // Community WETH Prize Pool Ticket (Rari)
const prizePoolABI = [
"function calculateEarlyExitFee( address from, address controlledToken, uint256 amount) external returns ( uint256 exitFee, uint256 burnedCredit)"
]
const podABI = [
"function getEarlyExitFee(uint256 amount) external returns (uint256)",
"function balanceOfUnderlying(address user) external view returns (uint256 amount)",
"function drop() public returns (uint256)",
"function balanceOf(address account) external view returns (uint256)"
]
const POD_FACTORY_ADDRESS = "0x4e3a9f9fbafb2ec49727cffa2a411f7a0c1c4ce1"
const podFactoryABI = [
"function create( address _prizePool, address _ticket, address _faucet, address _manager, uint8 _decimals) external returns (address pod)"
]
const tokenDropABI = [
"function claim(address user) external returns (uint256)",
]
describe("PoolTogether", function () {
const connectorName = "COMPOUND-TEST-A"
const uniswapConnectorName = "UNISWAP-TEST-A"
const ptConnectorName = "POOLTOGETHER-TEST-A"
let dsaWallet0
let masterSigner;
let instaConnectorsV2;
let connector;
let ptConnector;
let uniswapConnector;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
before(async () => {
masterSigner = await getMasterSigner(wallet3)
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
// Deploy and enable Compound Connector
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectV2CompoundArtifacts,
signer: masterSigner,
connectors: instaConnectorsV2
})
// Deploy and enable Pool Together Connector
ptConnector = await deployAndEnableConnector({
connectorName: ptConnectorName,
contractArtifact: connectV2PoolTogetherArtifacts,
signer: masterSigner,
connectors: instaConnectorsV2
})
// Deploy and enable Uniswap Connector
uniswapConnector = await deployAndEnableConnector({
connectorName: uniswapConnectorName,
contractArtifact: connectV2UniswapArtifacts,
signer: masterSigner,
connectors: instaConnectorsV2
})
})
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!ptConnector.address).to.be.true;
expect(!!uniswapConnector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
});
describe("DSA wallet setup", function () {
it("Should build DSA v2", async function () {
dsaWallet0 = await buildDSAv2(wallet0.address)
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit 10 ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("10")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
});
});
describe("Main - DAI Prize Pool Test", function () {
it("Should deposit 1 ETH in Compound", async function () {
const amount = ethers.utils.parseEther("1") // 1 ETH
const spells = [
{
connector: connectorName,
method: "deposit",
args: ["ETH-A", amount, 0, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9"));
});
it("Should borrow 100 DAI from Compound and deposit DAI into DAI Prize Pool", async function () {
const amount = ethers.utils.parseEther("100") // 100 DAI
const setId = "83478237"
const spells = [
{
connector: connectorName,
method: "borrow",
args: ["DAI-A", amount, 0, setId]
},
{
connector: ptConnectorName,
method: "depositTo",
args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, setId, 0]
}
]
// Before Spell
let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR)
let daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `DAI balance is 0`).to.be.eq(ethers.utils.parseEther("0"));
let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR)
const balance = await cToken.balanceOf(dsaWallet0.address)
expect(balance,`PoolTogether DAI Ticket balance is 0`).to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `Expect DAI balance to still equal 0 since it was deposited into Prize Pool`).to.be.eq(0);
const balanceAfter = await cToken.balanceOf(dsaWallet0.address)
expect(balanceAfter, `PoolTogether DAI Ticket balance equals 100`).to.be.eq(ethers.utils.parseEther("100"));
// ETH used for transaction
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9"));
});
it("Should wait 11 days, withdraw all PrizePool, get back 100 DAI, and claim POOL", async function () {
const amount = ethers.utils.parseEther("100") // 100 DAI
let prizePoolContract = new ethers.Contract(DAI_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider);
let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount);
expect(earlyExitFee.exitFee, "Exit Fee equal to 1 DAI because starts at 10%").to.be.eq(ethers.utils.parseEther("1"));
const spells = [
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, earlyExitFee.exitFee, 0, 0]
},
{
connector: ptConnectorName,
method: "claim",
args: [DAI_POOL_FAUCET_ADDR, 0]
}
]
// Before spell
let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR)
let daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `DAI balance equals 0`).to.be.eq(ethers.utils.parseEther("0"));
let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR)
const balance = await cToken.balanceOf(dsaWallet0.address)
expect(balance, `PoolTogether Dai Ticket is 100`).to.be.eq(ethers.utils.parseEther("100"));
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token equals 0`).to.be.eq(ethers.utils.parseEther("0"));
// Increase time by 11 days so we get back all DAI without early withdrawal fee
await ethers.provider.send("evm_increaseTime", [11*24*60*60]);
await ethers.provider.send("evm_mine");
earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount);
expect(earlyExitFee.exitFee, "Exit Fee equal to 0 DAI because past 10 days").to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance,
`DAI balance to be equal to 100, because of no early withdrawal fee`
).to.be.eq(ethers.utils.parseEther("100"));
const balanceAfter = await cToken.balanceOf(dsaWallet0.address)
expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0);
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalanceAfter, `POOL Token Balance to be greater than 0`).to.be.gt(ethers.utils.parseEther("0"));
});
it("Should deposit and withdraw all PrizePool, get back less than 100 DAI", async function() {
const amount = ethers.utils.parseEther("100") // 100 DAI
const exitFee = ethers.utils.parseEther("1") // 1 DAI is 10% of 100 DAI
const spells = [
{
connector: ptConnectorName,
method: "depositTo",
args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0]
},
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, exitFee, 0, 0]
}
]
// Before spell
let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR)
let daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `DAI Balance equals 0`).to.be.eq(ethers.utils.parseEther("100"));
let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR)
const balance = await cToken.balanceOf(dsaWallet0.address)
expect(balance, `PoolTogether DAI Ticket equals 0`).to.be.eq(0);
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `PoolTogether Token greater than 0`).to.be.gt(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance,
`DAI balance to be less than 100, because of early withdrawal fee`
).to.be.lt(ethers.utils.parseEther("100"));
const balanceAfter = await cToken.balanceOf(dsaWallet0.address)
expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0);
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalanceAfter, `POOL Token Balance to greater than 0`).to.be.gt(ethers.utils.parseEther("0"));
});
it("Should deposit, wait 11 days, and withdraw all PrizePool, get 99 DAI, and claim all POOL using claimAll", async function() {
const amount = ethers.utils.parseEther("99") // 99 DAI
const depositSpells = [
{
connector: ptConnectorName,
method: "depositTo",
args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0]
}
]
// Before spell
let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR)
let daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `DAI balance less than 100`).to.be.lt(ethers.utils.parseEther("100"));
let cToken = await ethers.getContractAt(abis.basic.erc20, PT_DAI_TICKET_ADDR)
const balance = await cToken.balanceOf(dsaWallet0.address)
expect(balance, `PoolTogether DAI Ticket equal 0`).to.be.eq(0);
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token is greater than 0`).to.be.gt(ethers.utils.parseEther("0"));
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpells), wallet1.address)
const receipt = await tx.wait()
const prizePoolContract = new ethers.Contract(DAI_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider);
let earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount);
expect(earlyExitFee.exitFee, "Exit Fee equal to .99 DAI because starts at 10%").to.be.eq(ethers.utils.parseEther(".99"));
// Increase time by 11 days so we get back all DAI without early withdrawal fee
await ethers.provider.send("evm_increaseTime", [11*24*60*60]);
await ethers.provider.send("evm_mine");
earlyExitFee = await prizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount);
expect(earlyExitFee.exitFee, "Exit Fee equal to 0 DAI because past 10 days").to.be.eq(0);
const withdrawSpells = [
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, earlyExitFee.exitFee, 0, 0]
},
{
connector: ptConnectorName,
method: "claimAll",
args: [TOKEN_FAUCET_PROXY_FACTORY_ADDR, [DAI_POOL_FAUCET_ADDR]]
}
]
// Run spell transaction
const tx2 = await dsaWallet0.connect(wallet0).cast(...encodeSpells(withdrawSpells), wallet1.address)
const receipt2 = await tx2.wait()
// After spell
daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `DAI balance equals 99`).to.be.eq(ethers.utils.parseEther("99"));
const balanceAfter = await cToken.balanceOf(dsaWallet0.address)
expect(balanceAfter, `PoolTogether DAI Ticket equal 0`).to.be.eq(0);
// Expect
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalanceAfter, `Pool Token to be greateir than 0`).to.be.gt(ethers.utils.parseEther("0"));
});
})
describe("Main - DAI Pod Test", function() {
it("Should deposit 99 DAI in DAI Pod", async function() {
const amount = ethers.utils.parseEther("99") // 99 DAI
const spells = [
{
connector: ptConnectorName,
method: "depositToPod",
args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0]
}
]
// Before spell
let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR)
let daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `DAI balance equals 99`).to.be.eq(ethers.utils.parseEther("99"));
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0);
let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR)
const podBalance = await podToken.balanceOf(dsaWallet0.address)
expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `DAI equals 0`).to.be.eq(0);
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalanceAfter, `POOL Token greater than 0`).to.be.gt(0);
const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address)
expect(podBalanceAfter, `Pod DAI token greater than 0`).to.be.eq(ethers.utils.parseEther("99"));
});
it("Should claim rewards from pod token drop", async function() {
const spells = [
{
connector: ptConnectorName,
method: "claimPodTokenDrop",
args: [DAI_POD_TOKEN_DROP, 0]
}
]
const tokenDropContract = new ethers.Contract(DAI_POD_TOKEN_DROP, tokenDropABI, ethers.provider);
const podContract = new ethers.Contract(DAI_POD_ADDR, podABI, masterSigner);
// drop(): Claim TokenDrop asset for PrizePool Pod and transfers token(s) to external Pod TokenDrop
// dropt() also calls batch which, Deposit Pod float into PrizePool. Deposits the current float
// amount into the PrizePool and claims current POOL rewards.
const dropTx = await podContract.drop();
await dropTx.wait();
// POOL Rewards able to claim from Pod Token Drop
let claimAmount = await tokenDropContract.callStatic["claim"](dsaWallet0.address);
// Before spell
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
const total = claimAmount.add(poolBalance);
expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq(total);
});
it("Should wait 11 days, withdraw all podTokens, get back 99 DAI", async function () {
const amount = ethers.utils.parseEther("99") // 99 DAI
const podContract = new ethers.Contract(DAI_POD_ADDR, podABI, ethers.provider);
let maxFee = await podContract.callStatic["getEarlyExitFee"](amount);
// maxFee depends on if token has been deposited to PrizePool yet
// since we called drop in previous test case, the tokens were deposited to PrizePool
expect(maxFee, "Exit Fee equal to .99 DAI because token still in float").to.be.eq(ethers.utils.parseEther(".99"));
const spells = [
{
connector: ptConnectorName,
method: "withdrawFromPod",
args: [DAI_POD_ADDR, amount, maxFee, 0, 0]
}
]
// Before spell
let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR)
let daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `DAI Balance equals 0`).to.be.eq(0);
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token balance greater than 0`).to.be.gt(0);
let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR)
const podBalance = await podToken.balanceOf(dsaWallet0.address)
expect(podBalance, `Pod DAI Token equals 99`).to.be.eq(ethers.utils.parseEther("99"));
// Increase time by 11 days so we get back all DAI without early withdrawal fee
await ethers.provider.send("evm_increaseTime", [11*24*60*60]);
await ethers.provider.send("evm_mine");
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance,
`DAI balance equals 99, because of no early withdrawal fee`
).to.be.eq(ethers.utils.parseEther("99"));
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalanceAfter, `POOL Token to be greater than 0`).to.be.gt(0);
const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address)
expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq(0);
});
it("Should deposit and withdraw from pod, get back same amount of 99 DAI", async function() {
const amount = ethers.utils.parseEther("99")
const maxFee = 0; // maxFee 0 since it doesn't give chance for Pod to actually deposit into PrizePool
const spells = [
{
connector: ptConnectorName,
method: "depositToPod",
args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0]
},
{
connector: ptConnectorName,
method: "withdrawFromPod",
args: [DAI_POD_ADDR, amount, maxFee, 0, 0]
}
]
// Before spell
let daiToken = await ethers.getContractAt(abis.basic.erc20, DAI_TOKEN_ADDR)
let daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance, `DAI equals 99`).to.be.eq(ethers.utils.parseEther("99"));
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0);
// PodToken is 0
let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR)
const podBalance = await podToken.balanceOf(dsaWallet0.address)
expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
daiBalance = await daiToken.balanceOf(dsaWallet0.address);
expect(daiBalance,
`DAI balance to be equal to 99, because funds still in 'float`
).to.be.eq(ethers.utils.parseEther("99"));
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq(poolBalance);
// Expect Pod Token Balance to equal 0
const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address)
expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq(ethers.utils.parseEther("0"));
});
})
describe("Main - UNISWAP POOL/ETH Prize Pool Test", function () {
it("Should use uniswap to swap ETH for POOL, deposit to POOL/ETH LP, deposit POOL/ETH LP to PrizePool", async function () {
const amount = ethers.utils.parseEther("100") // 100 POOL
const slippage = ethers.utils.parseEther("0.03");
const setId = "83478237"
const UniswapV2Router02ABI = [
"function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)"
];
// Get amount of ETH for 100 POOL from Uniswap
const UniswapV2Router02 = await ethers.getContractAt(UniswapV2Router02ABI, "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D");
const amounts = await UniswapV2Router02.getAmountsOut(amount, [POOL_TOKEN_ADDRESS, WETH_ADDR]);
const unitAmount = ethers.utils.parseEther(((amounts[1]*1.03)/amounts[0]).toString());
const spells = [
{
connector: uniswapConnectorName,
method: "buy",
args: [POOL_TOKEN_ADDRESS, tokens.eth.address, amount, unitAmount, 0, setId]
},
{
connector: uniswapConnectorName,
method: "deposit",
args: [POOL_TOKEN_ADDRESS, tokens.eth.address, amount, unitAmount, slippage, 0, setId]
},
{
connector: ptConnectorName,
method: "depositTo",
args: [UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, 0, PT_UNISWAP_POOLETHLP_TICKET_ADDR, setId, 0]
}
]
// Before Spell
let ethBalance = await ethers.provider.getBalance(dsaWallet0.address);
expect(ethBalance, `ETH Balance equals 9`).to.be.eq(ethers.utils.parseEther("9"));
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0);
let uniswapLPToken = await ethers.getContractAt(abis.basic.erc20, UNISWAP_POOLETHLP_TOKEN_ADDR)
const uniswapPoolEthBalance = await uniswapLPToken.balanceOf(dsaWallet0.address)
expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0);
let ptUniswapPoolEthToken = await ethers.getContractAt(abis.basic.erc20, PT_UNISWAP_POOLETHLP_TICKET_ADDR)
const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address)
expect(ptUniswapPoolEthBalance, `PoolTogether Uniswap POOL?ETH LP equals 0`).to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
ethBalance = await ethers.provider.getBalance(dsaWallet0.address);
expect(ethBalance, `ETH Balance less than 9`).to.be.lt(ethers.utils.parseEther("9"));
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalanceAfter, `POOL Token to be same after spell`).to.be.eq(poolBalance);
const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf(dsaWallet0.address)
expect(uniswapPoolEthBalanceAfter, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0);
const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address)
expect(ptUniswapPoolEthBalanceAfter, `PT Uniswap POOL/ETH LP to greater than 0`).to.be.gt(0);
});
it("Should withdraw all PrizePool, get back Uniswap LP, claim POOL, deposit claimed POOL into Pool PrizePool", async function () {
let ptUniswapPoolEthToken = await ethers.getContractAt(abis.basic.erc20, PT_UNISWAP_POOLETHLP_TICKET_ADDR)
const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address)
const setId = "83478237"
let uniswapPrizePoolContract = new ethers.Contract(UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, prizePoolABI, ethers.provider);
let earlyExitFee = await uniswapPrizePoolContract.callStatic["calculateEarlyExitFee"](dsaWallet0.address, PT_UNISWAP_POOLETHLP_TICKET_ADDR, ptUniswapPoolEthBalance);
expect(earlyExitFee.exitFee, "Exit Fee equals 0 because no early exit fee for this prize pool").to.be.eq(0);
const spells = [
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, ptUniswapPoolEthBalance, PT_UNISWAP_POOLETHLP_TICKET_ADDR, earlyExitFee.exitFee, 0, 0]
},
{
connector: ptConnectorName,
method: "claim",
args: [UNISWAP_POOLETHLP_FAUCET_ADDR , setId]
},
{
connector: ptConnectorName,
method: "depositTo",
args: [POOL_PRIZE_POOL_ADDR, 0, PT_POOL_TICKET_ADDR, setId, 0]
}
]
// Before spell
let poolToken = await ethers.getContractAt(abis.basic.erc20, POOL_TOKEN_ADDRESS)
const poolBalance = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0);
// Uniswap POOL/ETH LP is 0
let uniswapLPToken = await ethers.getContractAt(abis.basic.erc20, UNISWAP_POOLETHLP_TOKEN_ADDR)
const uniswapPoolEthBalance = await uniswapLPToken.balanceOf(dsaWallet0.address)
expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0);
expect(ptUniswapPoolEthBalance, `PT Uniswap POOL/ETH LP greater than 0`).to.be.gt(0);
let poolPoolTicket = await ethers.getContractAt(abis.basic.erc20, PT_POOL_TICKET_ADDR)
const poolPoolTicketBalance = await poolPoolTicket.balanceOf(dsaWallet0.address)
expect(poolPoolTicketBalance, `PoolTogether POOL Ticket equals 0`).to.be.eq(0);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address)
expect(poolBalanceAfter, `Pool Token Balance equal to balance before spell`).to.be.eq(poolBalance);
const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf(dsaWallet0.address)
expect(uniswapPoolEthBalanceAfter, `Uniswap POOL/ETH LP to greater than 0`).to.be.gt(0);
const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf(dsaWallet0.address)
expect(ptUniswapPoolEthBalanceAfter, `PT Uniswap POOL/ETH LP equal 0`).to.be.eq(0);
const poolPoolTicketBalanceAfter = await poolPoolTicket.balanceOf(dsaWallet0.address)
expect(poolPoolTicketBalanceAfter, `PoolTogether POOL Ticket greater than 0`).to.be.gt(0);
});
})
describe("Main - WETH Prize Pool Test", function () {
it("Deposit 1 ETH into WETH Prize Pool and withdraw immediately", async function () {
const amount = ethers.utils.parseEther("1") // 1 ETH
const setId = "83478237"
const spells = [
{
connector: ptConnectorName,
method: "depositTo",
args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, setId]
},
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, setId, 0]
},
]
// Before Spell
const ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After spell
const ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
// ETH used for transaction
expect(ethBalanceAfter, `ETH Balance less than before spell because of early withdrawal fee`).to.be.lte(ethBalanceBefore);
});
it("Deposit 1 ETH into WETH Prize Pool, wait 14 days, then withdraw", async function () {
const amount = ethers.utils.parseEther("1") // 1 ETH
const depositSpell = [
{
connector: ptConnectorName,
method: "depositTo",
args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, 0]
}
]
const withdrawSpell = [
{
connector: ptConnectorName,
method: "withdrawInstantlyFrom",
args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, amount, 0, 0]
}
]
// Before Deposit Spell
let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address);
// Run deposit spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(depositSpell), wallet1.address)
const receipt = await tx.wait()
// After Deposit spell
let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
expect(ethBalanceAfter, `ETH Balance less than before spell`).to.be.lte(ethBalanceBefore);
// Increase time by 11 days so we get back all ETH without early withdrawal fee
await ethers.provider.send("evm_increaseTime", [14*24*60*60]);
await ethers.provider.send("evm_mine");
// Run withdraw spell transaction
const tx2 = await dsaWallet0.connect(wallet0).cast(...encodeSpells(withdrawSpell), wallet1.address)
const receipt2 = await tx.wait()
// After Deposit spell
ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
expect(ethBalanceAfter, `ETH Balance equal to before spell because no early exit fee`).to.be.eq(ethBalanceBefore);
});
});
describe("Main - WETH Pod Test", function() {
let podAddress
it("Should deposit 1 ETH in WETH Pod and get Pod Ticket", async function() {
const amount = ethers.utils.parseEther("1")
// Create Pod for WETH Prize Pool (Rari)
const podFactoryContract = new ethers.Contract(POD_FACTORY_ADDRESS, podFactoryABI, masterSigner)
podAddress = await podFactoryContract.callStatic.create(WETH_PRIZE_POOL_ADDR, WETH_POOL_TICKET_ADDR, constants.address_zero, wallet0.address, 18)
await podFactoryContract.create(WETH_PRIZE_POOL_ADDR, WETH_POOL_TICKET_ADDR, constants.address_zero, wallet0.address, 18)
const spells = [
{
connector: ptConnectorName,
method: "depositToPod",
args: [WETH_ADDR, podAddress, amount, 0, 0]
}
]
// Before Deposit Spell
const podContract = new ethers.Contract(podAddress, podABI, ethers.provider);
let podBalanceBefore = await podContract.balanceOfUnderlying(dsaWallet0.address)
expect(podBalanceBefore, `Pod balance equal to 0`).to.be.eq(0);
let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After Deposit spell
let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
expect(ethBalanceAfter, `ETH balance less than before`).to.be.lt(ethBalanceBefore);
podBalanceAfter = await podContract.balanceOfUnderlying(dsaWallet0.address)
expect(podBalanceAfter, `Pod balance equal to 1`).to.be.eq(ethers.utils.parseEther("1"));
});
it("Should withdraw 1 Ticket from WETH Pod and get back ETH", async function() {
const amount = ethers.utils.parseEther("1")
const podContract = new ethers.Contract(podAddress, podABI, ethers.provider);
let maxFee = await podContract.callStatic["getEarlyExitFee"](amount);
expect(maxFee, "Exit Fee equal to 0 DAI because token still in float").to.be.eq(0);
// maxFee depends on if token has been deposited to PrizePool yet
const spells = [
{
connector: ptConnectorName,
method: "withdrawFromPod",
args: [podAddress, amount, maxFee, 0, 0]
}
]
// Before Deposit Spell
let podBalanceBefore = await podContract.balanceOfUnderlying(dsaWallet0.address)
expect(podBalanceBefore, `Pod balance equal to 1`).to.be.eq(ethers.utils.parseEther("1"));
let ethBalanceBefore = await ethers.provider.getBalance(dsaWallet0.address);
// Run spell transaction
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address)
const receipt = await tx.wait()
// After Deposit spell
let ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address);
expect(ethBalanceAfter, `ETH balance greater than before`).to.be.gt(ethBalanceBefore);
podBalanceAfter = await podContract.balanceOfUnderlying(dsaWallet0.address)
expect(podBalanceAfter, `Pod balance equal to 0`).to.be.eq(ethers.utils.parseEther("0"));
});
});
})

View File

@ -1,153 +0,0 @@
const { expect } = require("chai");
const hre = require("hardhat");
const { waffle, ethers } = hre;
const { provider } = waffle
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js")
const buildDSAv2 = require("../../scripts/buildDSAv2")
const encodeSpells = require("../../scripts/encodeSpells.js")
const getMasterSigner = require("../../scripts/getMasterSigner")
const tokens = require("../../scripts/constant/tokens");
const addresses = require("../../scripts/constant/addresses");
const abis = require("../../scripts/constant/abis");
const connectV2YearnArtifacts = require("../../artifacts/contracts/mainnet/connectors/yearn_v2/main.sol/ConnectV2YearnV2.json")
const toBytes32 = (bn) => {
return ethers.utils.hexlify(ethers.utils.zeroPad(bn.toHexString(), 32));
};
const setStorageAt = async (address, index, value) => {
await ethers.provider.send("hardhat_setStorageAt", [address, index, value]);
await ethers.provider.send("evm_mine", []); // Just mines to the next block
};
describe("Yearn", function () {
const connectorName = "YEARN-TEST-A"
let dsaWallet0
let masterSigner;
let instaConnectorsV2;
let connector;
const wallets = provider.getWallets()
const [wallet0, wallet1, wallet2, wallet3] = wallets
before(async () => {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 12996975,
},
},
],
});
masterSigner = await getMasterSigner(wallet3)
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
connector = await deployAndEnableConnector({
connectorName,
contractArtifact: connectV2YearnArtifacts,
signer: masterSigner,
connectors: instaConnectorsV2
})
console.log("Connector address", connector.address)
})
it("Should have contracts deployed.", async function () {
expect(!!instaConnectorsV2.address).to.be.true;
expect(!!connector.address).to.be.true;
expect(!!masterSigner.address).to.be.true;
});
describe("DSA wallet setup", function () {
it("Should build DSA v2", async function () {
dsaWallet0 = await buildDSAv2(wallet0.address)
expect(!!dsaWallet0.address).to.be.true;
});
it("Deposit ETH into DSA wallet", async function () {
await wallet0.sendTransaction({
to: dsaWallet0.address,
value: ethers.utils.parseEther("10")
});
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
});
});
describe("Main", function () {
it("Should increase the DAI balance to 100 DAI", async function () {
const DAI = new ethers.Contract(tokens.dai.address, abis.basic.erc20, ethers.provider);
const DAI_SLOT = 2;
const locallyManipulatedBalance = ethers.utils.parseEther("100");
// Get storage slot index
const index = ethers.utils.solidityKeccak256(
["uint256", "uint256"],
[dsaWallet0.address, DAI_SLOT]
);
// Manipulate local balance (needs to be bytes32 string)
await setStorageAt(
tokens.dai.address,
index.toString(),
toBytes32(locallyManipulatedBalance).toString()
);
// Get DAI balance
const balance = await DAI.balanceOf(dsaWallet0.address);
expect(await ethers.BigNumber.from(balance).eq(ethers.utils.parseEther("100")));
});
it("Should deposit and withdraw 50 DAI in/out the Yearn Vault", async function () {
const DAI = new ethers.Contract(tokens.dai.address, abis.basic.erc20, ethers.provider);
const DAI_VAULT = '0xdA816459F1AB5631232FE5e97a05BBBb94970c95';
const amount = ethers.utils.parseEther("50") // 50 DAI
const setId = "132456";
const spells = [
{
connector: connectorName,
method: "deposit",
args: [DAI_VAULT, amount, 0, setId]
},
{
connector: connectorName,
method: "withdraw",
args: [DAI_VAULT, amount, setId, 0]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
await tx.wait();
// Get DAI balance
const balance = await DAI.balanceOf(dsaWallet0.address);
expect(await ethers.BigNumber.from(balance).eq(ethers.utils.parseEther("100")));
});
it("Should deposit 70 DAI in the Yearn Vault", async function () {
const DAI_VAULT = '0xdA816459F1AB5631232FE5e97a05BBBb94970c95';
const DAI = new ethers.Contract(tokens.dai.address, abis.basic.erc20, ethers.provider);
const YVDAI = new ethers.Contract(DAI_VAULT, abis.basic.erc20, ethers.provider);
const amount = ethers.utils.parseEther("70") // 70 DAI
const setId = "568445";
const spells = [
{
connector: connectorName,
method: "deposit",
args: [DAI_VAULT, amount, 0, setId]
}
]
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address);
await tx.wait();
// Get DAI balance
const yvDAIBalance = await YVDAI.balanceOf(dsaWallet0.address);
const daiBalance = await DAI.balanceOf(dsaWallet0.address);
const correctDaiBalance = await ethers.BigNumber.from(daiBalance).eq(ethers.utils.parseEther("30"));
const correctYVDaiBalance = await ethers.BigNumber.from(yvDAIBalance).lte(ethers.utils.parseEther("70"));
expect(correctDaiBalance && correctYVDaiBalance);
});
})
})

26
tsconfig.json Normal file
View File

@ -0,0 +1,26 @@
// tsconfig.json
{
"compilerOptions": {
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"lib": ["es5", "es6"],
"module": "commonjs",
"moduleResolution": "node",
"outDir": "dist",
"resolveJsonModule": true,
"sourceMap": true,
"strict": true,
"target": "es5",
},
"exclude": ["artifacts", "node_modules"],
"files": ["./hardhat.config.ts"],
"include": [
"artifacts/**/*",
"artifacts/**/*.json",
"scripts/**/*",
"tasks/**/*",
"test/**/*",
"typechain/**/*",
"types/**/*"
]
}

1726
yarn.lock

File diff suppressed because it is too large Load Diff