Skip to content
This repository was archived by the owner on Aug 26, 2024. It is now read-only.

Commit d7a7826

Browse files
authored
Merge pull request #78 from ionicprotocol/feat/liquidate-borrow-permissioning
Feat/liquidate borrow permissioning
2 parents 31600e4 + f8eda78 commit d7a7826

File tree

7 files changed

+155
-54
lines changed

7 files changed

+155
-54
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ ionic-contracts.iml
1616
cache_hardhat
1717
transactions.json
1818
*transactions.json
19+
deployments/local

contracts/test/PermissionedLiquidationsMarketTest.t.sol

+87
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,26 @@ import { FeeDistributor } from "../FeeDistributor.sol";
1515
import { CTokenFirstExtension } from "../compound/CTokenFirstExtension.sol";
1616
import { ComptrollerV3Storage } from "../compound/ComptrollerStorage.sol";
1717
import { IonicComptroller } from "../compound/ComptrollerInterface.sol";
18+
import { ILiquidator } from "../ILiquidator.sol";
1819

1920
import { IERC20Upgradeable } from "openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
2021
import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
2122
import { PoolLens } from "../PoolLens.sol";
2223
import { AddressesProvider } from "../ionic/AddressesProvider.sol";
2324
import { IonicUniV3Liquidator } from "../IonicUniV3Liquidator.sol";
2425
import { ERC20 } from "solmate/tokens/ERC20.sol";
26+
import { IRedemptionStrategy } from "../liquidators/IRedemptionStrategy.sol";
27+
import { IFundsConversionStrategy } from "../liquidators/IFundsConversionStrategy.sol";
2528

