\n {title &&
{title}
}\n
\n {showIcon &&
{icon}
}\n
\n
\n {dismissable && (\n
\n \n
\n )}\n
\n ) : null\n}\n","import { BigNumber, BigNumberish } from '@ethersproject/bignumber'\nimport { ChainId, WNATIVE } from '@sushiswap/core-sdk'\nimport { getProviderOrSigner } from '../functions/contract'\n\nimport { AddressZero } from '@ethersproject/constants'\nimport { Contract } from '@ethersproject/contracts'\nimport KASHIPAIR_ABI from '../constants/abis/kashipair.json'\nimport { KashiPermit } from '../hooks/useKashiApproveCallback'\nimport { Web3Provider } from '@ethersproject/providers'\nimport { ZERO } from '../functions/math'\nimport { defaultAbiCoder } from '@ethersproject/abi'\nimport { toElastic } from '../functions/rebase'\nimport { toShare } from '../functions/bentobox'\n\nenum Action {\n ADD_ASSET = 1,\n REPAY = 2,\n REMOVE_ASSET = 3,\n REMOVE_COLLATERAL = 4,\n BORROW = 5,\n GET_REPAY_SHARE = 6,\n GET_REPAY_PART = 7,\n ACCRUE = 8,\n\n // Functions that don't need accrue to be called\n ADD_COLLATERAL = 10,\n UPDATE_EXCHANGE_RATE = 11,\n\n // Function on BentoBox\n BENTO_DEPOSIT = 20,\n BENTO_WITHDRAW = 21,\n BENTO_TRANSFER = 22,\n BENTO_TRANSFER_MULTIPLE = 23,\n BENTO_SETAPPROVAL = 24,\n\n // Any external call (except to BentoBox)\n CALL = 30,\n}\n\nexport default class KashiCooker {\n private pair: any\n private account: string\n private library: Web3Provider | undefined\n private chainId: ChainId\n\n private actions: Action[]\n private values: BigNumber[]\n private datas: string[]\n\n constructor(\n pair: any,\n account: string | null | undefined,\n library: Web3Provider | undefined,\n chainId: ChainId | undefined\n ) {\n this.pair = pair\n this.account = account || AddressZero\n this.library = library\n this.chainId = chainId || 1\n\n this.actions = []\n this.values = []\n this.datas = []\n }\n\n add(action: Action, data: string, value: BigNumberish = 0): void {\n this.actions.push(action)\n this.datas.push(data)\n this.values.push(BigNumber.from(value))\n }\n\n approve(permit: KashiPermit): void {\n if (permit) {\n this.add(\n Action.BENTO_SETAPPROVAL,\n defaultAbiCoder.encode(\n ['address', 'address', 'bool', 'uint8', 'bytes32', 'bytes32'],\n [permit.account, permit.masterContract, true, permit.v, permit.r, permit.s]\n )\n )\n }\n }\n\n updateExchangeRate(mustUpdate = false, minRate = ZERO, maxRate = ZERO): KashiCooker {\n this.add(\n Action.UPDATE_EXCHANGE_RATE,\n defaultAbiCoder.encode(['bool', 'uint256', 'uint256'], [mustUpdate, minRate, maxRate])\n )\n return this\n }\n\n bentoDepositCollateral(amount: BigNumber): KashiCooker {\n const useNative = this.pair.collateral.address === WNATIVE[this.chainId].address\n\n this.add(\n Action.BENTO_DEPOSIT,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.collateral.address, this.account, amount, 0]\n ),\n useNative ? amount : ZERO\n )\n\n return this\n }\n\n bentoWithdrawCollateral(amount: BigNumber, share: BigNumber): KashiCooker {\n const useNative = this.pair.collateral.address === WNATIVE[this.chainId].address\n\n this.add(\n Action.BENTO_WITHDRAW,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.collateral.address, this.account, amount, share]\n ),\n useNative ? amount : ZERO\n )\n\n return this\n }\n\n bentoTransferCollateral(share: BigNumber, toAddress: string): KashiCooker {\n this.add(\n Action.BENTO_TRANSFER,\n defaultAbiCoder.encode(['address', 'address', 'int256'], [this.pair.collateral.address, toAddress, share])\n )\n\n return this\n }\n\n repayShare(part: BigNumber): KashiCooker {\n this.add(Action.GET_REPAY_SHARE, defaultAbiCoder.encode(['int256'], [part]))\n\n return this\n }\n\n addCollateral(amount: BigNumber, fromBento: boolean): KashiCooker {\n let share: BigNumber\n if (fromBento) {\n share = amount.lt(0) ? amount : toShare(this.pair.collateral, amount)\n } else {\n const useNative = this.pair.collateral.address === WNATIVE[this.chainId].address\n\n this.add(\n Action.BENTO_DEPOSIT,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.collateral.address, this.account, amount, 0]\n ),\n useNative ? amount : ZERO\n )\n share = BigNumber.from(-2)\n }\n\n this.add(Action.ADD_COLLATERAL, defaultAbiCoder.encode(['int256', 'address', 'bool'], [share, this.account, false]))\n return this\n }\n\n addAsset(amount: BigNumber, fromBento: boolean): KashiCooker {\n let share: BigNumber\n if (fromBento) {\n share = toShare(this.pair.asset, amount)\n } else {\n const useNative = this.pair.asset.address === WNATIVE[this.chainId].address\n\n this.add(\n Action.BENTO_DEPOSIT,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.asset.address, this.account, amount, 0]\n ),\n useNative ? amount : ZERO\n )\n share = BigNumber.from(-2)\n }\n\n this.add(Action.ADD_ASSET, defaultAbiCoder.encode(['int256', 'address', 'bool'], [share, this.account, false]))\n return this\n }\n\n removeAsset(fraction: BigNumber, toBento: boolean): KashiCooker {\n this.add(Action.REMOVE_ASSET, defaultAbiCoder.encode(['int256', 'address'], [fraction, this.account]))\n if (!toBento) {\n const useNative = this.pair.asset.address === WNATIVE[this.chainId].address\n\n this.add(\n Action.BENTO_WITHDRAW,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.asset.address, this.account, 0, -1]\n )\n )\n }\n return this\n }\n\n removeCollateral(share: BigNumber, toBento: boolean): KashiCooker {\n this.add(Action.REMOVE_COLLATERAL, defaultAbiCoder.encode(['int256', 'address'], [share, this.account]))\n if (!toBento) {\n const useNative = this.pair.collateral.address === WNATIVE[this.chainId].address\n\n this.add(\n Action.BENTO_WITHDRAW,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.collateral.address, this.account, 0, share]\n )\n )\n }\n return this\n }\n\n removeCollateralFraction(fraction: BigNumber, toBento: boolean): KashiCooker {\n this.add(Action.REMOVE_COLLATERAL, defaultAbiCoder.encode(['int256', 'address'], [fraction, this.account]))\n if (!toBento) {\n const useNative = this.pair.collateral.address === WNATIVE[this.chainId].address\n\n this.add(\n Action.BENTO_WITHDRAW,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.collateral.address, this.account, 0, -1]\n )\n )\n }\n return this\n }\n\n borrow(amount: BigNumber, toBento: boolean, toAddress = ''): KashiCooker {\n this.add(\n Action.BORROW,\n defaultAbiCoder.encode(['int256', 'address'], [amount, toAddress && toBento ? toAddress : this.account])\n )\n if (!toBento) {\n const useNative = this.pair.asset.address === WNATIVE[this.chainId].address\n\n this.add(\n Action.BENTO_WITHDRAW,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.asset.address, toAddress || this.account, amount, 0]\n )\n )\n }\n return this\n }\n\n repay(amount: BigNumber, fromBento: boolean): KashiCooker {\n if (!fromBento) {\n const useNative = this.pair.asset.address === WNATIVE[this.chainId].address\n\n this.add(\n Action.BENTO_DEPOSIT,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.asset.address, this.account, amount, 0]\n ),\n useNative ? amount : ZERO\n )\n }\n this.add(Action.GET_REPAY_PART, defaultAbiCoder.encode(['int256'], [fromBento ? amount : -1]))\n this.add(Action.REPAY, defaultAbiCoder.encode(['int256', 'address', 'bool'], [-1, this.account, false]))\n return this\n }\n\n repayPart(part: BigNumber, fromBento: boolean): KashiCooker {\n if (!fromBento) {\n const useNative = this.pair.asset.address === WNATIVE[this.chainId].address\n\n this.add(Action.GET_REPAY_SHARE, defaultAbiCoder.encode(['int256'], [part]))\n this.add(\n Action.BENTO_DEPOSIT,\n defaultAbiCoder.encode(\n ['address', 'address', 'int256', 'int256'],\n [useNative ? AddressZero : this.pair.asset.address, this.account, 0, -1]\n ),\n // TODO: Put some warning in the UI or not allow repaying ETH directly from wallet, because this can't be pre-calculated\n useNative ? toShare(this.pair.asset, toElastic(this.pair.totalBorrow, part, true)).mul(1001).div(1000) : ZERO\n )\n }\n this.add(Action.REPAY, defaultAbiCoder.encode(['int256', 'address', 'bool'], [part, this.account, false]))\n return this\n }\n\n action(\n address: string,\n value: BigNumberish,\n data: string,\n useValue1: boolean,\n useValue2: boolean,\n returnValues: number\n ): void {\n this.add(\n Action.CALL,\n defaultAbiCoder.encode(\n ['address', 'bytes', 'bool', 'bool', 'uint8'],\n [address, data, useValue1, useValue2, returnValues]\n ),\n value\n )\n }\n\n async cook() {\n if (!this.library) {\n return {\n success: false,\n }\n }\n\n const kashiPairCloneContract = new Contract(\n this.pair.address,\n KASHIPAIR_ABI,\n getProviderOrSigner(this.library, this.account) as any\n )\n\n try {\n return {\n success: true,\n tx: await kashiPairCloneContract.cook(this.actions, this.values, this.datas, {\n value: this.values.reduce((a, b) => a.add(b), ZERO),\n }),\n }\n } catch (error) {\n console.error('KashiCooker Error: ', error)\n return {\n success: false,\n error: error,\n }\n }\n }\n}\n","import { KASHI_ADDRESS } from '@sushiswap/core-sdk'\nimport KashiCooker from '../entities/KashiCooker'\nimport { signMasterContractApproval } from '../functions'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { setKashiApprovalPending } from '../state/application/actions'\nimport { useActiveWeb3React } from '../services/web3'\nimport { useBentoBoxContract } from './useContract'\nimport { useBentoMasterContractAllowed } from '../state/bentobox/hooks'\nimport { useDispatch } from 'react-redux'\nimport { useKashiApprovalPending } from '../state/application/hooks'\nimport { useTransactionAdder } from '../state/transactions/hooks'\nimport { AddressZero, HashZero } from '@ethersproject/constants'\nimport { splitSignature } from '@ethersproject/bytes'\n\nexport enum BentoApprovalState {\n UNKNOWN,\n NOT_APPROVED,\n PENDING,\n FAILED,\n APPROVED,\n}\n\nexport interface KashiPermit {\n account: string\n masterContract: string\n v: number\n r: string\n s: string\n}\n\nexport enum BentoApproveOutcome {\n SUCCESS,\n REJECTED,\n FAILED,\n NOT_READY,\n}\n\nexport type BentoApproveResult = {\n outcome: BentoApproveOutcome\n permit?: KashiPermit\n}\n\n// returns a variable indicating the state of the approval and a function which approves if necessary or early returns\nfunction useKashiApproveCallback(): [\n BentoApprovalState,\n boolean,\n KashiPermit | undefined,\n () => void,\n (pair: any, execute: (cooker: KashiCooker) => Promise