import {TestEnv, SignerWithAddress} from './make-suite'; import { mint, approve, deposit, borrow, withdraw, repay, setUseAsCollateral, swapBorrowRateMode, rebalanceStableBorrowRate, redirectInterestStream, redirectInterestStreamOf, allowInterestRedirectionTo, } from './actions'; import {RateMode} from '../../helpers/types'; export interface Action { name: string; args?: any; expected: string; revertMessage?: string; } export interface Story { description: string; actions: Action[]; } export interface Scenario { title: string; description: string; stories: Story[]; } export const executeStory = async (story: Story, testEnv: TestEnv) => { for (const action of story.actions) { const {users} = testEnv; await executeAction(action, users, testEnv); } }; const executeAction = async (action: Action, users: SignerWithAddress[], testEnv: TestEnv) => { const {reserve, user: userIndex, borrowRateMode} = action.args; const {name, expected, revertMessage} = action; if (!name || name === '') { throw 'Action name is missing'; } if (!reserve || reserve === '') { throw 'Invalid reserve selected for deposit'; } if (!userIndex || userIndex === '') { throw `Invalid user selected to deposit into the ${reserve} reserve`; } if (!expected || expected === '') { throw `An expected resut for action ${name} is required`; } let rateMode: string = RateMode.None; if (borrowRateMode) { if (borrowRateMode === 'none') { RateMode.None; } else if (borrowRateMode === 'stable') { rateMode = RateMode.Stable; } else if (borrowRateMode === 'variable') { rateMode = RateMode.Variable; } else { //random value, to test improper selection of the parameter rateMode = '4'; } } const user = users[parseInt(userIndex)]; switch (name) { case 'mint': const {amount} = action.args; if (!amount || amount === '') { throw `Invalid amount of ${reserve} to mint`; } await mint(reserve, amount, user); break; case 'approve': await approve(reserve, user, testEnv); break; case 'deposit': { const {amount, sendValue, onBehalfOf: onBehalfOfIndex} = action.args; const onBehalfOf = onBehalfOfIndex ? users[parseInt(onBehalfOfIndex)].address : user.address; if (!amount || amount === '') { throw `Invalid amount to deposit into the ${reserve} reserve`; } await deposit( reserve, amount, user, onBehalfOf, sendValue, expected, testEnv, revertMessage ); } break; case 'withdraw': { const {amount} = action.args; if (!amount || amount === '') { throw `Invalid amount to withdraw from the ${reserve} reserve`; } await withdraw(reserve, amount, user, expected, testEnv, revertMessage); } break; case 'borrow': { const {amount, timeTravel} = action.args; if (!amount || amount === '') { throw `Invalid amount to borrow from the ${reserve} reserve`; } await borrow(reserve, amount, rateMode, user, timeTravel, expected, testEnv, revertMessage); } break; case 'repay': { const {amount, borrowRateMode, sendValue} = action.args; let {onBehalfOf: onBehalfOfIndex} = action.args; if (!amount || amount === '') { throw `Invalid amount to repay into the ${reserve} reserve`; } let userToRepayOnBehalf: SignerWithAddress; if (!onBehalfOfIndex || onBehalfOfIndex === '') { console.log( 'WARNING: No onBehalfOf specified for a repay action. Defaulting to the repayer address' ); userToRepayOnBehalf = user; } else { userToRepayOnBehalf = users[parseInt(onBehalfOfIndex)]; } await repay( reserve, amount, rateMode, user, userToRepayOnBehalf, sendValue, expected, testEnv, revertMessage ); } break; case 'setUseAsCollateral': { const {useAsCollateral} = action.args; if (!useAsCollateral || useAsCollateral === '') { throw `A valid value for useAsCollateral needs to be set when calling setUseReserveAsCollateral on reserve ${reserve}`; } await setUseAsCollateral(reserve, user, useAsCollateral, expected, testEnv, revertMessage); } break; case 'swapBorrowRateMode': await swapBorrowRateMode(reserve, user, rateMode, expected, testEnv, revertMessage); break; case 'rebalanceStableBorrowRate': { const {target: targetIndex} = action.args; if (!targetIndex || targetIndex === '') { throw `A target must be selected when trying to rebalance a stable rate`; } const target = users[parseInt(targetIndex)]; await rebalanceStableBorrowRate(reserve, user, target, expected, testEnv, revertMessage); } break; case 'redirectInterestStream': { const {to: toIndex} = action.args; if (!toIndex || toIndex === '') { throw `A target must be selected when trying to redirect the interest`; } const toUser = users[parseInt(toIndex)]; await redirectInterestStream( reserve, user, toUser.address, expected, testEnv, revertMessage ); } break; case 'redirectInterestStreamOf': { const {from: fromIndex, to: toIndex} = action.args; if (!fromIndex || fromIndex === '') { throw `A from address must be specified when trying to redirect the interest`; } if (!toIndex || toIndex === '') { throw `A target must be selected when trying to redirect the interest`; } const toUser = users[parseInt(toIndex)]; const fromUser = users[parseInt(fromIndex)]; await redirectInterestStreamOf( reserve, user, fromUser.address, toUser.address, expected, testEnv, revertMessage ); } break; case 'allowInterestRedirectionTo': { const {to: toIndex} = action.args; if (!toIndex || toIndex === '') { throw `A target must be selected when trying to redirect the interest`; } const toUser = users[parseInt(toIndex)]; await allowInterestRedirectionTo( reserve, user, toUser.address, expected, testEnv, revertMessage ); } break; default: throw `Invalid action requested: ${name}`; } };