2629
contract PermissionedLiquidationsMarketTest is MarketsTest {
2730
ICErc20 wethMarket;
2831
ICErc20 usdtMarket;
32+
33+
ICErc20 wethNativeMarket;
34+
ICErc20 usdcNativeMarket;
35+
ICErc20 usdtNativeMarket;
36+
ICErc20 modeNativeMarket;
37+
2938
IonicComptroller pool;
3039
PoolLens lens;
3140
address borrower;
@@ -37,6 +46,12 @@ contract PermissionedLiquidationsMarketTest is MarketsTest {
3746

3847
wethMarket = ICErc20(0x71ef7EDa2Be775E5A7aa8afD02C45F059833e9d2);
3948
usdtMarket = ICErc20(0x94812F2eEa03A49869f95e1b5868C6f3206ee3D3);
49+
50+
wethNativeMarket = ICErc20(0xDb8eE6D1114021A94A045956BBeeCF35d13a30F2);
51+
usdcNativeMarket = ICErc20(0xc53edEafb6D502DAEC5A7015D67936CEa0cD0F52);
52+
usdtNativeMarket = ICErc20(0x3120B4907851cc9D780eef9aF88ae4d5360175Fd);
53+
modeNativeMarket = ICErc20(0x4341620757Bee7EB4553912FaFC963e59C949147);
54+
4055
pool = IonicComptroller(0xFB3323E24743Caf4ADD0fDCCFB268565c0685556);
4156
lens = PoolLens(0x70BB19a56BfAEc65aE861E6275A90163AbDF36a6);
4257
ffd = FeeDistributor(payable(ap.getAddress("FeeDistributor")));
@@ -164,6 +179,54 @@ contract PermissionedLiquidationsMarketTest is MarketsTest {
164179
vm.stopPrank();
165180
}
166181

182+
function testPostUpgradeLiquidate() public debuggingOnly fork(MODE_MAINNET) {
183+
address borrower = 0xE10B38bbe359656066b3c4648DfEa7018711c35f;
184+
PoolLens.PoolAsset[] memory assets = lens.getPoolAssetsByUser(pool, borrower);
185+
186+
for (uint i; i < assets.length; i++) {
187+
emit log_named_string("Asset Named", assets[i].underlyingName);
188+
emit log_named_uint("Supply Balance", assets[i].supplyBalance);
189+
emit log_named_uint("Borrow Balance", assets[i].borrowBalance);
190+
emit log_named_uint("Liquidity", assets[i].liquidity);
191+
emit log("----------------------------------------------------");
192+
}
193+
194+
emit log_named_uint("HF", lens.getHealthFactor(borrower, pool));
195+
196+
// vm.startPrank(0x344d9C4f488bb5519D390304457D64034618145C);
197+
198+
// ERC20(0xd988097fb8612cc24eeC14542bC03424c656005f).approve(address(uniV3liquidator), 4000);
199+
200+
// // ILiquidator.LiquidateToTokensWithFlashSwapVars memory vars = ILiquidator.LiquidateToTokensWithFlashSwapVars({
201+
// // borrower: borrower,
202+
// // repayAmount: 4000,
203+
// // cErc20: ICErc20(0x2BE717340023C9e14C1Bb12cb3ecBcfd3c3fB038),
204+
// // cTokenCollateral: wethMarket,
205+
// // flashSwapContract: 0x468cC91dF6F669CaE6cdCE766995Bd7874052FBc,
206+
// // minProfitAmount: 0,
207+
// // redemptionStrategies: new IRedemptionStrategy[](0),
208+
// // strategyData: new bytes[](0),
209+
// // debtFundingStrategies: new IFundsConversionStrategy[](0),
210+
// // debtFundingStrategiesData: new bytes[](0)
211+
// // });
212+
// // uniV3liquidator.safeLiquidateToTokensWithFlashLoan(vars);
213+
214+
// uniV3liquidator.safeLiquidate(borrower, 4000, ICErc20(0x2BE717340023C9e14C1Bb12cb3ecBcfd3c3fB038), wethMarket, 0);
215+
216+
// vm.stopPrank();
217+
218+
// emit log_named_uint("HF", lens.getHealthFactor(borrower, pool));
219+
}
220+
221+
function testUpgradeNativeMarket() public debuggingOnly fork(MODE_MAINNET) {
222+
_upgradeMarket(wethNativeMarket);
223+
_upgradeMarket(usdcNativeMarket);
224+
_upgradeMarket(usdtNativeMarket);
225+
_upgradeMarket(modeNativeMarket);
226+
_upgradeMarket(wethMarket);
227+
_upgradeMarket(usdtMarket);
228+
}
229+
167230
struct CErc20StorageStruct {
168231
address ionicAdmin;
169232
string name;
@@ -431,4 +494,28 @@ contract PermissionedLiquidationsMarketTest is MarketsTest {
431494
"Mismatch in feeSeizeShareMantissa"
432495
);
433496
}
497+
498+
function testCurrentMarkets() public debuggingOnly forkAtBlock(MODE_MAINNET, 10785800) {
499+
address[] memory ionAddresses = new address[](10);
500+
501+
_upgradeMarket(wethMarket);
502+
503+
ionAddresses[0] = 0x71ef7EDa2Be775E5A7aa8afD02C45F059833e9d2;
504+
ionAddresses[1] = 0x2BE717340023C9e14C1Bb12cb3ecBcfd3c3fB038;
505+
ionAddresses[2] = 0x94812F2eEa03A49869f95e1b5868C6f3206ee3D3;
506+
ionAddresses[3] = 0xd70254C3baD29504789714A7c69d60Ec1127375C;
507+
ionAddresses[4] = 0x59e710215d45F584f44c0FEe83DA6d43D762D857;
508+
ionAddresses[5] = 0x959FA710CCBb22c7Ce1e59Da82A247e686629310;
509+
ionAddresses[6] = 0x49950319aBE7CE5c3A6C90698381b45989C99b46;
510+
ionAddresses[7] = 0xA0D844742B4abbbc43d8931a6Edb00C56325aA18;
511+
ionAddresses[8] = 0x9a9072302B775FfBd3Db79a7766E75Cf82bcaC0A;
512+
ionAddresses[9] = 0x19F245782b1258cf3e11Eda25784A378cC18c108;
513+
514+
address ap;
515+
for (uint i = 0; i < ionAddresses.length; i++) {
516+
// ap = address(CTokenFirstExtension(ionAddresses[i]).ap());
517+
ap = address(CTokenFirstExtension(address(wethMarket)).ap());
518+
emit log_named_address("ap", ap);
519+
}
520+
}
434521
}

hardhat.config.ts

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ const config: HardhatUserConfig = {
2929
}
3030
]
3131
},
32+
external: {
33+
contracts: [{ artifacts: "./out" }]
34+
},
3235
paths: {
3336
sources: "./contracts",
3437
tests: "./contracts/test",

lib/flywheel-v2

Submodule flywheel-v2 added at 5ac5d31

tasks/market/upgrade.ts

+59-52
Original file line numberDiff line numberDiff line change
@@ -64,45 +64,87 @@ task("market:upgrade:safe", "Upgrades a market's implementation")
6464
let { pluginAddress } = taskArgs;
6565

6666
const cTokenDelegator = await viem.getContractAt("CErc20Delegator", marketAddress);
67-
6867
const cfe = await viem.getContractAt(
6968
"CTokenFirstExtension",
7069
(await deployments.get("CTokenFirstExtension")).address as Address
7170
);
71+
const ap = await viem.getContractAt(
72+
"AddressesProvider",
73+
(await deployments.get("AddressesProvider")).address as Address
74+
);
75+
7276
const impl = await cTokenDelegator.read.implementation();
7377
const extensions = await cTokenDelegator.read._listExtensions();
74-
78+
const comptroller = await cTokenDelegator.read.comptroller();
79+
const comptrollerAsExt = await viem.getContractAt("IonicComptroller", comptroller as Address);
80+
const ctokenAsExt = await viem.getContractAt("CTokenFirstExtension", marketAddress)
81+
7582
if (
7683
impl.toLowerCase() != implementationAddress.toLowerCase() ||
7784
extensions.length == 0 ||
78-
extensions[0].toLowerCase() != cfe.address.toLowerCase()
85+
extensions[1].toLowerCase() != cfe.address.toLowerCase()
7986
) {
8087
if (!pluginAddress) {
8188
pluginAddress = zeroAddress;
8289
}
83-
8490
const implementationData = encodeAbiParameters(parseAbiParameters("address"), [pluginAddress]);
85-
8691
console.log(`Setting implementation to ${implementationAddress} with plugin ${pluginAddress}`);
8792

88-
await prepareAndLogTransaction({
89-
contractInstance: cTokenDelegator,
90-
functionName: "_setImplementationSafe",
91-
args: [implementationAddress, implementationData],
92-
description: `Setting new implementation on ${cTokenDelegator.address}`,
93-
inputs: [
94-
{ internalType: "address", name: "implementation_", type: "address" },
95-
{ internalType: "bytes", name: "implementationData", type: "bytes" }
96-
]
97-
});
93+
const comptrollerAdmin = await comptrollerAsExt.read.admin()
94+
if(comptrollerAdmin.toLowerCase() !== deployer.toLowerCase()) {
95+
await prepareAndLogTransaction({
96+
contractInstance: cTokenDelegator,
97+
functionName: "_setImplementationSafe",
98+
args: [implementationAddress, implementationData],
99+
description: `Setting new implementation on ${cTokenDelegator.address}`,
100+
inputs: [
101+
{ internalType: "address", name: "implementation_", type: "address" },
102+
{ internalType: "bytes", name: "implementationData", type: "bytes" }
103+
]
104+
});
105+
await prepareAndLogTransaction({
106+
contractInstance: ctokenAsExt,
107+
functionName: "_setAddressesProvider",
108+
args: [ap.address],
109+
description: `Setting AddressesProvider on ${marketAddress}`,
110+
inputs: [
111+
{ internalType: "address", name: "_ap", type: "address" }
112+
]
113+
});
114+
} else {
115+
console.log(`Setting implementation to ${implementationAddress}`);
116+
const setImplementationTx = await cTokenDelegator.write._setImplementationSafe([
117+
implementationAddress,
118+
implementationData
119+
]);
120+
const receipt = await publicClient.waitForTransactionReceipt({
121+
hash: setImplementationTx
122+
});
123+
if (receipt.status !== "success") {
124+
throw `Failed set implementation to ${implementationAddress}`;
125+
}
126+
console.log(
127+
`Implementation successfully set to ${implementationAddress}: ${setImplementationTx}`
128+
);
129+
130+
console.log(`Setting AP to to ${ap.address}`);
131+
const setAPTX = await ctokenAsExt.write._setAddressesProvider([ap.address]);
132+
const receiptAP = await publicClient.waitForTransactionReceipt({
133+
hash: setAPTX
134+
});
135+
if (receiptAP.status !== "success") {
136+
throw `Failed set AP to ${ap.address}`;
137+
}
138+
console.log(`AP successfully set to ${ap.address}`);
139+
}
98140

99141
if (pluginAddress != zeroAddress) {
100142
const cTokenPluginInstance = await viem.getContractAt("ICErc20Plugin", marketAddress);
101143
console.log(`with plugin ${await cTokenPluginInstance.read.plugin()}`);
102144
}
103145
} else {
104146
console.log(
105-
`market ${marketAddress} impl ${impl} already eq ${implementationAddress} and extension ${cfe.address} eq ${extensions[0]}`
147+
`market ${marketAddress} impl ${impl} already eq ${implementationAddress} and extension ${cfe.address} eq ${extensions[1]}`
106148
);
107149
}
108150
});
@@ -122,12 +164,6 @@ task("markets:upgrade-and-setup", "Upgrades all markets and sets addresses provi
122164
"FeeDistributor",
123165
(await deployments.get("FeeDistributor")).address as Address
124166
);
125-
126-
const addressProvider = await viem.getContractAt(
127-
"AddressesProvider",
128-
(await deployments.get("AddressesProvider")).address as Address
129-
);
130-
131167
const ionicUniV3Liquidator = await viem.getContractAt(
132168
"IonicUniV3Liquidator",
133169
(await deployments.get("IonicUniV3Liquidator")).address as Address
@@ -145,20 +181,6 @@ task("markets:upgrade-and-setup", "Upgrades all markets and sets addresses provi
145181
]
146182
});
147183

