Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/minor structural changes #5

Merged
merged 9 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ FORK=false
FORKED_NETWORK=bscmainnet

## Archive nodes
#ARCHIVE_NODE_bsctestnet=https://bsc-testnet.nodereal.io/v1/<YOUR_KEY_HERE>
#ARCHIVE_NODE_bscmainnet=https://bsc-mainnet.nodereal.io/v1/<YOUR_KEY_HERE>
#ARCHIVE_NODE_bscmainnet=http://127.0.0.1:1248
#ARCHIVE_NODE_sepolia=https://ethereum-sepolia.blockpi.network/v1/rpc/public
#ARCHIVE_NODE_ethereum=https://eth-mainnet.nodereal.io/v1/<YOUR_KEY_HERE>
#ARCHIVE_NODE_ethereum=http://127.0.0.1:1248
#LIVE_NETWORK_bsctestnet=https://bsc-testnet.nodereal.io/v1/<YOUR_KEY_HERE>
#LIVE_NETWORK_bscmainnet=https://bsc-mainnet.nodereal.io/v1/<YOUR_KEY_HERE>
#LIVE_NETWORK_bscmainnet=http://127.0.0.1:1248
#LIVE_NETWORK_sepolia=https://ethereum-sepolia.blockpi.network/v1/rpc/public
#LIVE_NETWORK_ethereum=https://eth-mainnet.nodereal.io/v1/<YOUR_KEY_HERE>
#LIVE_NETWORK_ethereum=http://127.0.0.1:1248

ETHERSCAN_API_KEY=
REPORT_GAS=
7 changes: 5 additions & 2 deletions .eslint-tsconfig
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{
"extends": "./tsconfig.json",
"include": [
"tests",
"./src",
"./typechain",
"docgen-templates",
"commitlint.config.js"
"commitlint.config.js",
"wagmi.config.ts",
"src/environment.d.ts"
]
}
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ cache
coverage
dist
typechain
src/config/abis/generated.ts
subgraph-client/.graphqlclient
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"varsIgnorePattern": "_"
}
],
"@typescript-eslint/ban-ts-comment": "warn",
"spaced-comment": [
"error",
"always",
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ artifacts
!.yarn/plugins
!.yarn/sdks
!.yarn/versions

# Generated files
src/config/abis/generated.ts
subgraph-client/.graphclient
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ dist
typechain
contracts/third-party
*.hbs

src/config/abis/generated.ts
subgraph-client/.graphqlclient
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"bracketSpacing": true,
"endOfLine": "auto",
"importOrder": ["module-alias/register", "<THIRD_PARTY_MODULES>", "^[./]"],
"importOrderParserPlugins": ["typescript"],
"importOrderParserPlugins": ["typescript", "importAssertions"],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true,
"printWidth": 120,
Expand Down
24 changes: 12 additions & 12 deletions contracts/operators/TokenConverterOperator.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import { IPancakeV3SwapCallback } from "@pancakeswap/v3-core/contracts/interfaces/callback/IPancakeV3SwapCallback.sol";

Check warning on line 4 in contracts/operators/TokenConverterOperator.sol

View workflow job for this annotation

GitHub Actions / Lint

imported name IPancakeV3SwapCallback is not used
import { IPancakeV3Pool } from "@pancakeswap/v3-core/contracts/interfaces/IPancakeV3Pool.sol";

Check warning on line 5 in contracts/operators/TokenConverterOperator.sol

View workflow job for this annotation

GitHub Actions / Lint

imported name IPancakeV3Pool is not used
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { ensureNonzeroAddress } from "@venusprotocol/solidity-utilities/contracts/validators.sol";

Check warning on line 8 in contracts/operators/TokenConverterOperator.sol

View workflow job for this annotation

GitHub Actions / Lint

imported name ensureNonzeroAddress is not used
import { IAbstractTokenConverter } from "@venusprotocol/protocol-reserve/contracts/TokenConverter/IAbstractTokenConverter.sol";

import { ExactOutputFlashSwap } from "../flash-swap/ExactOutputFlashSwap.sol";
Expand Down Expand Up @@ -139,18 +139,6 @@
_flashSwap(FlashSwapParams({ amountOut: amountToPay, path: params.path, data: abi.encode(data) }));
}

