WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
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
4,477 changes: 4,477 additions & 0 deletions simulations/vip-573/abi/Comptroller.json

Large diffs are not rendered by default.

957 changes: 957 additions & 0 deletions simulations/vip-573/abi/Diamond.json

Large diffs are not rendered by default.

132 changes: 132 additions & 0 deletions simulations/vip-573/bscmainnet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { TransactionResponse } from "@ethersproject/providers";
import { expect } from "chai";
import { Contract } from "ethers";
import { parseEther } from "ethers/lib/utils";
import { ethers } from "hardhat";
import { NETWORK_ADDRESSES } from "src/networkAddresses";
import { expectEvents, initMainnetUser } from "src/utils";
import { forking, testVip } from "src/vip-framework";

import vip573 from "../../vips/vip-573/bscmainnet";
import COMPTROLLER_ABI from "./abi/Comptroller.json";
import DIAMOND_ABI from "./abi/Diamond.json";

const { bscmainnet } = NETWORK_ADDRESSES;

const OLD_MARKET_FACET = "0x7ec871BA4248CC443a994f2febeDFB96DAe444F1";

const NEW_MARKET_FACET = "0x87FdF72FA2fB29Cb43f03aCa261A8DC2C613a860";

// Function selector for enterMarketBehalf(address,address)
const ENTER_MARKET_BEHALF_SELECTOR = "0xd585c3c6";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cast sig "enterMarketBehalf(address,address)"
0xd585c3c6


// Test accounts
const TEST_USER = "0x14A1c22EF6d2eF6cE33c0b018d8A34D02021e5c8";
const TEST_DELEGATE = "0x9cc6f5f16498fceef4d00a350bd8f8921d304dc9";
const VUSDT = "0xfD5840Cd36d94D7229439859C0112a4185BC0255";