148-
await prepareAndLogTransaction({
149-
contractInstance: addressProvider,
150-
functionName: "setAddress",
151-
args: [
152-
"PoolLens",
153-
(await deployments.get("PoolLens")).address as Address
154-
],
155-
description: `Setting PoolLens id on AddressProvider`,
156-
inputs: [
157-
{ internalType: "string", name: "id", type: "string" },
158-
{ internalType: "address", name: "newAddress", type: "address" }
159-
]
160-
});
161-
162184
const [, pools] = await poolDirectory.read.getActivePools();
163185
for (let i = 0; i < pools.length; i++) {
164186
const pool = pools[i];
@@ -178,24 +200,9 @@ task("markets:upgrade-and-setup", "Upgrades all markets and sets addresses provi
178200
marketAddress: market,
179201
implementationAddress: latestImpl,
180202
});
181-
const ap = await viem.getContractAt(
182-
"AddressesProvider",
183-
(await deployments.get("AddressesProvider")).address as Address
184-
);
185-
const ctokenAsExt = await viem.getContractAt("CTokenFirstExtension", market)
186-
187-
await prepareAndLogTransaction({
188-
contractInstance: ctokenAsExt,
189-
functionName: "_setAddressesProvider",
190-
args: [ap.address],
191-
description: `Setting AddressesProvider on ${market}`,
192-
inputs: [
193-
{ internalType: "address", name: "_ap", type: "address" }
194-
]
195-
});
196203
}
197204
} catch (e) {
198-
console.error(`error while upgrading the pool ${JSON.stringify(pool)}`, e);
205+
console.error(`error while upgrading the pool`, e);
199206
}
200207
}
201208
});

0 commit comments

Comments
 (0)