diff --git a/.env.local b/.env.local index 8f5b43368..f6f6c776c 100644 --- a/.env.local +++ b/.env.local @@ -1,14 +1,9 @@ REACT_APP_DEFAULT_CHAINID=42161 REACT_APP_VERSION=$npm_package_version -REACT_APP_RPC_URL_1='https://eth-mainnet.g.alchemy.com/v2/ZXDCq5iy0KrKR0XjsqC6E4QG7Z_FuXDv' -REACT_APP_RPC_URL_42161='https://arb-mainnet.g.alchemy.com/v2/vtMM4_eLnOvkjkdckprVw3cIa64EVkDZ' - -REACT_APP_DEFAULT_FORK_RPC_URL='https://rpc.tenderly.co/fork/6fd873f9-62cb-44b7-a7ab-e871f8f3b764' +REACT_APP_DEFAULT_FORK_RPC_URL='https://rpc.tenderly.co/fork/90a229c1-7aef-4d13-a897-24e14b070508' REACT_APP_LOCALHOST_RPC_URL='http://127.0.0.1:8545' -REACT_APP_RPC_URL_421611='https://arb-rinkeby.g.alchemy.com/v2/AY_Q_Uy-Kcfwmf5In5qwG636vaOIoA8L' - TENDERLY_USER='Yield' TENDERLY_PROJECT='v2' TENDERLY_ACCESS_KEY='B4N3hpAhTmY09c3pyeC9zC8rMfto7ukj' @@ -23,4 +18,4 @@ ALLOWED_SUPPORT_ADDRESSES='0x1Bd3Abb6ef058408734EA01cA81D325039cd7bcA, ' KILLSWITCH_ACTIVE=false KILLSWITCH_CHAIN=1 -KILLSWITCH_TEXT='Due to an Euler Finance security incident, we are suspending UI interaction with the Yield Protocol until we have fully assessed the implications of the breach' +KILLSWITCH_TEXT='Due to an incident, we are suspending UI interaction with the Yield Protocol until we have fully assessed the implications of the breach' diff --git a/next.config.js b/next.config.js index 5ccddd31b..9408bfb03 100644 --- a/next.config.js +++ b/next.config.js @@ -5,9 +5,6 @@ const nextConfig = { env: { REACT_APP_DEFAULT_CHAINID: process.env.REACT_APP_DEFAULT_CHAINID, REACT_APP_VERSION: process.env.REACT_APP_VERSION, - REACT_APP_INFURA_KEY_V1: process.env.REACT_APP_INFURA_KEY_V1, - REACT_APP_RPC_URL_1: process.env.TENDERLY_JSON_RPC_URL, - REACT_APP_RPC_URL_42161: process.env.REACT_APP_RPC_URL_42161, REACT_APP_DEFAULT_FORK_RPC_URL: process.env.REACT_APP_DEFAULT_FORK_RPC_URL, REACT_APP_LOCALHOST_RPC_URL: process.env.REACT_APP_LOCALHOST_RPC_URL, @@ -22,6 +19,7 @@ const nextConfig = { TENDERLY_ACCESS_KEY: process.env.TENDERLY_ACCESS_KEY, ALLOWED_SUPPORT_ADDRESSES: process.env.ALLOWED_SUPPORT_ADDRESSES, + KILLSWITCH_ACTIVE: process.env.KILLSWITCH_ACTIVE, KILLSWITCH_TEXT: process.env.KILLSWITCH_TEXT, KILLSWITCH_CHAIN: process.env.KILLSWITCH_CHAIN, diff --git a/src/components/selectors/AssetSelector.tsx b/src/components/selectors/AssetSelector.tsx index 5814e2652..4ae8521c9 100644 --- a/src/components/selectors/AssetSelector.tsx +++ b/src/components/selectors/AssetSelector.tsx @@ -43,6 +43,7 @@ function AssetSelector({ selectCollateral, isModal }: IAssetSelectorProps) { const [options, setOptions] = useState([]); const [modalOpen, toggleModal] = useState(false); const { logAnalyticsEvent } = useAnalytics(); + const { validIlks, validIlksLoading } = useAssetPair(undefined, undefined, selectedSeries?.id); const optionText = (asset: IAsset | undefined) => @@ -79,7 +80,7 @@ function AssetSelector({ selectCollateral, isModal }: IAssetSelectorProps) { /* update options on any changes */ useEffect(() => { - const opts = (selectCollateral ? validIlks! : Array.from(assetMap.values())) + const opts = (selectCollateral && validIlks ? validIlks : Array.from(assetMap.values())) // if !validIlks, then we just return all assets ( for forked env ) .filter((a) => a.showToken) .filter((a) => (showWrappedTokens ? true : !a.isWrappedToken)); // filter based on whether wrapped tokens are shown or not diff --git a/src/config/assets.ts b/src/config/assets.ts index 290ef7d24..d226c4d8a 100644 --- a/src/config/assets.ts +++ b/src/config/assets.ts @@ -12,7 +12,6 @@ export interface AssetStaticInfo { digitFormat: number; // this is the 'reasonable' number of digits to show. accuracy equivalent to +- 1 us cent. tokenRoles: TokenRole[]; - // optionals // isYieldBase?: boolean; diff --git a/src/config/contracts.ts b/src/config/contracts.ts index e2d1679f9..004a2821b 100644 --- a/src/config/contracts.ts +++ b/src/config/contracts.ts @@ -8,6 +8,7 @@ export enum ContractNames { WRAP_ETHER_MODULE = 'WrapEtherModule', CONVEX_LADLE_MODULE = 'ConvexLadleModule', TRANSFER_1155_MODULE = 'Transfer1155Module', + ASSERT = 'Assert', } export type ContractMap = Map; @@ -28,6 +29,7 @@ const contractAddresses: ContractAddresses = { [ContractNames.TRANSFER_1155_MODULE, '0x97f1d43A217aDD678bB6Dcd3C5D51F40b6729d06'], [ContractNames.WRAP_ETHER_MODULE, '0x22768FCaFe7BB9F03e31cb49823d1Ece30C0b8eA'], [ContractNames.CONVEX_LADLE_MODULE, '0x9Bf195997581C99cef8be95a3a816Ca19Cf1A3e6'], + [ContractNames.ASSERT, '0x40f0b18c7a41c04f848c033ed7f9178d9c5a80d8'], ]), ], [ @@ -38,6 +40,7 @@ const contractAddresses: ContractAddresses = { [ContractNames.WITCH, '0x08173D0885B00BDD640aaE57D05AbB74cd00d669'], [ContractNames.WITCHV2, '0x07c2c74811cb14a5003c3ccff7ec436d504fffb6'], [ContractNames.WRAP_ETHER_MODULE, '0x4cd01ed221d6d198e2656c16c32803bf78134568'], + [ContractNames.ASSERT, '0x40f0b18c7a41c04f848c033ed7f9178d9c5a80d8'], ]), ], ]), diff --git a/src/contexts/SettingsContext.tsx b/src/contexts/SettingsContext.tsx index 013d376c6..09b9275d6 100644 --- a/src/contexts/SettingsContext.tsx +++ b/src/contexts/SettingsContext.tsx @@ -1,6 +1,7 @@ import { createContext, Dispatch, ReactNode, useEffect, useReducer } from 'react'; import { USDC } from '../config/assets'; import { ApprovalType } from '../types'; +import { BLANK_ADDRESS } from '../utils/constants'; import { ISettingsContextActions, ISettingsContextState, Settings, SettingsContextAction } from './types/settings'; const initState: ISettingsContextState = { @@ -39,6 +40,7 @@ const initState: ISettingsContextState = { /* Development settings */ /* Always force transctions to the chain -> even if they will likely fail */ + forceTransactions: false, /* Show diagnostic messages in the console */ diff --git a/src/contracts/Assert.d.ts b/src/contracts/Assert.d.ts new file mode 100644 index 000000000..71a77d919 --- /dev/null +++ b/src/contracts/Assert.d.ts @@ -0,0 +1,956 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + +import { + ethers, + EventFilter, + Signer, + BigNumber, + BigNumberish, + PopulatedTransaction, + BaseContract, + ContractTransaction, + Overrides, + CallOverrides, +} from "ethers"; +import { BytesLike } from "@ethersproject/bytes"; +import { Listener, Provider } from "@ethersproject/providers"; +import { FunctionFragment, EventFragment, Result } from "@ethersproject/abi"; +import type { TypedEventFilter, TypedEvent, TypedListener } from "./common"; + +interface AssertInterface extends ethers.utils.Interface { + functions: { + "assertEq(address,bytes,address,bytes)": FunctionFragment; + "assertEqAbs(address,bytes,address,bytes,uint256)": FunctionFragment; + "assertEqRel(address,bytes,uint256,uint256)": FunctionFragment; + "assertGe(address,bytes,address,bytes)": FunctionFragment; + "assertGt(address,bytes,address,bytes)": FunctionFragment; + "assertLe(address,bytes,uint256)": FunctionFragment; + "assertLt(address,bytes,uint256)": FunctionFragment; + }; + + encodeFunctionData( + functionFragment: "assertEq", + values: [string, BytesLike, string, BytesLike] + ): string; + encodeFunctionData( + functionFragment: "assertEqAbs", + values: [string, BytesLike, string, BytesLike, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "assertEqRel", + values: [string, BytesLike, BigNumberish, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "assertGe", + values: [string, BytesLike, string, BytesLike] + ): string; + encodeFunctionData( + functionFragment: "assertGt", + values: [string, BytesLike, string, BytesLike] + ): string; + encodeFunctionData( + functionFragment: "assertLe", + values: [string, BytesLike, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "assertLt", + values: [string, BytesLike, BigNumberish] + ): string; + + decodeFunctionResult(functionFragment: "assertEq", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "assertEqAbs", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "assertEqRel", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "assertGe", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "assertGt", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "assertLe", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "assertLt", data: BytesLike): Result; + + events: {}; +} + +export class Assert extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + listeners, EventArgsObject>( + eventFilter?: TypedEventFilter + ): Array>; + off, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this; + on, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this; + once, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this; + removeListener, EventArgsObject>( + eventFilter: TypedEventFilter, + listener: TypedListener + ): this; + removeAllListeners, EventArgsObject>( + eventFilter: TypedEventFilter + ): this; + + listeners(eventName?: string): Array; + off(eventName: string, listener: Listener): this; + on(eventName: string, listener: Listener): this; + once(eventName: string, listener: Listener): this; + removeListener(eventName: string, listener: Listener): this; + removeAllListeners(eventName?: string): this; + + queryFilter, EventArgsObject>( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + interface: AssertInterface; + + functions: { + "assertEq(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEq(bytes,bytes)"( + actual: BytesLike, + expected: BytesLike, + overrides?: CallOverrides + ): Promise<[void]>; + + "assertEq(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise<[void]>; + + "assertEq(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEq(bool,bool)"( + actual: boolean, + expected: boolean, + overrides?: CallOverrides + ): Promise<[void]>; + + "assertEqAbs(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + abs: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqAbs(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + abs: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqAbs(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + abs: BigNumberish, + overrides?: CallOverrides + ): Promise<[void]>; + + "assertEqRel(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + rel: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqRel(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + rel: BigNumberish, + overrides?: CallOverrides + ): Promise<[void]>; + + "assertEqRel(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + rel: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise<[void]>; + + "assertGe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise<[void]>; + + "assertLe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise<[void]>; + + "assertLe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise<[void]>; + + "assertLt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + }; + + "assertEq(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEq(bytes,bytes)"( + actual: BytesLike, + expected: BytesLike, + overrides?: CallOverrides + ): Promise; + + "assertEq(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEq(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEq(bool,bool)"( + actual: boolean, + expected: boolean, + overrides?: CallOverrides + ): Promise; + + "assertEqAbs(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + abs: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqAbs(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + abs: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqAbs(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + abs: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqRel(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + rel: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqRel(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + rel: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqRel(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + rel: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertGe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + callStatic: { + "assertEq(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: CallOverrides + ): Promise; + + "assertEq(bytes,bytes)"( + actual: BytesLike, + expected: BytesLike, + overrides?: CallOverrides + ): Promise; + + "assertEq(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEq(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEq(bool,bool)"( + actual: boolean, + expected: boolean, + overrides?: CallOverrides + ): Promise; + + "assertEqAbs(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + abs: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqAbs(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + abs: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqAbs(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + abs: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqRel(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + rel: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqRel(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + rel: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqRel(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + rel: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertGe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: CallOverrides + ): Promise; + + "assertGe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertGe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertGt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: CallOverrides + ): Promise; + + "assertGt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertGt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: CallOverrides + ): Promise; + + "assertLt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: CallOverrides + ): Promise; + }; + + filters: {}; + + estimateGas: { + "assertEq(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEq(bytes,bytes)"( + actual: BytesLike, + expected: BytesLike, + overrides?: CallOverrides + ): Promise; + + "assertEq(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEq(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEq(bool,bool)"( + actual: boolean, + expected: boolean, + overrides?: CallOverrides + ): Promise; + + "assertEqAbs(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + abs: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqAbs(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + abs: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqAbs(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + abs: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqRel(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + rel: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqRel(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + rel: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqRel(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + rel: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertGe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + }; + + populateTransaction: { + "assertEq(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEq(bytes,bytes)"( + actual: BytesLike, + expected: BytesLike, + overrides?: CallOverrides + ): Promise; + + "assertEq(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEq(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEq(bool,bool)"( + actual: boolean, + expected: boolean, + overrides?: CallOverrides + ): Promise; + + "assertEqAbs(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + abs: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqAbs(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + abs: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqAbs(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + abs: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqRel(address,bytes,uint256,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + rel: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertEqRel(uint256,uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + rel: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertEqRel(address,bytes,address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + rel: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertGe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertGt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLe(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLe(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLe(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLt(address,bytes,uint256)"( + actualTarget: string, + actualCalldata: BytesLike, + expected: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + + "assertLt(uint256,uint256)"( + actual: BigNumberish, + expected: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "assertLt(address,bytes,address,bytes)"( + actualTarget: string, + actualCalldata: BytesLike, + expectedTarget: string, + expectedCalldata: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + }; +} diff --git a/src/contracts/abis/Assert.json b/src/contracts/abis/Assert.json new file mode 100644 index 000000000..7133b1fe1 --- /dev/null +++ b/src/contracts/abis/Assert.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"address","name":"expectedTarget","type":"address"},{"internalType":"bytes","name":"expectedCalldata","type":"bytes"}],"name":"assertEq","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"actual","type":"bytes"},{"internalType":"bytes","name":"expected","type":"bytes"}],"name":"assertEq","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertEq","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertEq","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"actual","type":"bool"},{"internalType":"bool","name":"expected","type":"bool"}],"name":"assertEq","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"address","name":"expectedTarget","type":"address"},{"internalType":"bytes","name":"expectedCalldata","type":"bytes"},{"internalType":"uint256","name":"abs","type":"uint256"}],"name":"assertEqAbs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"abs","type":"uint256"}],"name":"assertEqAbs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"abs","type":"uint256"}],"name":"assertEqAbs","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"rel","type":"uint256"}],"name":"assertEqRel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"rel","type":"uint256"}],"name":"assertEqRel","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"address","name":"expectedTarget","type":"address"},{"internalType":"bytes","name":"expectedCalldata","type":"bytes"},{"internalType":"uint256","name":"rel","type":"uint256"}],"name":"assertEqRel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"address","name":"expectedTarget","type":"address"},{"internalType":"bytes","name":"expectedCalldata","type":"bytes"}],"name":"assertGe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertGe","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertGe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"address","name":"expectedTarget","type":"address"},{"internalType":"bytes","name":"expectedCalldata","type":"bytes"}],"name":"assertGt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertGt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertGt","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertLe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertLe","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"address","name":"expectedTarget","type":"address"},{"internalType":"bytes","name":"expectedCalldata","type":"bytes"}],"name":"assertLe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertLt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"assertLt","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"actualTarget","type":"address"},{"internalType":"bytes","name":"actualCalldata","type":"bytes"},{"internalType":"address","name":"expectedTarget","type":"address"},{"internalType":"bytes","name":"expectedCalldata","type":"bytes"}],"name":"assertLt","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/src/contracts/factories/Assert__factory.ts b/src/contracts/factories/Assert__factory.ts new file mode 100644 index 000000000..3b122e070 --- /dev/null +++ b/src/contracts/factories/Assert__factory.ts @@ -0,0 +1,569 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + +import { Contract, Signer, utils } from "ethers"; +import { Provider } from "@ethersproject/providers"; +import type { Assert, AssertInterface } from "../Assert"; + +const _abi = [ + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "address", + name: "expectedTarget", + type: "address", + }, + { + internalType: "bytes", + name: "expectedCalldata", + type: "bytes", + }, + ], + name: "assertEq", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes", + name: "actual", + type: "bytes", + }, + { + internalType: "bytes", + name: "expected", + type: "bytes", + }, + ], + name: "assertEq", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "actual", + type: "uint256", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertEq", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertEq", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bool", + name: "actual", + type: "bool", + }, + { + internalType: "bool", + name: "expected", + type: "bool", + }, + ], + name: "assertEq", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "address", + name: "expectedTarget", + type: "address", + }, + { + internalType: "bytes", + name: "expectedCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "abs", + type: "uint256", + }, + ], + name: "assertEqAbs", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + { + internalType: "uint256", + name: "abs", + type: "uint256", + }, + ], + name: "assertEqAbs", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "actual", + type: "uint256", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + { + internalType: "uint256", + name: "abs", + type: "uint256", + }, + ], + name: "assertEqAbs", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + { + internalType: "uint256", + name: "rel", + type: "uint256", + }, + ], + name: "assertEqRel", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "actual", + type: "uint256", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + { + internalType: "uint256", + name: "rel", + type: "uint256", + }, + ], + name: "assertEqRel", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "address", + name: "expectedTarget", + type: "address", + }, + { + internalType: "bytes", + name: "expectedCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "rel", + type: "uint256", + }, + ], + name: "assertEqRel", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "address", + name: "expectedTarget", + type: "address", + }, + { + internalType: "bytes", + name: "expectedCalldata", + type: "bytes", + }, + ], + name: "assertGe", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "actual", + type: "uint256", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertGe", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertGe", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "address", + name: "expectedTarget", + type: "address", + }, + { + internalType: "bytes", + name: "expectedCalldata", + type: "bytes", + }, + ], + name: "assertGt", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertGt", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "actual", + type: "uint256", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertGt", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertLe", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "actual", + type: "uint256", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertLe", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "address", + name: "expectedTarget", + type: "address", + }, + { + internalType: "bytes", + name: "expectedCalldata", + type: "bytes", + }, + ], + name: "assertLe", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertLt", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "actual", + type: "uint256", + }, + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + ], + name: "assertLt", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "actualTarget", + type: "address", + }, + { + internalType: "bytes", + name: "actualCalldata", + type: "bytes", + }, + { + internalType: "address", + name: "expectedTarget", + type: "address", + }, + { + internalType: "bytes", + name: "expectedCalldata", + type: "bytes", + }, + ], + name: "assertLt", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; + +export class Assert__factory { + static readonly abi = _abi; + static createInterface(): AssertInterface { + return new utils.Interface(_abi) as AssertInterface; + } + static connect(address: string, signerOrProvider: Signer | Provider): Assert { + return new Contract(address, _abi, signerOrProvider) as Assert; + } +} diff --git a/src/contracts/index.ts b/src/contracts/index.ts index eb26a04ae..49a457801 100644 --- a/src/contracts/index.ts +++ b/src/contracts/index.ts @@ -2,6 +2,7 @@ /* tslint:disable */ /* eslint-disable */ export type { AccumulatorOracle } from "./AccumulatorOracle"; +export type { Assert } from "./Assert"; export type { Cauldron } from "./Cauldron"; export type { ChainlinkMultiOracle } from "./ChainlinkMultiOracle"; export type { ChainlinkUSDOracle } from "./ChainlinkUSDOracle"; @@ -28,6 +29,7 @@ export type { WrapEtherModule } from "./WrapEtherModule"; export type { YearnVaultMultiOracle } from "./YearnVaultMultiOracle"; export { AccumulatorOracle__factory } from "./factories/AccumulatorOracle__factory"; +export { Assert__factory } from "./factories/Assert__factory"; export { Cauldron__factory } from "./factories/Cauldron__factory"; export { ChainlinkMultiOracle__factory } from "./factories/ChainlinkMultiOracle__factory"; export { ChainlinkUSDOracle__factory } from "./factories/ChainlinkUSDOracle__factory"; diff --git a/src/hooks/actionHooks/useAddCollateral.ts b/src/hooks/actionHooks/useAddCollateral.ts index 3423ab4d7..506d0105f 100644 --- a/src/hooks/actionHooks/useAddCollateral.ts +++ b/src/hooks/actionHooks/useAddCollateral.ts @@ -1,29 +1,30 @@ -import { ethers } from 'ethers'; +import { BigNumber, ethers } from 'ethers'; import { useContext } from 'react'; import { UserContext } from '../../contexts/UserContext'; -import { ICallData, IVault, ActionCodes, LadleActions, IAsset, IHistoryContext } from '../../types'; +import { ICallData, IVault, ActionCodes, LadleActions, IAsset, IHistoryContext, TokenType } from '../../types'; import { cleanValue, getTxCode } from '../../utils/appUtils'; -import { BLANK_VAULT, ZERO_BN } from '../../utils/constants'; -import { CONVEX_BASED_ASSETS, ETH_BASED_ASSETS } from '../../config/assets'; +import { BLANK_VAULT, WAD_BN, ZERO_BN } from '../../utils/constants'; +import { CONVEX_BASED_ASSETS, ETH_BASED_ASSETS, WETH } from '../../config/assets'; import { useChain } from '../useChain'; import { useWrapUnwrapAsset } from './useWrapUnwrapAsset'; import { useAddRemoveEth } from './useAddRemoveEth'; -import { ConvexLadleModule } from '../../contracts'; +import { Cauldron, ConvexLadleModule } from '../../contracts'; import { ModuleActions } from '../../types/operations'; import { HistoryContext } from '../../contexts/HistoryContext'; import { Address, useBalance } from 'wagmi'; import useContracts from '../useContracts'; import useAccountPlus from '../useAccountPlus'; +import { useAssert, AssertActions } from './useAssert'; import { ContractNames } from '../../config/contracts'; import useAllowAction from '../useAllowAction'; export const useAddCollateral = () => { const { userState, userActions } = useContext(UserContext); - const { selectedBase, selectedIlk, selectedSeries, assetMap } = userState; + const { selectedBase, selectedIlk, selectedSeries, assetMap, } = userState; const { updateAssets, updateVaults } = userActions; - const { address: account } = useAccountPlus(); + const { address: account, nativeBalance } = useAccountPlus(); const contracts = useContracts(); const { @@ -34,6 +35,7 @@ export const useAddCollateral = () => { const { wrapAsset } = useWrapUnwrapAsset(); const { addEth } = useAddRemoveEth(); + const { assert } = useAssert(); const {isActionAllowed} = useAllowAction(); const { refetch: refetchBaseBal } = useBalance({ @@ -53,9 +55,11 @@ export const useAddCollateral = () => { const vaultId = vault?.id || BLANK_VAULT; /* set the ilk based on if a vault has been selected or it's a new vault */ - const ilk: IAsset | null | undefined = vault ? assetMap?.get(vault.ilkId) : selectedIlk; + const ilk: IAsset | null | undefined = vault ? assetMap?.get(vault.ilkId)! : selectedIlk!; const base: IAsset | null | undefined = vault ? assetMap?.get(vault.baseId) : selectedBase; + const ladleAddress = contracts.get(ContractNames.LADLE)?.address; + const cauldron = contracts.get(ContractNames.CAULDRON) as Cauldron; /* generate the reproducible txCode for tx tracking and tracing */ const txCode = getTxCode(ActionCodes.ADD_COLLATERAL, vaultId); @@ -66,6 +70,11 @@ export const useAddCollateral = () => { /* check if the ilk/asset is an eth asset variety, if so pour to Ladle */ const isEthCollateral = ETH_BASED_ASSETS.includes(ilk?.proxyId!); + /* pour destination based on ilk/asset is an eth asset variety */ + const pourToAddress = () => { + if (isEthCollateral) return ladleAddress; + return account; + }; /* is convex-type collateral */ const isConvexCollateral = CONVEX_BASED_ASSETS.includes(selectedIlk?.proxyId!); @@ -99,11 +108,15 @@ export const useAddCollateral = () => { selectedIlk?.proxyId ); - /* pour destination based on ilk/asset is an eth asset variety */ - const pourToAddress = () => { - if (isEthCollateral) return ladleAddress; - return account; - }; + /* Add in an Assert call : collateral(ilk) increases by input amount */ + const assertCallData: ICallData[] = [] ; + // vault ? assert( + // cauldron.address, + // cauldron.interface.encodeFunctionData('balances', [vaultId]), + // AssertActions.Fn.ASSERT_EQ_REL, + // vault.ink.add(input), + // WAD_BN.div('10') // 10% relative tolerance + // ) : []; /** * BUILD CALL DATA ARRAY @@ -139,6 +152,9 @@ export const useAddCollateral = () => { args: [vaultId, pourToAddress(), _input, ethers.constants.Zero] as LadleActions.Args.POUR, ignoreIf: false, // never ignore }, + + /* handle any assert at end of tx */ + ...assertCallData, ]; /* TRANSACT */ diff --git a/src/hooks/actionHooks/useAddLiquidity.ts b/src/hooks/actionHooks/useAddLiquidity.ts index 11cf260be..e859b8c4a 100644 --- a/src/hooks/actionHooks/useAddLiquidity.ts +++ b/src/hooks/actionHooks/useAddLiquidity.ts @@ -1,6 +1,13 @@ import { BigNumber, ethers } from 'ethers'; import { useContext } from 'react'; -import { calcPoolRatios, calculateSlippage, fyTokenForMint, MAX_256, splitLiquidity } from '@yield-protocol/ui-math'; +import { + calcPoolRatios, + calculateSlippage, + fyTokenForMint, + MAX_256, + splitLiquidity, + WAD_BN, +} from '@yield-protocol/ui-math'; import { formatUnits } from 'ethers/lib/utils'; import { UserContext } from '../../contexts/UserContext'; @@ -25,16 +32,17 @@ import { SettingsContext } from '../../contexts/SettingsContext'; import { useAddRemoveEth } from './useAddRemoveEth'; import { ETH_BASED_ASSETS, USDT, WETH } from '../../config/assets'; import useTimeTillMaturity from '../useTimeTillMaturity'; -import { Address, useAccount, useBalance } from 'wagmi'; +import { Address, useBalance } from 'wagmi'; import useContracts from '../useContracts'; import useChainId from '../useChainId'; import useAccountPlus from '../useAccountPlus'; +import { AssertActions, useAssert } from './useAssert'; import { ContractNames } from '../../config/contracts'; import useAllowAction from '../useAllowAction'; export const useAddLiquidity = () => { const { - settingsState: { slippageTolerance }, + settingsState: { slippageTolerance, diagnostics }, } = useContext(SettingsContext); const { userState, userActions } = useContext(UserContext); @@ -53,6 +61,8 @@ export const useAddLiquidity = () => { const {isActionAllowed} = useAllowAction(); const { addEth } = useAddRemoveEth(); + const { assert, encodeBalanceCall } = useAssert(); + const { getTimeTillMaturity } = useTimeTillMaturity(); const { refetch: refetchBaseBal } = useBalance({ address: account, @@ -134,7 +144,8 @@ export const useAddLiquidity = () => { const baseToPool = _series.getBase(sharesToPool); /* DIAGNOSITCS */ - method === AddLiquidityType.BUY && + diagnostics && + method === AddLiquidityType.BUY && console.log( '\n', 'method: ', @@ -162,7 +173,8 @@ export const useAddLiquidity = () => { formatUnits(maxRatio, strategy.decimals) ); - method === AddLiquidityType.BORROW && + diagnostics && + method === AddLiquidityType.BORROW && console.log( '\n', 'method: ', @@ -221,7 +233,14 @@ export const useAddLiquidity = () => { return []; // sends back an empty array [] if not eth base }; - console.log('isEthBase', isEthBase); + /* Add in an Assert call : Strategy Tokens received within 10% of baseIn. */ + const assertCallData: ICallData[] = assert( + strategy.address, + encodeBalanceCall(strategy.address, undefined), + AssertActions.Fn.ASSERT_EQ_REL, + strategy.accountBalance!.add(_input), + WAD_BN.div('10') // 10% relative tolerance + ); /** * BUILD CALL DATA ARRAY @@ -230,7 +249,6 @@ export const useAddLiquidity = () => { ...permitCallData, /* addETh calldata */ - ...addEthCallData(), /** @@ -310,6 +328,8 @@ export const useAddLiquidity = () => { targetContract: strategy.strategyContract, ignoreIf: !strategy, }, + + ...assertCallData, ]; await transact(calls, txCode); diff --git a/src/hooks/actionHooks/useAssert.ts b/src/hooks/actionHooks/useAssert.ts new file mode 100644 index 000000000..c38ed52d0 --- /dev/null +++ b/src/hooks/actionHooks/useAssert.ts @@ -0,0 +1,96 @@ +import { BigNumber, BigNumberish, BytesLike, Contract } from 'ethers'; +import { erc20ABI, useAccount, useNetwork } from 'wagmi'; +import { ContractNames } from '../../config/contracts'; +import { Assert, ERC1155__factory } from '../../contracts'; +import { ICallData, LadleActions } from '../../types'; +import { ZERO_BN } from '../../utils/constants'; +import useContracts from '../useContracts'; + +export namespace AssertActions { + export enum Fn { + ASSERT_GT = 'assertGt(address,bytes,uint)', + ASSERT_LT = 'assertLt(address,bytes,uint,uint256)', + ASSERT_EQ_REL = 'assertEqRel(address,bytes,uint,uint256)', + ASSERT_EQ_ABS = 'assertEqAbs(address,bytes,uint,uint256)', + ASSERT_GE = 'assertGe(address,bytes,uint)', + ASSERT_LE = 'assertLe(address,bytes,uint)', + } + export namespace Args { + export type ASSERT_GT = [actualTarget: string, bytes: BytesLike, expected: BigNumberish]; + export type ASSERT_LT = [actualTarget: string, bytes: BytesLike, expected: BigNumberish]; + export type ASSERT_EQ_REL = [ + actualTarget: string, + bytes: BytesLike, + expected: BigNumberish, + relative: BigNumberish + ]; + export type ASSERT_EQ_ABS = [ + actualTarget: string, + bytes: BytesLike, + expected: BigNumberish, + absolute: BigNumberish + ]; + export type ASSERT_GE = [actualTarget: string, bytes: BytesLike, expected: BigNumberish]; + export type ASSERT_LE = [actualTarget: string, bytes: BytesLike, expected: BigNumberish]; + } +} + +export const useAssert = () => { + const contracts = useContracts(); + const { address: account } = useAccount(); + const { chain } = useNetwork(); + + const encodeBalanceCall = (targetAddress: string | undefined, tokenIdentifier: string | number | undefined = undefined) => { + + if (targetAddress) { + const abi = tokenIdentifier ? ERC1155__factory.abi : erc20ABI; + const args = tokenIdentifier ? [account, tokenIdentifier] : [account]; + const assetContract_ = new Contract(targetAddress, abi); + return assetContract_.interface.encodeFunctionData('balanceOf', args); + } + + /* if no address provided, assume the balance is the native balance and get the users ETH balance via a multical3 contract */ + const contract_ = new Contract(chain?.contracts?.multicall3?.address!, multiCallFragment); + return contract_.interface.encodeFunctionData('getEthBalance', [account]); // this calls the helper contract -> because we are looking for an ETH/Native balance; + }; + + const assert = ( + address: string | undefined, + encodedCallBytes: string, + assertFn: AssertActions.Fn, + expectedVal: BigNumber, + relOrAbsVal: BigNumber = ZERO_BN, + ignoreIf: boolean = false + ): ICallData[] => { + if (!contracts) return []; + + /* if address == undefined, then use the appropriate multicall contract for the connected chain as the defualt */ + const defaultAddress = chain?.contracts?.multicall3?.address! + const assertContract = contracts.get(ContractNames.ASSERT) as Assert; + + return [ + { + operation: LadleActions.Fn.ROUTE, + args: relOrAbsVal.gt(ZERO_BN) + ? [address || defaultAddress, encodedCallBytes, expectedVal, relOrAbsVal] + : [address || defaultAddress, encodedCallBytes, expectedVal], + fnName: assertFn, + targetContract: assertContract, + ignoreIf, + }, + ]; + }; + + /* if there is a destination 'to' then use the ladle module (wrapEtherModule) */ + return { assert, encodeBalanceCall }; +}; + +const multiCallFragment = [ + { + inputs: [{ internalType: 'address', name: 'addr', type: 'address' }], + name: 'getEthBalance', + outputs: [{ internalType: 'uint256', name: 'balance', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, +]; diff --git a/src/hooks/actionHooks/useBorrow.ts b/src/hooks/actionHooks/useBorrow.ts index a9104bce1..7e056de23 100644 --- a/src/hooks/actionHooks/useBorrow.ts +++ b/src/hooks/actionHooks/useBorrow.ts @@ -1,6 +1,6 @@ import { ethers } from 'ethers'; import { useContext } from 'react'; -import { buyBase, calculateSlippage } from '@yield-protocol/ui-math'; +import { buyBase, calculateSlippage, WAD_BN } from '@yield-protocol/ui-math'; import { SettingsContext } from '../../contexts/SettingsContext'; import { UserContext } from '../../contexts/UserContext'; @@ -13,7 +13,9 @@ import { CONVEX_BASED_ASSETS, ETH_BASED_ASSETS, WETH } from '../../config/assets import { useChain } from '../useChain'; import { useWrapUnwrapAsset } from './useWrapUnwrapAsset'; import { useAddRemoveEth } from './useAddRemoveEth'; -import { ModuleActions } from '../../types/operations'; +import { AssertActions, useAssert } from './useAssert'; + +import { ModuleActions, RoutedActions } from '../../types/operations'; import { ConvexLadleModule } from '../../contracts'; import useTimeTillMaturity from '../useTimeTillMaturity'; import { Address, useBalance } from 'wagmi'; @@ -30,7 +32,7 @@ export const useBorrow = () => { const { userState, userActions } = useContext(UserContext); const { selectedBase, selectedIlk, selectedSeries, seriesMap, assetMap } = userState; const { updateVaults, updateAssets, updateSeries } = userActions; - const { address: account } = useAccountPlus(); + const { address: account, nativeBalance } = useAccountPlus(); const contracts = useContracts(); const { refetch: refetchIlkBal } = useBalance({ @@ -44,17 +46,18 @@ export const useBorrow = () => { const { addEth, removeEth } = useAddRemoveEth(); + const { assert, encodeBalanceCall } = useAssert(); + const { wrapAsset } = useWrapUnwrapAsset(); const { sign, transact } = useChain(); const { getTimeTillMaturity } = useTimeTillMaturity(); - const {isActionAllowed} = useAllowAction(); + const { isActionAllowed } = useAllowAction(); const borrow = async (vault: IVault | undefined, input: string | undefined, collInput: string | undefined) => { if (!contracts) return; if (!isActionAllowed(ActionCodes.BORROW)) return; // return if action is not allowed - /* generate the reproducible txCode for tx tracking and tracing */ const txCode = getTxCode(ActionCodes.BORROW, selectedSeries?.id!); /* use the vault id provided OR 0 if new/ not provided */ @@ -126,6 +129,26 @@ export const useBorrow = () => { txCode ); + /* Add in an Assert call */ + const assertCallData: ICallData[] = + isEthBase && nativeBalance + ? assert( + // if base is WETH, check the native balance increase + undefined, + encodeBalanceCall(undefined), + AssertActions.Fn.ASSERT_EQ_REL, // relative here + nativeBalance.value.add(_input), + WAD_BN + ) + : assert( + // else check the token balance + base.address, + encodeBalanceCall(base.address, base.tokenIdentifier), + AssertActions.Fn.ASSERT_EQ_REL, // relative here + base.balance.add(_input), + WAD_BN + ); + /* if ETH is being borrowed, send the borrowed tokens (WETH) to ladle for unwrapping */ const serveToAddress = () => { if (isEthBase) return ladleAddress; @@ -169,7 +192,10 @@ export const useBorrow = () => { args: [vaultId, serveToAddress(), _collInput, _input, _expectedFyTokenWithSlippage] as LadleActions.Args.SERVE, ignoreIf: false, }, + ...removeEthCallData, + + ...assertCallData, ]; /* finally, handle the transaction */ diff --git a/src/hooks/actionHooks/useClosePosition.ts b/src/hooks/actionHooks/useClosePosition.ts index 6afd29ef7..6836d403c 100644 --- a/src/hooks/actionHooks/useClosePosition.ts +++ b/src/hooks/actionHooks/useClosePosition.ts @@ -1,8 +1,8 @@ import { ethers } from 'ethers'; import { useContext } from 'react'; -import { buyBase, calculateSlippage } from '@yield-protocol/ui-math'; +import { buyBase, calculateSlippage, WAD_BN } from '@yield-protocol/ui-math'; -import { ETH_BASED_ASSETS } from '../../config/assets'; +import { ETH_BASED_ASSETS, WETH } from '../../config/assets'; import { HistoryContext } from '../../contexts/HistoryContext'; import { SettingsContext } from '../../contexts/SettingsContext'; import { UserContext } from '../../contexts/UserContext'; @@ -16,6 +16,7 @@ import useTimeTillMaturity from '../useTimeTillMaturity'; import { Address, useBalance } from 'wagmi'; import useContracts from '../useContracts'; import useAccountPlus from '../useAccountPlus'; +import { AssertActions, useAssert } from './useAssert'; import { ContractNames } from '../../config/contracts'; import useAllowAction from '../useAllowAction'; @@ -27,7 +28,7 @@ export const useClosePosition = () => { const { userState, userActions } = useContext(UserContext); const { assetMap, selectedSeries, selectedBase } = userState; - const { address: account } = useAccountPlus(); + const { address: account, nativeBalance } = useAccountPlus(); const { refetch: refetchFyTokenBal } = useBalance({ address: account, token: selectedSeries?.address as Address, @@ -47,6 +48,8 @@ export const useClosePosition = () => { const { getTimeTillMaturity } = useTimeTillMaturity(); const { isActionAllowed } = useAllowAction(); + const { assert, encodeBalanceCall } = useAssert(); + const closePosition = async ( input: string | undefined, series: ISeries, @@ -85,6 +88,19 @@ export const useClosePosition = () => { /* if ethBase */ const isEthBase = ETH_BASED_ASSETS.includes(series.baseId); + /* Set the transferTo address based on series maturity */ + const transferToAddress = () => { + if (seriesIsMature) return address; + return poolAddress; + }; + + /* receiver based on whether base is ETH (- or wrapped Base) */ + const receiverAddress = () => { + if (isEthBase) return ladleAddress; + // if ( unwrapping) return unwrapHandlerAddress; + return account; + }; + /* if approveMAx, check if signature is required */ const alreadyApproved = (await series.fyTokenContract.allowance(account!, ladleAddress!)).gte(_fyTokenValueOfInput); @@ -102,18 +118,24 @@ export const useClosePosition = () => { const removeEthCallData = isEthBase ? removeEth(ONE_BN) : []; - /* Set the transferTo address based on series maturity */ - const transferToAddress = () => { - if (seriesIsMature) return address; - return poolAddress; - }; - - /* receiver based on whether base is ETH (- or wrapped Base) */ - const receiverAddress = () => { - if (isEthBase) return ladleAddress; - // if ( unwrapping) return unwrapHandlerAddress; - return account; - }; + /* Add in an Assert call : base Balance increases up to 10% of fyToken balance */ + const assertCallData: ICallData[] = + isEthBase && nativeBalance + ? assert( + // if base is WETH, check the native balance increase + undefined, + encodeBalanceCall(undefined), + AssertActions.Fn.ASSERT_EQ_REL, // relative here + nativeBalance.value.add(_input), + WAD_BN.div('10') + ) + : assert( + base.address, + encodeBalanceCall(base.address, base.tokenIdentifier), + AssertActions.Fn.ASSERT_EQ_REL, + base.balance.add(_input), + WAD_BN.div('10') // 10% relative tolerance + ); const calls: ICallData[] = [ ...permitCallData, @@ -144,6 +166,8 @@ export const useClosePosition = () => { }, ...removeEthCallData, // (exit_ether sweeps all the eth out the ladle, so exact amount is not importnat -> just greater than zero) + + ...assertCallData, ]; await transact(calls, txCode); refetchBaseBal(); diff --git a/src/hooks/actionHooks/useLend.ts b/src/hooks/actionHooks/useLend.ts index 18aaf4c24..8bd1226e3 100644 --- a/src/hooks/actionHooks/useLend.ts +++ b/src/hooks/actionHooks/useLend.ts @@ -1,6 +1,6 @@ import { ethers } from 'ethers'; import { useContext } from 'react'; -import { calculateSlippage, MAX_256, sellBase } from '@yield-protocol/ui-math'; +import { calculateSlippage, MAX_256, sellBase, WAD_BN } from '@yield-protocol/ui-math'; import { ETH_BASED_ASSETS, USDT } from '../../config/assets'; import { HistoryContext } from '../../contexts/HistoryContext'; @@ -15,6 +15,7 @@ import { Address, useBalance } from 'wagmi'; import useContracts from '../useContracts'; import useChainId from '../useChainId'; import useAccountPlus from '../useAccountPlus'; +import { AssertActions, useAssert } from './useAssert'; import { ContractNames } from '../../config/contracts'; import useAllowAction from '../useAllowAction'; @@ -46,6 +47,8 @@ export const useLend = () => { const { getTimeTillMaturity } = useTimeTillMaturity(); const contracts = useContracts(); + const { assert, encodeBalanceCall } = useAssert(); + const lend = async (input: string | undefined, series: ISeries) => { if (!contracts) return; if (!isActionAllowed(ActionCodes.LEND)) return; // return if action is not allowed @@ -97,6 +100,15 @@ export const useLend = () => { return []; }; + /* Add in an Assert call : fyToken balance is 10% higher than what they inputed (as fyTokens) */ + const assertCallData: ICallData[] = assert( + series.fyTokenContract.address, + encodeBalanceCall(series.fyTokenContract.address, undefined), + AssertActions.Fn.ASSERT_EQ_REL, + series.fyTokenBalance!.add(_inputAsFyToken), + WAD_BN.div('10') // 10% relative tolerance + ); + const calls: ICallData[] = [ ...permitCallData, ...addEthCallData(), @@ -112,6 +124,7 @@ export const useLend = () => { targetContract: series.poolContract, ignoreIf: false, }, + ...assertCallData, ]; await transact(calls, txCode); diff --git a/src/hooks/actionHooks/useRemoveCollateral.ts b/src/hooks/actionHooks/useRemoveCollateral.ts index 5b61bebab..e48c162ae 100644 --- a/src/hooks/actionHooks/useRemoveCollateral.ts +++ b/src/hooks/actionHooks/useRemoveCollateral.ts @@ -7,19 +7,20 @@ import { CONVEX_BASED_ASSETS, ETH_BASED_ASSETS, WETH } from '../../config/assets import { useChain } from '../useChain'; import { useWrapUnwrapAsset } from './useWrapUnwrapAsset'; import { useAddRemoveEth } from './useAddRemoveEth'; -import { ONE_BN, ZERO_BN } from '../../utils/constants'; -import { ConvexJoin__factory } from '../../contracts'; +import { ONE_BN, WAD_BN, ZERO_BN } from '../../utils/constants'; +import { Cauldron, ConvexJoin__factory } from '../../contracts'; import { HistoryContext } from '../../contexts/HistoryContext'; import { Address, useBalance, useNetwork, useProvider } from 'wagmi'; import useContracts from '../useContracts'; import useAccountPlus from '../useAccountPlus'; +import { AssertActions, useAssert } from './useAssert'; import { ContractNames } from '../../config/contracts'; import useAllowAction from '../useAllowAction'; export const useRemoveCollateral = () => { const { userState, userActions } = useContext(UserContext); const { selectedIlk, assetMap } = userState; - const { address: account } = useAccountPlus(); + const { address: account, nativeBalance } = useAccountPlus(); const { chain } = useNetwork(); const provider = useProvider(); const contracts = useContracts(); @@ -36,19 +37,21 @@ export const useRemoveCollateral = () => { const { transact } = useChain(); const { removeEth } = useAddRemoveEth(); const { unwrapAsset } = useWrapUnwrapAsset(); + const { assert, encodeBalanceCall } = useAssert(); const { isActionAllowed } = useAllowAction(); const removeCollateral = async (vault: IVault, input: string, unwrapOnRemove: boolean = true) => { if (!contracts) return; if (!isActionAllowed(ActionCodes.REMOVE_COLLATERAL)) return; // return if action is not allowed - /* generate the txCode for tx tracking and tracing */ const txCode = getTxCode(ActionCodes.REMOVE_COLLATERAL, vault.id); /* get associated series and ilk */ const ilk = assetMap?.get(vault.ilkId)!; const ladleAddress = contracts.get(ContractNames.LADLE)?.address; + const cauldron = contracts.get(ContractNames.CAULDRON) as Cauldron; + /* get unwrap handler if required */ const unwrapHandlerAddress = ilk.unwrapHandlerAddresses?.get(chain?.id!); /* check if the ilk/asset is an eth asset variety OR if it is wrapped token, if so pour to Ladle */ @@ -74,6 +77,16 @@ export const useRemoveCollateral = () => { return account; }; + /* Add in an Assert call : collateral(ilk) decreases by input amount */ + const assertCallData: ICallData[] = []; + // vault ? assert( + // cauldron.address, + // cauldron.interface.encodeFunctionData('balances', [vault.id]), + // AssertActions.Fn.ASSERT_EQ_REL, + // vault.ink.sub(_input), + // WAD_BN.div('10') + // ): []; + const calls: ICallData[] = [ /* convex-type collateral; ensure checkpoint before giving collateral back to account */ { @@ -95,6 +108,8 @@ export const useRemoveCollateral = () => { }, ...removeEthCallData, ...unwrapCallData, + + ...assertCallData, ]; await transact(calls, txCode); diff --git a/src/hooks/actionHooks/useRemoveLiquidity.ts b/src/hooks/actionHooks/useRemoveLiquidity.ts index 146912797..f27d47490 100644 --- a/src/hooks/actionHooks/useRemoveLiquidity.ts +++ b/src/hooks/actionHooks/useRemoveLiquidity.ts @@ -7,6 +7,7 @@ import { calculateSlippage, newPoolState, sellFYToken, + WAD_BN, } from '@yield-protocol/ui-math'; import { formatUnits } from 'ethers/lib/utils'; @@ -26,6 +27,7 @@ import useContracts from '../useContracts'; import { Strategy__factory } from '../../contracts'; import { StrategyType } from '../../config/strategies'; import useAccountPlus from '../useAccountPlus'; +import { AssertActions, useAssert } from './useAssert'; import { ContractNames } from '../../config/contracts'; import useAllowAction from '../useAllowAction'; @@ -55,7 +57,7 @@ is Mature? N +--------+ export const useRemoveLiquidity = () => { const provider = useProvider(); - const { address: account } = useAccountPlus(); + const { address: account, nativeBalance } = useAccountPlus(); const { txActions } = useContext(TxContext); const { resetProcess } = txActions; @@ -69,6 +71,8 @@ export const useRemoveLiquidity = () => { const { getTimeTillMaturity } = useTimeTillMaturity(); const { isActionAllowed } = useAllowAction(); + const { assert, encodeBalanceCall } = useAssert(); + const contracts = useContracts(); const { refetch: refetchBaseBal } = useBalance({ address: account, @@ -294,6 +298,35 @@ export const useRemoveLiquidity = () => { txCode ); + /* Add in an Assert call : Base received + fyToken received within 10% of strategy tokens held. */ + const assertCallData_base: ICallData[] = + isEthBase && nativeBalance + ? assert( + undefined, + encodeBalanceCall(undefined), + AssertActions.Fn.ASSERT_EQ_REL, + nativeBalance.value.add(series.getBase(_sharesReceived)), + WAD_BN.div('10') // 10% relative tolerance + ): + assert( + _base.address, + encodeBalanceCall(_base.address, _base.tokenIdentifier), + AssertActions.Fn.ASSERT_EQ_REL, + _base.balance!.add(series.getBase(_sharesReceived)), + WAD_BN.div('10') // 10% relative tolerance + ) + + /* Add in an Assert call : Base received + fyToken received within 10% of strategy tokens held. */ + const assertCallData_fyToken: ICallData[] = _fyTokenReceived.gt(ZERO_BN) + ? assert( + series.address, + encodeBalanceCall(series.address, undefined), + AssertActions.Fn.ASSERT_EQ_REL, + series.fyTokenBalance!.add(_fyTokenReceived), + WAD_BN.div('10') // 10% relative tolerance + ) + : []; + // const unwrapping: ICallData[] = await unwrapAsset(_base, account) const calls: ICallData[] = [ ...permitCallData, @@ -452,6 +485,10 @@ export const useRemoveLiquidity = () => { }, ...removeEthCallData, + + ...assertCallData_base, + // ...assertCallData_fyToken, temporarily remove fyToken check + ]; await transact(calls, txCode); diff --git a/src/hooks/actionHooks/useRepayDebt.ts b/src/hooks/actionHooks/useRepayDebt.ts index eaca59a12..f4df1ff78 100644 --- a/src/hooks/actionHooks/useRepayDebt.ts +++ b/src/hooks/actionHooks/useRepayDebt.ts @@ -1,6 +1,6 @@ import { ethers } from 'ethers'; import { useContext } from 'react'; -import { calculateSlippage, maxBaseIn, MAX_256, sellBase } from '@yield-protocol/ui-math'; +import { calculateSlippage, maxBaseIn, MAX_256, sellBase, WAD_BN } from '@yield-protocol/ui-math'; import { UserContext } from '../../contexts/UserContext'; import { ICallData, IVault, ISeries, ActionCodes, LadleActions, IAsset, RoutedActions } from '../../types'; @@ -11,13 +11,14 @@ import { SettingsContext } from '../../contexts/SettingsContext'; import { useAddRemoveEth } from './useAddRemoveEth'; import { ONE_BN, ZERO_BN } from '../../utils/constants'; import { useWrapUnwrapAsset } from './useWrapUnwrapAsset'; -import { ConvexJoin__factory } from '../../contracts'; +import { Cauldron, ConvexJoin__factory } from '../../contracts'; import useTimeTillMaturity from '../useTimeTillMaturity'; import { Address, useBalance, useNetwork, useProvider } from 'wagmi'; import useContracts from '../useContracts'; import useChainId from '../useChainId'; import useAccountPlus from '../useAccountPlus'; import { ContractNames } from '../../config/contracts'; +import { AssertActions, useAssert } from './useAssert'; import useAllowAction from '../useAllowAction'; export const useRepayDebt = () => { @@ -28,7 +29,7 @@ export const useRepayDebt = () => { const { userState, userActions } = useContext(UserContext); const { seriesMap, assetMap, selectedIlk, selectedBase } = userState; const { updateVaults, updateAssets, updateSeries } = userActions; - const { address: account } = useAccountPlus(); + const { address: account, nativeBalance } = useAccountPlus(); const { chain } = useNetwork(); const provider = useProvider(); const contracts = useContracts(); @@ -47,6 +48,7 @@ export const useRepayDebt = () => { const { getTimeTillMaturity, isMature } = useTimeTillMaturity(); const chainId = useChainId(); + const { assert, encodeBalanceCall } = useAssert(); const {isActionAllowed} = useAllowAction(); /** @@ -58,7 +60,8 @@ export const useRepayDebt = () => { const repay = async (vault: IVault, input: string | undefined, reclaimCollateral: boolean) => { if (!contracts) return; - + + const cauldron = contracts.get(ContractNames.CAULDRON) as Cauldron; const txCode = getTxCode(ActionCodes.REPAY, vault.id); const ladleAddress = contracts.get(ContractNames.LADLE)?.address; @@ -164,9 +167,31 @@ export const useRepayDebt = () => { return account; }; + /** Add in an Assert call : + * - Users ilk balance increases by ilk amount> if repaying all debt AND removing all collateral + * - vault debt reduced by input amount > if repaying part debt + */ + const assertCallData: ICallData[] = + _collateralToRemove !== ZERO_BN && nativeBalance ? + isEthCollateral + ? assert( + // if base is WETH, check the native balance increase + undefined, + encodeBalanceCall(undefined), + AssertActions.Fn.ASSERT_EQ_REL, // relative here + nativeBalance.value.add(vault.ink), + WAD_BN + ) : + assert( + ilk.address, + encodeBalanceCall(ilk.address, ilk.tokenIdentifier), + AssertActions.Fn.ASSERT_GE, + ilk.balance.add(vault.ink) + ) + : []; // currently not handling asserts on partial debt repayments + const calls: ICallData[] = [ ...permitCallData, - /* Reqd. when we have a wrappedBase */ // ...wrapAssetCallData @@ -221,6 +246,8 @@ export const useRepayDebt = () => { ...removeEthCallData, ...unwrapAssetCallData, + + ...assertCallData, ]; await transact(calls, txCode); diff --git a/src/hooks/actionHooks/useRollDebt.ts b/src/hooks/actionHooks/useRollDebt.ts index d45ac07a8..f812491ab 100644 --- a/src/hooks/actionHooks/useRollDebt.ts +++ b/src/hooks/actionHooks/useRollDebt.ts @@ -1,11 +1,16 @@ +import { WAD_BN } from '@yield-protocol/ui-math'; import { useContext } from 'react'; +import { ContractNames } from '../../config/contracts'; import { HistoryContext } from '../../contexts/HistoryContext'; import { UserContext } from '../../contexts/UserContext'; +import { Cauldron } from '../../contracts'; import { ICallData, IVault, ISeries, ActionCodes, LadleActions, IHistoryContext } from '../../types'; import { getTxCode } from '../../utils/appUtils'; import { MAX_128, ZERO_BN } from '../../utils/constants'; import useAllowAction from '../useAllowAction'; import { useChain } from '../useChain'; +import useContracts from '../useContracts'; +import { AssertActions, useAssert } from './useAssert'; /* Generic hook for chain transactions */ export const useRollDebt = () => { @@ -20,7 +25,13 @@ export const useRollDebt = () => { const { transact } = useChain(); const { isActionAllowed } = useAllowAction(); + const { assert, encodeBalanceCall } = useAssert(); + const contracts = useContracts(); + const rollDebt = async (vault: IVault, toSeries: ISeries) => { + if (!contracts) return; + + const cauldron = contracts.get(ContractNames.CAULDRON) as Cauldron; if (!isActionAllowed(ActionCodes.ROLL_DEBT)) return; // return if action is not allowed @@ -29,6 +40,15 @@ export const useRollDebt = () => { const hasDebt = vault.accruedArt.gt(ZERO_BN); const fromSeries = seriesMap?.get(vault.seriesId); + /* Add in an Assert call : debt in new series within 10% of old debt */ + const assertCallData: ICallData[] = assert( + cauldron.address, + cauldron.interface.encodeFunctionData('balances', [vault.id]), + AssertActions.Fn.ASSERT_EQ_REL, + vault.accruedArt, + WAD_BN.div('10') // 10% relative tolerance + ); + const calls: ICallData[] = [ { // ladle.rollAction(vaultId: string, newSeriesId: string, max: BigNumberish) @@ -42,6 +62,7 @@ export const useRollDebt = () => { args: [vault.id, toSeries.id, vault.ilkId] as LadleActions.Args.TWEAK, ignoreIf: hasDebt, }, + ...assertCallData, ]; await transact(calls, txCode); updateVaults([vault]); diff --git a/src/hooks/actionHooks/useRollPosition.ts b/src/hooks/actionHooks/useRollPosition.ts index fcfc6cf81..073f38af3 100644 --- a/src/hooks/actionHooks/useRollPosition.ts +++ b/src/hooks/actionHooks/useRollPosition.ts @@ -1,6 +1,6 @@ import { ethers } from 'ethers'; import { useContext } from 'react'; -import { buyBase, calculateSlippage, sellBase } from '@yield-protocol/ui-math'; +import { buyBase, calculateSlippage, sellBase, WAD_BN } from '@yield-protocol/ui-math'; import { formatUnits } from 'ethers/lib/utils'; import { HistoryContext } from '../../contexts/HistoryContext'; @@ -13,6 +13,7 @@ import useTimeTillMaturity from '../useTimeTillMaturity'; import { useRouter } from 'next/router'; import useContracts from '../useContracts'; import useAccountPlus from '../useAccountPlus'; +import { AssertActions, useAssert } from './useAssert'; import { ContractNames } from '../../config/contracts'; import useAllowAction from '../useAllowAction'; @@ -38,6 +39,8 @@ export const useRollPosition = () => { const { getTimeTillMaturity } = useTimeTillMaturity(); const { isActionAllowed } = useAllowAction(); + const { assert, encodeBalanceCall } = useAssert(); + /** * Transfer fyToken to the "from" pool to sell for base, then send base to "to" pool and sell base for fyToken * @param input in base (i.e.: 100 USDC) @@ -120,6 +123,15 @@ export const useRollPosition = () => { txCode ); + /* Add in an Assert call : new fyToken balance within 10% (up or down) of old position. */ + const assertCallData: ICallData[] = assert( + toSeries.address, + encodeBalanceCall(toSeries.address, undefined), + AssertActions.Fn.ASSERT_EQ_REL, + fromSeries.fyTokenBalance!, + WAD_BN.div('10') // 10% relative tolerance + ); + /* Reciever of transfer (based on maturity) the series maturity */ const transferToAddress = () => { if (fromSeries.seriesIsMature) return fromSeries.address; @@ -166,6 +178,8 @@ export const useRollPosition = () => { targetContract: toSeries.poolContract, ignoreIf: !fromSeries.seriesIsMature, }, + + ...assertCallData, ]; const res = (await transact(calls, txCode)) as Promise | void; diff --git a/src/hooks/useAccountPlus.ts b/src/hooks/useAccountPlus.ts index 5296c8a0c..f4cf63518 100644 --- a/src/hooks/useAccountPlus.ts +++ b/src/hooks/useAccountPlus.ts @@ -1,5 +1,5 @@ import { useContext, useMemo } from 'react'; -import { useAccount } from 'wagmi'; +import { useAccount, useBalance } from 'wagmi'; import { SettingsContext } from '../contexts/SettingsContext'; /** @@ -7,13 +7,15 @@ import { SettingsContext } from '../contexts/SettingsContext'; * @returns mockUserAddress input when using mocked data, else simply the wagmi useAccount hook address */ const useAccountPlus = () => { + const { settingsState: { useMockedUser, mockUserAddress }, } = useContext(SettingsContext); const { address } = useAccount(); + const {data:nativeBalance} = useBalance({address}); return useMemo( - () => (useMockedUser ? { address: mockUserAddress } : { address }), + () => (useMockedUser ? { address: mockUserAddress, nativeBalance } : { address, nativeBalance }), [address, mockUserAddress, useMockedUser] ); }; diff --git a/src/hooks/useChain.ts b/src/hooks/useChain.ts index 6f9624db7..6fe13e9d1 100644 --- a/src/hooks/useChain.ts +++ b/src/hooks/useChain.ts @@ -97,7 +97,7 @@ export const useChain = () => { gasEst = await _contract.estimateGas.batch(encodedCalls, { value: batchValue } as PayableOverrides); console.log('Auto gas estimate:', gasEst.mul(135).div(100).toString()); } catch (e: any) { - gasEst = BigNumber.from(500000); + gasEst = BigNumber.from(5000000); /* handle if the tx if going to fail and transactions aren't forced */ if (!forceTransactions) return handleTxWillFail(e.error, txCode, e.transaction); } diff --git a/src/hooks/viewHelperHooks/useBorrowHelpers.ts b/src/hooks/viewHelperHooks/useBorrowHelpers.ts index 36a7d8a47..4fc34773d 100644 --- a/src/hooks/viewHelperHooks/useBorrowHelpers.ts +++ b/src/hooks/viewHelperHooks/useBorrowHelpers.ts @@ -163,12 +163,12 @@ export const useBorrowHelpers = ( futureSeries.mu ); - const _minCollat = calculateMinCollateral( - assetPairInfo?.pairPrice!, + const _minCollat = assetPairInfo ? calculateMinCollateral( + assetPairInfo.pairPrice, newDebt, - assetPairInfo?.minRatio.toString()!, + assetPairInfo.minRatio.toString()!, undefined - ); + ): ZERO_BN diagnostics && console.log('min Collat of roll to series', _minCollat.toString()); /* SET MAX ROLL */ diff --git a/src/types/operations.ts b/src/types/operations.ts index fbaa89137..64bf70a65 100644 --- a/src/types/operations.ts +++ b/src/types/operations.ts @@ -95,6 +95,8 @@ export namespace RoutedActions { UNWRAP = 'unwrap', CHECKPOINT = 'checkpoint', // convex + + // ASSERT = 'assert', } export namespace Args { @@ -119,6 +121,8 @@ export namespace RoutedActions { export type UNWRAP = [receiver: string]; export type CHECKPOINT = [vaultOwner: string]; + + // export type ASSERT = []; } }