Skip to content

Commit

Permalink
Fix failing scenarios (#771)
Browse files Browse the repository at this point in the history
* decrease block_span for Fuji

* ReserveConstraint

* lint

* update withdrawReserves scenario

* lint

* PR feedback

* lint

* bump approximation threshold for stETH scenario

* update Arbitrum/USDC flash loan pool
  • Loading branch information
scott-silver authored Jun 29, 2023
1 parent fe6f0a7 commit 6d9c48c
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 18 deletions.
2 changes: 1 addition & 1 deletion plugins/scenario/utils/hreForBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { HARDHAT_PARAM_DEFINITIONS } from 'hardhat/internal/core/params/hardhat-
import { Environment } from 'hardhat/internal/core/runtime-environment';
import { ForkSpec } from '../World';
import { HttpNetworkUserConfig } from 'hardhat/types';
import { EthereumProvider } from "hardhat/types/provider";
import { EthereumProvider } from 'hardhat/types/provider';

/*
mimics https://github.com/nomiclabs/hardhat/blob/master/packages/hardhat-core/src/internal/lib/hardhat-lib.ts
Expand Down
2 changes: 1 addition & 1 deletion scenario/MainnetBulkerScenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ scenario(
expectApproximately(
(await stETH.balanceOf(albert.address)).toBigInt(),
(await wstETH.getStETHByWstETH(exp(1, 18))).toBigInt(),
1n
2n
);
expect(await comet.collateralBalanceOf(albert.address, wstETH.address)).to.be.equal(0n);
}
Expand Down
10 changes: 3 additions & 7 deletions scenario/WithdrawReservesScenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,20 @@ import { scenario } from './context/CometContext';
import { expectRevertCustom } from './utils';
import { expect } from 'chai';

// XXX we could use a Comet reserves constraint here
scenario(
'Comet#withdrawReserves > governor withdraw reserves',
'Comet#withdrawReserves > governor withdraws reserves',
{
reserves: '>= 10000',
tokenBalances: {
betty: { $base: '== 100000' },
albert: { $base: '== 0' },
},
},
async ({ comet, timelock, actors }, context) => {
const { admin, albert, betty } = actors;
const { admin, albert } = actors;

const baseToken = context.getAssetByAddress(await comet.baseToken());
const scale = (await comet.baseScale()).toBigInt();

// Since we don't have a constraint to set Comet reserves, we'll be transferring 100K base tokens to Comet from an actor
// XXX however, this wouldn't work if reserves on testnet are too negative
await betty.transferErc20(baseToken.address, comet.address, 100000n * scale);
const cometBaseBalance = await baseToken.balanceOf(comet.address);

expect(await comet.governor()).to.equal(timelock.address);
Expand Down
1 change: 1 addition & 0 deletions scenario/constraints/Requirements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export interface Requirements {
tokenBalances?: object; // Token balance constraint
utilization?: number; // Utilization constraint
prices?: object; // Price constraint
reserves?: number | string; // Reserves constraint
}
62 changes: 62 additions & 0 deletions scenario/constraints/ReservesConstraint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Constraint, Solution } from '../../plugins/scenario';
import { CometContext } from '../context/CometContext';
import { expect } from 'chai';
import { Requirements } from './Requirements';
import { exp } from '../../test/helpers';
import { ComparisonOp, parseAmount, getToTransferAmount } from '../utils';

export class ReservesConstraint<T extends CometContext, R extends Requirements> implements Constraint<T, R> {
async solve(requirements: R, _initialContext: T) {
const reservesRequirement = requirements.reserves;
if (reservesRequirement !== undefined) {
const solutions: Solution<T>[] = [];
solutions.push(async function barelyMeet(context: T) {
const comet = await context.getComet();
const baseToken = await comet.baseToken();
const currentReserves = (await comet.getReserves()).toBigInt();
const amount = parseAmount(reservesRequirement);
const decimals = await comet.decimals();

expect(amount.op).to.equal(ComparisonOp.GTE, `Operation ${amount.op} not supported (yet) by reserve cap constraint`);

const amountToSource = getToTransferAmount(amount, currentReserves, decimals);
// add buffer to adjust for interest accrual
await context.sourceTokens(amountToSource * 105n / 100n, baseToken, comet.address);

return context;
});
return solutions;
} else {
return null;
}
}

async check(requirements: R, context: T) {
const reservesRequirement = requirements.reserves;
if (reservesRequirement !== undefined) {
const comet = await context.getComet();
const amount = parseAmount(reservesRequirement);
const decimals = await comet.decimals();
const currentReserves = (await comet.getReserves()).toBigInt();
const expectedReserves = exp(amount.val, decimals);

switch (amount.op) {
case ComparisonOp.EQ:
expect(currentReserves).to.equal(expectedReserves);
break;
case ComparisonOp.GTE:
expect(currentReserves).to.be.at.least(expectedReserves);
break;
case ComparisonOp.LTE:
expect(currentReserves).to.be.at.most(expectedReserves);
break;
case ComparisonOp.GT:
expect(currentReserves).to.be.above(expectedReserves);
break;
case ComparisonOp.LT:
expect(currentReserves).to.be.below(expectedReserves);
break;
}
}
}
}
1 change: 1 addition & 0 deletions scenario/constraints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export { MigrationConstraint } from './MigrationConstraint';
export { ProposalConstraint } from './ProposalConstraint';
export { FilterConstraint } from './FilterConstraint';
export { PriceConstraint } from './PriceConstraint';
export { ReservesConstraint } from './ReservesConstraint';
6 changes: 4 additions & 2 deletions scenario/context/CometContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
MigrationConstraint,
ProposalConstraint,
FilterConstraint,
PriceConstraint
PriceConstraint,
ReservesConstraint
} from '../constraints';
import CometActor from './CometActor';
import CometAsset from './CometAsset';
Expand Down Expand Up @@ -414,7 +415,8 @@ export const dynamicConstraints: DynamicConstraint<CometContext, Requirements>[]
new CometBalanceConstraint(),
new TokenBalanceConstraint(),
new UtilizationConstraint(),
new PriceConstraint()
new PriceConstraint(),
new ReservesConstraint()
];

export const scenarioLoader = Loader.get<CometContext, CometProperties, Requirements>().configure(
Expand Down
6 changes: 3 additions & 3 deletions scenario/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,11 @@ export function getToTransferAmount(amount: ComparativeAmount, existingBalance:
break;
case ComparisonOp.GTE:
// `toTransfer` should not be negative
toTransfer = max(exp(amount.val, decimals) - existingBalance, 0);
toTransfer = max(exp(amount.val, decimals) - existingBalance, 0n);
break;
case ComparisonOp.LTE:
// `toTransfer` should not be positive
toTransfer = min(exp(amount.val, decimals) - existingBalance, 0);
toTransfer = min(exp(amount.val, decimals) - existingBalance, 0n);
break;
case ComparisonOp.GT:
toTransfer = exp(amount.val, decimals) - existingBalance + 1n;
Expand Down Expand Up @@ -310,7 +310,7 @@ export async function fetchLogs(
filter: EventFilter,
fromBlock: number,
toBlock: number,
BLOCK_SPAN = 2048 // NB: sadly max for fuji
BLOCK_SPAN = 2047 // NB: sadly max for fuji is LESS than 2048
): Promise<Event[]> {
if (toBlock - fromBlock > BLOCK_SPAN) {
const midBlock = fromBlock + BLOCK_SPAN;
Expand Down
4 changes: 2 additions & 2 deletions scripts/clone-multisig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ async function main() {

// Get owners and threshold from existing multisig
const GnosisABI = [
{"constant":true,"inputs":[],"name":"getOwners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},
{"constant":true,"inputs":[],"name":"getThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},
{'constant':true,'inputs':[],'name':'getOwners','outputs':[{'internalType':'address[]','name':'','type':'address[]'}],'payable':false,'stateMutability':'view','type':'function'},
{'constant':true,'inputs':[],'name':'getThreshold','outputs':[{'internalType':'uint256','name':'','type':'uint256'}],'payable':false,'stateMutability':'view','type':'function'},
];
const GnosisSafeContract = new hre.ethers.Contract(guardian, GnosisABI, hre.ethers.provider);
const owners = await GnosisSafeContract.getOwners();
Expand Down
6 changes: 4 additions & 2 deletions scripts/liquidation_bot/liquidateUnderwaterBorrowers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ const addresses = {
GMX: '0xfc5a1a6eb076a2c7ad06ed22c90d7e710e35ad0a',
WETH: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1',
WBTC: '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f',
USDT: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9'
USDT: '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9',
USDC: '0xaf88d065e77c8cc2239327c5edb3a432268e5831',
USDC_E: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8'
}
};

Expand Down Expand Up @@ -100,7 +102,7 @@ export const flashLoanPools = {
},
arbitrum: {
usdc: {
tokenAddress: addresses.arbitrum.USDT,
tokenAddress: addresses.arbitrum.USDC, // USDC/USDC_E/.01% pool
poolFee: 100
}
}
Expand Down

0 comments on commit 6d9c48c

Please sign in to comment.