forking(69628476, async () => {
const provider = ethers.provider;
let unitroller: Contract;

let marketFacetFunctionSelectors: string[];

before(async () => {
unitroller = new ethers.Contract(bscmainnet.UNITROLLER, COMPTROLLER_ABI, provider);

// Get current MarketFacet function selectors
marketFacetFunctionSelectors = await unitroller.facetFunctionSelectors(OLD_MARKET_FACET);
});

describe("Pre-VIP behavior", async () => {
it("MarketFacet should have old implementation", async () => {
expect(await unitroller.facetFunctionSelectors(OLD_MARKET_FACET)).to.deep.equal(marketFacetFunctionSelectors);
expect(await unitroller.facetFunctionSelectors(NEW_MARKET_FACET)).to.deep.equal([]);
});

it("enterMarketBehalf function should not exist", async () => {
expect(marketFacetFunctionSelectors).to.not.include(ENTER_MARKET_BEHALF_SELECTOR);
});

it("unitroller should contain old MarketFacet address", async () => {
expect(await unitroller.facetAddresses()).to.include(OLD_MARKET_FACET);
expect(await unitroller.facetAddresses()).to.not.include(NEW_MARKET_FACET);
});
});

testVip("vip-573", await vip573(), {
callbackAfterExecution: async (txResponse: TransactionResponse) => {
await expectEvents(txResponse, [DIAMOND_ABI], ["DiamondCut"], [1]);
},
});

describe("Post-VIP behavior", async () => {
it("MarketFacet function selectors should be updated for new facet address", async () => {
const newMarketFacetFunctionSelectors = [ENTER_MARKET_BEHALF_SELECTOR];

const expectSelectors = [...marketFacetFunctionSelectors, ...newMarketFacetFunctionSelectors].sort();
const updatedSelectors = [...(await unitroller.facetFunctionSelectors(NEW_MARKET_FACET))].sort();

expect(updatedSelectors).to.deep.equal(expectSelectors);
expect(await unitroller.facetFunctionSelectors(OLD_MARKET_FACET)).to.deep.equal([]);
});

it("unitroller should contain new MarketFacet address", async () => {
expect(await unitroller.facetAddresses()).to.include(NEW_MARKET_FACET);
expect(await unitroller.facetAddresses()).to.not.include(OLD_MARKET_FACET);
});

it("enterMarketBehalf function should exist in new facet", async () => {
const newFacetSelectors = await unitroller.facetFunctionSelectors(NEW_MARKET_FACET);
expect(newFacetSelectors).to.include(ENTER_MARKET_BEHALF_SELECTOR);
});
it("should allow approved delegate to enter market on behalf of user", async () => {
const user = await initMainnetUser(TEST_USER, parseEther("10000"));

// First, exit the market if already in it
try {
await unitroller.connect(user).exitMarket(VUSDT);
} catch (e) {
// Market might not be entered, continue
}

// Approve delegate
await unitroller.connect(user).updateDelegate(TEST_DELEGATE, true);

// Switch to delegate
const delegate = await initMainnetUser(TEST_DELEGATE, parseEther("10000"));

// Check membership before
const membershipBefore = await unitroller.checkMembership(TEST_USER, VUSDT);
expect(membershipBefore).to.be.false;

await expect(await unitroller.connect(delegate).enterMarketBehalf(TEST_USER, VUSDT))
.to.emit(unitroller, "MarketEntered")
.withArgs(VUSDT, TEST_USER);

// Check membership after
const membershipAfter = await unitroller.checkMembership(TEST_USER, VUSDT);
expect(membershipAfter).to.be.true;
});

it("should revert when unapproved delegate tries to enter market", async () => {
const userSigner = await initMainnetUser(TEST_DELEGATE, parseEther("10000"));
const comptroller = unitroller.connect(userSigner);

try {
await comptroller.exitMarket(VUSDT);
} catch (e) {
// Market might not be entered, continue
}

const delegateSigner = await initMainnetUser(TEST_USER, parseEther("10000"));
const comptrollerDelegate = unitroller.connect(delegateSigner);

// Should revert with NotAnApprovedDelegate
await expect(comptrollerDelegate.enterMarketBehalf(TEST_DELEGATE, VUSDT)).to.be.revertedWithCustomError(
comptrollerDelegate,
"NotAnApprovedDelegate",
);
});
});
});
132 changes: 132 additions & 0 deletions simulations/vip-573/bsctestnet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { TransactionResponse } from "@ethersproject/providers";
import { expect } from "chai";
import { Contract } from "ethers";
import { parseEther } from "ethers/lib/utils";
import { ethers } from "hardhat";
import { NETWORK_ADDRESSES } from "src/networkAddresses";
import { expectEvents, initMainnetUser } from "src/utils";
import { forking, testVip } from "src/vip-framework";

import vip573 from "../../vips/vip-573/bsctestnet";
import COMPTROLLER_ABI from "./abi/Comptroller.json";
import DIAMOND_ABI from "./abi/Diamond.json";

const { bsctestnet } = NETWORK_ADDRESSES;

const OLD_MARKET_FACET = "0x0A7A88aB6aB40417Bd6bF1EB3907EFF06D24C2FC";

const NEW_MARKET_FACET = "0x8e0e15C99Ab0985cB39B2FE36532E5692730eBA9";

// Function selector for enterMarketBehalf(address,address)
const ENTER_MARKET_BEHALF_SELECTOR = "0xd585c3c6";

// Test accounts
const TEST_USER = "0x14A1c22EF6d2eF6cE33c0b018d8A34D02021e5c8";
const TEST_DELEGATE = "0x9cc6f5f16498fceef4d00a350bd8f8921d304dc9";
const VUSDT = "0xb7526572FFE56AB9D7489838Bf2E18e3323b441A";

