mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
commit
b59d97c234
|
@ -2,4 +2,10 @@ ETHERSCAN_API_KEY=""
|
|||
PRIVATE_KEY=""
|
||||
TENDERLY_PROJECT=""
|
||||
TENDERLY_USERNAME=""
|
||||
ALCHEMY_ID=""
|
||||
ALCHEMY_ID=""
|
||||
MAIN_ETHSCAN_KEY=
|
||||
OPT_ETHSCAN_KEY=
|
||||
POLY_ETHSCAN_KEY=
|
||||
ARB_ETHSCAN_KEY=
|
||||
AVAX_ETHSCAN_KEY=
|
||||
FTM_ETHSCAN_KEY=
|
73
README.md
73
README.md
|
@ -47,8 +47,27 @@ Run all the tests:
|
|||
```sh
|
||||
$ npm run test
|
||||
```
|
||||
|
||||
(Striclty use this envirnment to test, or otherwise make suitable changes in config file before testing).
|
||||
|
||||
### Deploy
|
||||
|
||||
To deploy a connector using interactive CLI
|
||||
|
||||
```sh
|
||||
$ npm run deploy:runner
|
||||
```
|
||||
|
||||
(To deploy script manually use `scripts/deployment/deployManually.ts` script)
|
||||
|
||||
### checks
|
||||
|
||||
To check that code is compatible with github actions
|
||||
|
||||
```sh
|
||||
$ npm run check
|
||||
```
|
||||
|
||||
## How to add a new connector
|
||||
|
||||
You can create a new PR to add a new connector. To get the PR merged, certain requirements needs to be met which will be explained here.
|
||||
|
@ -57,39 +76,39 @@ You can create a new PR to add a new connector. To get the PR merged, certain re
|
|||
|
||||
Common files for all connectors are in `contracts/common` directory.
|
||||
|
||||
* `math.sol` has methods for mathematical operations (`DSMath`)
|
||||
* `interfaces.sol` contains the common interfaces
|
||||
* `TokenInterface` for ERC-20 interface including WETH
|
||||
* `stores.sol` contains the global constants as well as methods `getId` & `setId` (`Stores`)
|
||||
* `basic.sol` inherits `DSMath` & `Stores` contracts. This contains few details explained below
|
||||
* Wrapping & unwrapping ETH (`convertEthToWeth` & `convertWethToEth`)
|
||||
* Getting token & ETH balance of DSA
|
||||
- `math.sol` has methods for mathematical operations (`DSMath`)
|
||||
- `interfaces.sol` contains the common interfaces
|
||||
- `TokenInterface` for ERC-20 interface including WETH
|
||||
- `stores.sol` contains the global constants as well as methods `getId` & `setId` (`Stores`)
|
||||
- `basic.sol` inherits `DSMath` & `Stores` contracts. This contains few details explained below
|
||||
- Wrapping & unwrapping ETH (`convertEthToWeth` & `convertWethToEth`)
|
||||
- Getting token & ETH balance of DSA
|
||||
|
||||
Connectors are under `contracts/connectors` directory, and should be formatted as follows:
|
||||
|
||||
* Connector events should be in a separate contract: `events.sol`
|
||||
* Interfaces should be defined in a seperate file: `interface.sol`
|
||||
* If the connector has helper methods & constants (including interface instances), this should be defined in a separate file: `helpers.sol`
|
||||
* `Helpers` contract should inherit `Basic` contract from common directory
|
||||
* If the connector doesn't have any helper methods, the main contract should inherit `Basic` contract
|
||||
* The main logic of the contract should be under `main.sol`, and the contract should inherit `Helpers` (if exists, otherwise `Basic`) & `Events`
|
||||
- Connector events should be in a separate contract: `events.sol`
|
||||
- Interfaces should be defined in a seperate file: `interface.sol`
|
||||
- If the connector has helper methods & constants (including interface instances), this should be defined in a separate file: `helpers.sol`
|
||||
- `Helpers` contract should inherit `Basic` contract from common directory
|
||||
- If the connector doesn't have any helper methods, the main contract should inherit `Basic` contract
|
||||
- The main logic of the contract should be under `main.sol`, and the contract should inherit `Helpers` (if exists, otherwise `Basic`) & `Events`
|
||||
|
||||
Few things to consider while writing the connector:
|
||||
|
||||
* Connector should have a public constant string declared `name`, which will be the name of the connector. This will be versioned. Ex: `Compound-v1`
|
||||
* Contract name should start with `ConnectV2` appended with protocol name. Eg: `ConnectV2Compound`
|
||||
* User interacting methods (`external` methods) will not be emitting events, rather the methods will be returning 2 variables:
|
||||
* `_eventName` of `string` type: This will be the event signture defined in the `Events` contract. Ex: `LogDeposit(address,address,uint256,uint256,uint256)`
|
||||
* `_eventParam` of `bytes` type: This will be the abi encoded event parameters
|
||||
* The contracts should not have `selfdestruct()`
|
||||
* The contracts should not have `delegatecall()`
|
||||
* Use `uint(-1)` of `type(uint256).max` for maximum amount everywhere
|
||||
* Use `ethAddr` (declared in `Stores`) to denote Ethereum (non-ERC20)
|
||||
* Use `address(this)` instead of `msg.sender` for fetching balance on-chain, etc
|
||||
* Only `approve()` (declared in `Basic`) limited amount while giving ERC20 allowance, which strictly needs to be 0 by the end of the spell.
|
||||
* User interacting functions should have natspec comments(@dev, @notice, @param).
|
||||
* Use `getUint()` (declared in `Stores`) for getting value that saved from previous spell
|
||||
* Use `setUint()` (declared in `Stores`) for setting value to save for the future spell
|
||||
- Connector should have a public constant string declared `name`, which will be the name of the connector. This will be versioned. Ex: `Compound-v1`
|
||||
- Contract name should start with `ConnectV2` appended with protocol name. Eg: `ConnectV2Compound`
|
||||
- User interacting methods (`external` methods) will not be emitting events, rather the methods will be returning 2 variables:
|
||||
- `_eventName` of `string` type: This will be the event signture defined in the `Events` contract. Ex: `LogDeposit(address,address,uint256,uint256,uint256)`
|
||||
- `_eventParam` of `bytes` type: This will be the abi encoded event parameters
|
||||
- The contracts should not have `selfdestruct()`
|
||||
- The contracts should not have `delegatecall()`
|
||||
- Use `uint(-1)` of `type(uint256).max` for maximum amount everywhere
|
||||
- Use `ethAddr` (declared in `Stores`) to denote Ethereum (non-ERC20)
|
||||
- Use `address(this)` instead of `msg.sender` for fetching balance on-chain, etc
|
||||
- Only `approve()` (declared in `Basic`) limited amount while giving ERC20 allowance, which strictly needs to be 0 by the end of the spell.
|
||||
- User interacting functions should have natspec comments(@dev, @notice, @param).
|
||||
- Use `getUint()` (declared in `Stores`) for getting value that saved from previous spell
|
||||
- Use `setUint()` (declared in `Stores`) for setting value to save for the future spell
|
||||
|
||||
### Support
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import { NetworkUserConfig } from "hardhat/types";
|
|||
import { utils } from "ethers";
|
||||
import Web3 from "web3";
|
||||
import { network } from "hardhat";
|
||||
import bigNumber from "bignumber.js";
|
||||
|
||||
dotenvConfig({ path: resolve(__dirname, "./.env") });
|
||||
|
||||
|
@ -34,26 +35,22 @@ if (!alchemyApiKey) {
|
|||
}
|
||||
|
||||
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 FANTOMSCAN_API = process.env.FANTOM_API_KEY;
|
||||
const OPTIMISM_API = process.env.OPTIMISM_API_KEY;
|
||||
const mnemonic = process.env.MNEMONIC ?? "test test test test test test test test test test test junk";
|
||||
|
||||
const networkGasPriceConfig: Record<string, string> = {
|
||||
mainnet: "160",
|
||||
polygon: "50",
|
||||
avalanche: "50",
|
||||
arbitrum: "2"
|
||||
const networkGasPriceConfig: Record<string, number> = {
|
||||
mainnet: 100,
|
||||
polygon: 50,
|
||||
avalanche: 30,
|
||||
arbitrum: 1,
|
||||
optimism: 0.001,
|
||||
fantom: 300
|
||||
};
|
||||
|
||||
function createConfig(network: string) {
|
||||
return {
|
||||
url: getNetworkUrl(network),
|
||||
accounts: !!PRIVATE_KEY ? [`0x${PRIVATE_KEY}`] : { mnemonic },
|
||||
gasPrice: 35 * 1e9 // 0.0001 GWEI
|
||||
gasPrice: new bigNumber(networkGasPriceConfig[network]).multipliedBy(1e9).toNumber() // Update the mapping above
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -66,16 +63,6 @@ function getNetworkUrl(networkType: string) {
|
|||
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 if (networkType === "fantom") return FANTOMSCAN_API;
|
||||
else if (networkType === "fantom") return FANTOMSCAN_API;
|
||||
else if (networkType === "optimism") return OPTIMISM_API;
|
||||
else return ETHERSCAN_API;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type import('hardhat/config').HardhatUserConfig
|
||||
*/
|
||||
|
@ -126,7 +113,14 @@ const config: HardhatUserConfig = {
|
|||
tests: "./test"
|
||||
},
|
||||
etherscan: {
|
||||
apiKey: "CZ1YB396AX4XAQ489Y4NJ33SJBCYZZD1VS"
|
||||
apiKey: {
|
||||
mainnet: String(process.env.MAIN_ETHSCAN_KEY),
|
||||
optimisticEthereum: String(process.env.OPT_ETHSCAN_KEY),
|
||||
polygon: String(process.env.POLY_ETHSCAN_KEY),
|
||||
arbitrumOne: String(process.env.ARB_ETHSCAN_KEY),
|
||||
avalanche: String(process.env.AVAX_ETHSCAN_KEY),
|
||||
opera: String(process.env.FTM_ETHSCAN_KEY)
|
||||
}
|
||||
},
|
||||
typechain: {
|
||||
outDir: "typechain",
|
||||
|
|
37
package-lock.json
generated
37
package-lock.json
generated
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@nomiclabs/hardhat-ethers": "^2.0.3",
|
||||
"@nomiclabs/hardhat-etherscan": "^2.1.8",
|
||||
"@nomiclabs/hardhat-etherscan": "^3.0.3",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
||||
"@nomiclabs/hardhat-web3": "^2.0.0",
|
||||
"@openzeppelin/test-helpers": "^0.5.15",
|
||||
|
@ -2121,9 +2121,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@nomiclabs/hardhat-etherscan": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-2.1.8.tgz",
|
||||
"integrity": "sha512-0+rj0SsZotVOcTLyDOxnOc3Gulo8upo0rsw/h+gBPcmtj91YqYJNhdARHoBxOhhE8z+5IUQPx+Dii04lXT14PA==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.0.3.tgz",
|
||||
"integrity": "sha512-OfNtUKc/ZwzivmZnnpwWREfaYncXteKHskn3yDnz+fPBZ6wfM4GR+d5RwjREzYFWE+o5iR9ruXhWw/8fejWM9g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@ethersproject/abi": "^5.1.2",
|
||||
|
@ -2131,8 +2131,8 @@
|
|||
"cbor": "^5.0.2",
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^7.0.1",
|
||||
"node-fetch": "^2.6.0",
|
||||
"semver": "^6.3.0"
|
||||
"semver": "^6.3.0",
|
||||
"undici": "^4.14.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"hardhat": "^2.0.4"
|
||||
|
@ -28736,6 +28736,15 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "4.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-4.16.0.tgz",
|
||||
"integrity": "sha512-tkZSECUYi+/T1i4u+4+lwZmQgLXd4BLGlrc7KZPcLIW7Jpq99+Xpc30ONv7nS6F5UNOxp/HBZSSL9MafUrvJbw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12.18"
|
||||
}
|
||||
},
|
||||
"node_modules/union-value": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
||||
|
@ -32499,9 +32508,9 @@
|
|||
"requires": {}
|
||||
},
|
||||
"@nomiclabs/hardhat-etherscan": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-2.1.8.tgz",
|
||||
"integrity": "sha512-0+rj0SsZotVOcTLyDOxnOc3Gulo8upo0rsw/h+gBPcmtj91YqYJNhdARHoBxOhhE8z+5IUQPx+Dii04lXT14PA==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.0.3.tgz",
|
||||
"integrity": "sha512-OfNtUKc/ZwzivmZnnpwWREfaYncXteKHskn3yDnz+fPBZ6wfM4GR+d5RwjREzYFWE+o5iR9ruXhWw/8fejWM9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@ethersproject/abi": "^5.1.2",
|
||||
|
@ -32509,8 +32518,8 @@
|
|||
"cbor": "^5.0.2",
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^7.0.1",
|
||||
"node-fetch": "^2.6.0",
|
||||
"semver": "^6.3.0"
|
||||
"semver": "^6.3.0",
|
||||
"undici": "^4.14.1"
|
||||
}
|
||||
},
|
||||
"@nomiclabs/hardhat-waffle": {
|
||||
|
@ -53586,6 +53595,12 @@
|
|||
"which-boxed-primitive": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"undici": {
|
||||
"version": "4.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-4.16.0.tgz",
|
||||
"integrity": "sha512-tkZSECUYi+/T1i4u+4+lwZmQgLXd4BLGlrc7KZPcLIW7Jpq99+Xpc30ONv7nS6F5UNOxp/HBZSSL9MafUrvJbw==",
|
||||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@nomiclabs/hardhat-ethers": "^2.0.3",
|
||||
"@nomiclabs/hardhat-etherscan": "^2.1.8",
|
||||
"@nomiclabs/hardhat-etherscan": "^3.0.3",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
||||
"@nomiclabs/hardhat-web3": "^2.0.0",
|
||||
"@openzeppelin/test-helpers": "^0.5.15",
|
||||
|
|
23
scripts/deployment/deployManually.ts
Normal file
23
scripts/deployment/deployManually.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { Contract } from "@ethersproject/contracts";
|
||||
import hre, { ethers } from "hardhat";
|
||||
|
||||
import { Greeter__factory } from "../../typechain";
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const Greeter: Greeter__factory = await ethers.getContractFactory("Greeter");
|
||||
const greeter: Contract = await Greeter.deploy("Hello, Buidler!");
|
||||
await greeter.deployed();
|
||||
|
||||
console.log("Greeter deployed to: ", greeter.address);
|
||||
|
||||
await hre.run("verify:verify", {
|
||||
address: greeter.address
|
||||
});
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error: Error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
Loading…
Reference in New Issue
Block a user