Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix failing scenarios #771

Merged
merged 9 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
scott-silver marked this conversation as resolved.
Show resolved Hide resolved
);
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
scott-silver marked this conversation as resolved.
Show resolved Hide resolved
poolFee: 100
}
}
Expand Down