forking(73659707, async () => {
const provider = ethers.provider;
let unitroller: Contract;

let marketFacetFunctionSelectors: string[];

before(async () => {
unitroller = new ethers.Contract(bsctestnet.UNITROLLER, COMPTROLLER_ABI, provider);

// Get current MarketFacet function selectors
marketFacetFunctionSelectors = await unitroller.facetFunctionSelectors(OLD_MARKET_FACET);
});

describe("Pre-VIP behavior", async () => {
it("MarketFacet should have old implementation", async () => {
expect(await unitroller.facetFunctionSelectors(OLD_MARKET_FACET)).to.deep.equal(marketFacetFunctionSelectors);
expect(await unitroller.facetFunctionSelectors(NEW_MARKET_FACET)).to.deep.equal([]);
});

it("enterMarketBehalf function should not exist", async () => {
expect(marketFacetFunctionSelectors).to.not.include(ENTER_MARKET_BEHALF_SELECTOR);
});

it("unitroller should contain old MarketFacet address", async () => {
expect(await unitroller.facetAddresses()).to.include(OLD_MARKET_FACET);
expect(await unitroller.facetAddresses()).to.not.include(NEW_MARKET_FACET);
});
});

testVip("vip-573", await vip573(), {
callbackAfterExecution: async (txResponse: TransactionResponse) => {
await expectEvents(txResponse, [DIAMOND_ABI], ["DiamondCut"], [1]);
},
});

describe("Post-VIP behavior", async () => {
it("MarketFacet function selectors should be updated for new facet address", async () => {
const newMarketFacetFunctionSelectors = [ENTER_MARKET_BEHALF_SELECTOR];

const expectSelectors = [...marketFacetFunctionSelectors, ...newMarketFacetFunctionSelectors].sort();
const updatedSelectors = [...(await unitroller.facetFunctionSelectors(NEW_MARKET_FACET))].sort();

expect(updatedSelectors).to.deep.equal(expectSelectors);
expect(await unitroller.facetFunctionSelectors(OLD_MARKET_FACET)).to.deep.equal([]);
});

it("unitroller should contain new MarketFacet address", async () => {
expect(await unitroller.facetAddresses()).to.include(NEW_MARKET_FACET);
expect(await unitroller.facetAddresses()).to.not.include(OLD_MARKET_FACET);
});

it("enterMarketBehalf function should exist in new facet", async () => {
const newFacetSelectors = await unitroller.facetFunctionSelectors(NEW_MARKET_FACET);
expect(newFacetSelectors).to.include(ENTER_MARKET_BEHALF_SELECTOR);
});
it("should allow approved delegate to enter market on behalf of user", async () => {
const user = await initMainnetUser(TEST_USER, parseEther("10000"));

// First, exit the market if already in it
try {
await unitroller.connect(user).exitMarket(VUSDT);
} catch (e) {
// Market might not be entered, continue
}

// Approve delegate
await unitroller.connect(user).updateDelegate(TEST_DELEGATE, true);

// Switch to delegate
const delegate = await initMainnetUser(TEST_DELEGATE, parseEther("10000"));

// Check membership before
const membershipBefore = await unitroller.checkMembership(TEST_USER, VUSDT);
expect(membershipBefore).to.be.false;

await expect(await unitroller.connect(delegate).enterMarketBehalf(TEST_USER, VUSDT))
.to.emit(unitroller, "MarketEntered")
.withArgs(VUSDT, TEST_USER);

// Check membership after
const membershipAfter = await unitroller.checkMembership(TEST_USER, VUSDT);
expect(membershipAfter).to.be.true;
});

it("should revert when unapproved delegate tries to enter market", async () => {
const userSigner = await initMainnetUser(TEST_DELEGATE, parseEther("10000"));
const comptroller = unitroller.connect(userSigner);

try {
await comptroller.exitMarket(VUSDT);
} catch (e) {
// Market might not be entered, continue
}

const delegateSigner = await initMainnetUser(TEST_USER, parseEther("10000"));
const comptrollerDelegate = unitroller.connect(delegateSigner);

// Should revert with NotAnApprovedDelegate
await expect(comptrollerDelegate.enterMarketBehalf(TEST_DELEGATE, VUSDT)).to.be.revertedWithCustomError(
comptrollerDelegate,
"NotAnApprovedDelegate",
);
});
});
});
41 changes: 41 additions & 0 deletions simulations/vip-573/utils/cut-params-bscmainnet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"cutParams": [
[
"0x87FdF72FA2fB29Cb43f03aCa261A8DC2C613a860",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we get it verified @GitGuru7

1,
[
"0xa76b3fda",
"0x929fe9a1",
"0xc2998238",
"0xede4edd0",
"0xb0772d0b",
"0xabfceffc",
"0x007e3dd2",
"0xc488847b",
"0xa78dc775",
"0x0686dab6",
"0xddbf54fd",
"0x3d98a1e5",
"0xcab4f84c",
"0xc5b4db55",
"0x89c13be0",
"0xd0d13036",
"0xf9682732",
"0x23617585",
"0xafd3783b",
"0x19ef3e8b",
"0xd686e9ee",
"0x7b86e42c",
"0x63e0d634",
"0xf02fdf97",
"0x0ef332ca",
"0x8e8f294b",
"0x3093c11e",
"0xd137f36e",
"0xd463654c",
"0x4d99c776"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aditya, curious, is there a tool to generate the selector list of a facet

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, nvm, guess u r calling unitroller.facetFunctionSelectors

]
],
["0x87FdF72FA2fB29Cb43f03aCa261A8DC2C613a860", 0, ["0xd585c3c6"]]
]
}
41 changes: 41 additions & 0 deletions simulations/vip-573/utils/cut-params-bsctestnet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"cutParams": [
[
"0x8e0e15C99Ab0985cB39B2FE36532E5692730eBA9",
1,
[
"0xa76b3fda",
"0x929fe9a1",
"0xc2998238",
"0xede4edd0",
"0xb0772d0b",
"0xabfceffc",
"0x007e3dd2",
"0xc488847b",
"0xa78dc775",
"0x0686dab6",
"0xddbf54fd",
"0x3d98a1e5",
"0xcab4f84c",
"0xc5b4db55",
"0x89c13be0",
"0xd0d13036",
"0xf9682732",
"0x23617585",
"0xafd3783b",
"0x19ef3e8b",
"0xd686e9ee",
"0x7b86e42c",
"0x63e0d634",
"0xf02fdf97",
"0x0ef332ca",
"0x8e8f294b",
"0x3093c11e",
"0xd137f36e",
"0xd463654c",
"0x4d99c776"
]
],
["0x8e0e15C99Ab0985cB39B2FE36532E5692730eBA9", 0, ["0xd585c3c6"]]
]
}
38 changes: 38 additions & 0 deletions vips/vip-573/bscmainnet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { NETWORK_ADDRESSES } from "src/networkAddresses";
import { ProposalType } from "src/types";
import { makeProposal } from "src/utils";

import { cutParams as params } from "../../simulations/vip-573/utils/cut-params-bscmainnet.json";

const { bscmainnet } = NETWORK_ADDRESSES;

export const cutParams = params;

export const vip573 = () => {
const meta = {
version: "v2",
title: "VIP-573 [BNB Chain] Add enterMarketBehalf support to Comptroller",
description: `#### Summary

If passed, this VIP will upgrade the MarketFacet of the core pool Comptroller on BNB Chain Mainnet to add support for the \`enterMarketBehalf\` function, allowing approved delegates to enter markets on behalf of users.

#### Description`,
forDescription: "Execute this proposal",
againstDescription: "Do not execute this proposal",
abstainDescription: "Indifferent to execution",
};

return makeProposal(
[
{
target: bscmainnet.UNITROLLER,
signature: "diamondCut((address,uint8,bytes4[])[])",
params: [cutParams],
},
],
meta,
ProposalType.REGULAR,
);
};

export default vip573;
Loading
Loading