function _validatePath(bytes calldata path, address expectedPathStart, address expectedPathEnd) internal pure {
address swapStart = path.toAddress(0);
if (swapStart != expectedPathStart) {
revert InvalidSwapStart(expectedPathStart, swapStart);
}

address swapEnd = path.toAddress(path.length - 20);
if (swapEnd != expectedPathEnd) {
revert InvalidSwapEnd(expectedPathEnd, swapEnd);
}
}

function _onMoneyReceived(bytes memory data) internal override returns (IERC20 tokenIn, uint256 maxAmountIn) {
ConversionData memory decoded = abi.decode(data, (ConversionData));

Expand Down Expand Up @@ -195,6 +183,18 @@
return tokensReceived;
}

function _validatePath(bytes calldata path, address expectedPathStart, address expectedPathEnd) internal pure {
address swapStart = path.toAddress(0);
if (swapStart != expectedPathStart) {
revert InvalidSwapStart(expectedPathStart, swapStart);
}

address swapEnd = path.toAddress(path.length - 20);
if (swapEnd != expectedPathEnd) {
revert InvalidSwapEnd(expectedPathEnd, swapEnd);
}
}

function _u(int256 value) private pure returns (uint256) {
if (value < 0) {
revert Underflow();
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"docgen": "hardhat docgen",
"prepare": "husky install",
"generate-abis": "yarn wagmi generate",
"postinstall": "yarn generate-abis"
"postinstall": "yarn generate-abis",
"generate-subgraph-types": "rm -rf /subgraph-client/.graphclient && npx graphclient build --dir ./subgraph-client"
},
"keywords": [],
"author": "Venus",
Expand Down Expand Up @@ -92,6 +93,7 @@
"dependencies": {
"@openzeppelin/contracts-upgradeable": "4.9.3",
"@venusprotocol/governance-contracts": "^1.4.0",
"@venusprotocol/isolated-pools": "^2.3.0",
"@venusprotocol/protocol-reserve": "^1.4.0",
"@venusprotocol/venus-protocol": "^7.1.0",
"viem": "^2.1.1"
Expand Down
39 changes: 37 additions & 2 deletions src/config/addresses.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,70 @@
import bscmainnetGovernance from "@venusprotocol/governance-contracts/deployments/bscmainnet_addresses.json";
import bsctestnetGovernance from "@venusprotocol/governance-contracts/deployments/bsctestnet_addresses.json";
import bscmainnetIsolated from "@venusprotocol/isolated-pools/deployments/bscmainnet_addresses.json";
import bsctestnetIsolated from "@venusprotocol/isolated-pools/deployments/bsctestnet_addresses.json";
import bscmainnetProtocolReserve from "@venusprotocol/protocol-reserve/deployments/bscmainnet_addresses.json";
import bsctestnetProtocolReserve from "@venusprotocol/protocol-reserve/deployments/bsctestnet_addresses.json";
import bscmainnetCore from "@venusprotocol/venus-protocol/deployments/bscmainnet_addresses.json";
import bsctestnetCore from "@venusprotocol/venus-protocol/deployments/bsctestnet_addresses.json";

export const addresses = {
import { SUPPORTED_CHAINS } from "./chains";

const addresses = {
bscmainnet: {
...bscmainnetCore.addresses,
...bscmainnetProtocolReserve.addresses,
...bscmainnetGovernance.addresses,
...bscmainnetIsolated.addresses,
BUSD: "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56",
USDT: "0x55d398326f99059fF775485246999027B3197955",
USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
PancakeSwapRouter: "0x13f4EA83D0bd40E75C8222255bc855a974568Dd4",

BTCBPrimeConverter: bscmainnetProtocolReserve.addresses.BTCBPrimeConverter,
ConverterNetwork: bscmainnetProtocolReserve.addresses.ConverterNetwork,
ETHPrimeConverter: bscmainnetProtocolReserve.addresses.ETHPrimeConverter,
RiskFundConverter: bscmainnetProtocolReserve.addresses.RiskFundConverter,
USDCPrimeConverter: bscmainnetProtocolReserve.addresses.USDCPrimeConverter,
USDTPrimeConverter: bscmainnetProtocolReserve.addresses.USDTPrimeConverter,
XVSVaultConverter: bscmainnetProtocolReserve.addresses.XVSVaultConverter,
TokenConverterOperator: "0x",
},
bsctestnet: {
...bsctestnetCore.addresses,
...bsctestnetProtocolReserve.addresses,
...bsctestnetGovernance.addresses,
...bsctestnetIsolated.addresses,
PancakeSwapRouter: "0x1b81D678ffb9C0263b24A97847620C99d213eB14",
xvsHolder: "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706",
usdtHolder: "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706",

BTCBPrimeConverter: bsctestnetProtocolReserve.addresses.BTCBPrimeConverter,
ConverterNetwork: bsctestnetProtocolReserve.addresses.ConverterNetwork,
ETHPrimeConverter: bsctestnetProtocolReserve.addresses.ETHPrimeConverter,
RiskFundConverter: bsctestnetProtocolReserve.addresses.RiskFundConverter,
USDCPrimeConverter: bsctestnetProtocolReserve.addresses.USDCPrimeConverter,
USDTPrimeConverter: bsctestnetProtocolReserve.addresses.USDTPrimeConverter,
XVSVaultConverter: bsctestnetProtocolReserve.addresses.XVSVaultConverter,

TokenConverterOperator: "0x9222F8b71603318d5EEbBf0074c2Da07fEbbB9eb",
},
} as const;

type Addresses = typeof addresses;

export type HasAddressFor<ContractName extends string> = {
[ChainT in keyof Addresses]: Addresses[ChainT] extends Record<ContractName, any> ? ChainT : never;
[ChainT in keyof Addresses]: Addresses[ChainT] extends Record<ContractName, string> ? ChainT : never;
}[keyof Addresses];

export type SupportedConverters =
| "BTCBPrimeConverter"
| "ETHPrimeConverter"
| "RiskFundConverter"
| "USDCPrimeConverter"
| "USDTPrimeConverter"
| "XVSVaultConverter";

const network = process.env.FORKED_NETWORK as SUPPORTED_CHAINS;

export default addresses[network];
4 changes: 4 additions & 0 deletions src/config/chains.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { bsc, bscTestnet } from "viem/chains";

import { HasAddressFor, SupportedConverters } from "./addresses";

export const chains = {
bscmainnet: bsc,
bsctestnet: bscTestnet,
} as const;

export type SUPPORTED_CHAINS = HasAddressFor<"TokenConverterOperator" | SupportedConverters>;
13 changes: 7 additions & 6 deletions src/config/clients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { HttpTransport, PublicClient, WalletClient, createPublicClient, createWa
import { PrivateKeyAccount, privateKeyToAccount } from "viem/accounts";

import { chains } from "./chains";
import type { SUPPORTED_CHAINS } from "./chains";

export const getPublicClient = <ChainT extends keyof typeof chains>(
chainName: ChainT,
): PublicClient<HttpTransport, typeof chains[ChainT]> => {
export const getPublicClient = (
chainName: SUPPORTED_CHAINS,
): PublicClient<HttpTransport, typeof chains[SUPPORTED_CHAINS]> => {
return createPublicClient({
chain: chains[chainName],
transport: http(process.env[`LIVE_NETWORK_${chainName}`]),
Expand All @@ -20,9 +21,9 @@ const readPrivateKeyFromEnv = (chainName: string): PrivateKeyAccount => {
throw new Error(`Invalid private key for ${chainName}. Please specify PRIVATE_KEY_${chainName} env variable.`);
};

export const getWalletClient = <ChainT extends keyof typeof chains>(
chainName: ChainT,
): WalletClient<HttpTransport, typeof chains[ChainT], PrivateKeyAccount> => {
export const getWalletClient = (
chainName: SUPPORTED_CHAINS,
): WalletClient<HttpTransport, typeof chains[SUPPORTED_CHAINS], PrivateKeyAccount> => {
return createWalletClient({
chain: chains[chainName],
transport: http(process.env[`LIVE_NETWORK_${chainName}`]),
Expand Down
48 changes: 12 additions & 36 deletions src/converter-bot/tokenConverterBot.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Address, parseAbi, parseUnits } from "viem";
import { Address, parseAbi } from "viem";

import TokenConverterOperator from "../config/abis/TokenConverterOperator";
import { type HasAddressFor, addresses } from "../config/addresses";
import addresses, { HasAddressFor } from "../config/addresses";
import { chains } from "../config/chains";
import { getPublicClient, getWalletClient } from "../config/clients";
import { Path, parsePath } from "./path";
import { Path } from "./path";

type SupportedConverters =
| "BTCBPrimeConverter"
Expand All @@ -14,22 +14,22 @@ type SupportedConverters =
| "USDTPrimeConverter"
| "XVSVaultConverter";

type SupportedChains = HasAddressFor<"TokenConverterOperator" | SupportedConverters>;
const REVERT_IF_NOT_MINED_AFTER = 60n; // seconds

const REVERT_IF_NOT_MINED_AFTER = 60n; //seconds
export type SUPPORTED_CHAINS = HasAddressFor<"TokenConverterOperator" | SupportedConverters>;

class Bot {
private chainName: SupportedChains;
private chainName: SUPPORTED_CHAINS;
private operator: { address: Address; abi: typeof TokenConverterOperator };
private addresses: typeof addresses[SupportedChains];
private _walletClient?: ReturnType<typeof getWalletClient<SupportedChains>>;
private _publicClient?: ReturnType<typeof getPublicClient<SupportedChains>>;
private addresses: typeof addresses;
private _walletClient?: ReturnType<typeof getWalletClient>;
private _publicClient?: ReturnType<typeof getPublicClient>;

constructor(chainName: SupportedChains) {
constructor(chainName: SUPPORTED_CHAINS) {
this.chainName = chainName;
this.addresses = addresses[chainName];
this.operator = {
address: addresses[chainName].TokenConverterOperator,
address: addresses.TokenConverterOperator,
abi: TokenConverterOperator,
};
}
Expand Down Expand Up @@ -89,28 +89,4 @@ class Bot {
}
}

const main = async () => {
const bot = new Bot("bsctestnet");
await bot.sanityCheck();

// Imagine the converter has LTC and wants USDT
// tokenToSendToConverter: USDT
// tokenToReceiveFromConverter: LTC
// We're swapping LTC to USDT on PCS, so
// the PCS reversed path should start with
// USDT (tokenToSendToConverter) and end
// with LTC (tokenToReceiveFromConverter)
//
// The income is paid out in LTC (if any)
await bot.arbitrage(
"RiskFundConverter",
parsePath([addresses.bsctestnet.USDT as Address, 500, addresses.bsctestnet.LTC as Address]),
parseUnits("1", 18), // 1 LTC
parseUnits("-0.1", 18), // We're ok with paying 0.1 LTC for this conversion
);
};

main().catch(error => {
console.error(error);
process.exit(1);
});
export default Bot;
12 changes: 12 additions & 0 deletions src/environment.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* eslint-disable no-unused-vars */
declare global {
namespace NodeJS {
interface ProcessEnv {
FORKED_NETWORK: "bsctestnet" | "bscmainnet";
}
}
}

// If this file has no import/export statements (i.e. is a script)
// convert it into a module by adding an empty export statement.
export {};
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
"@nomiclabs/hardhat-ethers": ["./node_modules/hardhat-deploy-ethers"]
}
},
"include": ["./typechain", "./tests"],
"include": ["./typechain"],
"files": ["./hardhat.config.ts"]
}
Loading
Loading