Skip to content
Open
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
38 changes: 38 additions & 0 deletions hardhat/tasks/sips/args/sipArgs.js
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,43 @@ const getArgsSip0084Part2 = async (hre) => {
return { args, governor: "GovernorOwner" };
};

const getArgsSip0087 = async (hre) => {
const {
ethers,
deployments: { get },
} = hre;
const abiCoder = new ethers.utils.AbiCoder();

const newTroveManagerImplementation = await get("TroveManager_Implementation");
const newTroveManagerRedeemOps = await get("TroveManagerRedeemOps");

const troveManagerProxy = await get("TroveManager_Proxy");
const troveManagerContract = await ethers.getContract("TroveManager");
const troveManagerOwner = await troveManagerContract.getOwner();

//validate
if (!network.tags.mainnet) {
logger.error("Unknown network");
process.exit(1);
}

const args = {
targets: [troveManagerProxy.address, troveManagerProxy.address],
targetOwnerValidationAddresses: [troveManagerOwner, troveManagerOwner],
values: [0, 0],
signatures: ["setImplementation(address)", "setTroveManagerRedeemOps(address)"],
data: [
abiCoder.encode(["address"], [newTroveManagerImplementation.address]),
abiCoder.encode(["address"], [newTroveManagerRedeemOps.address]),
],
// @todo update sip description & sha256
description:
"SIP-0087: Fix LiquityBaseParamsAddressChanges event argument, Details: https://github.com/DistributedCollective/SIPS/blob/a86ac0e/SIP-0087.md, sha256: ",
};

return { args, governor: "GovernorOwner" };
};

module.exports = {
sampleGovernorAdminSIP,
sampleGovernorOwnerSIP,
Expand All @@ -1202,4 +1239,5 @@ module.exports = {
getArgsSip0079,
getArgsSip0084Part1,
getArgsSip0084Part2,
getArgsSip0087,
};
167 changes: 167 additions & 0 deletions tests-onchain/sip0087.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// first run a local forked mainnet node in a separate terminal window:
// npx hardhat node --fork https://mainnet-dev.sovryn.app/rpc --no-deploy
// now run the test:
// npx hardhat test tests-onchain/sip0087.test.js --network rskForkedMainnet

const {
impersonateAccount,
mine,
time,
setBalance,
} = require("@nomicfoundation/hardhat-network-helpers");
const hre = require("hardhat");
const { getProtocolModules } = require("../deployment/helpers/helpers");

const {
ethers,
deployments: { createFixture, get },
} = hre;

const MAX_DURATION = ethers.BigNumber.from(24 * 60 * 60).mul(1092);

const ONE_RBTC = ethers.utils.parseEther("1.0");

const getImpersonatedSigner = async (addressToImpersonate) => {
await impersonateAccount(addressToImpersonate);
return await ethers.getSigner(addressToImpersonate);
};

describe("Protocol Modules Deployments and Upgrades via Governance", () => {
const getImpersonatedSignerFromJsonRpcProvider = async (addressToImpersonate) => {
const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545");
await provider.send("hardhat_impersonateAccount", [addressToImpersonate]);
return provider.getSigner(addressToImpersonate);
};

const setupTest = createFixture(async ({ deployments }) => {
const deployer = (await ethers.getSigners())[0].address;
const deployerSigner = await ethers.getSigner(deployer);

const multisigAddress = (await get("MultiSigWallet")).address;
const multisigSigner = await getImpersonatedSignerFromJsonRpcProvider(multisigAddress);

await setBalance(deployer, ONE_RBTC.mul(10));
await deployments.fixture(["ProtocolModules"], {
keepExistingDeployments: true,
}); // start from a fresh deployments

const staking = await ethers.getContract("Staking", deployerSigner);
const sovrynProtocol = await ethers.getContract("SovrynProtocol", deployerSigner);

const god = await deployments.get("GovernorOwner");
const governorOwner = await ethers.getContractAt(
"GovernorAlpha",
god.address,
deployerSigner
);
const governorOwnerSigner = await getImpersonatedSigner(god.address);

await setBalance(governorOwnerSigner.address, ONE_RBTC);
const timelockOwner = await ethers.getContract("TimelockOwner", governorOwnerSigner);

const timelockOwnerSigner = await getImpersonatedSignerFromJsonRpcProvider(
timelockOwner.address
);
await setBalance(timelockOwnerSigner._address, ONE_RBTC);

//
return {
deployer,
deployerSigner,
staking,
sovrynProtocol,
governorOwner,
governorOwnerSigner,
timelockOwner,
timelockOwnerSigner,
multisigAddress,
multisigSigner,
};
});

/// @todo change the SIP name
describe("SIP-0087 Test creation and execution", () => {
it("SIP-0087 is executable and valid", async () => {
if (!hre.network.tags["forked"]) {
console.error("ERROR: Must run on a forked net");
return;
}
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: "https://mainnet-dev.sovryn.app/rpc",
blockNumber: 6037998,
},
},
],
});

const {
deployer,
deployerSigner,
staking,
sovrynProtocol,
governorOwner,
timelockOwnerSigner,
multisigAddress,
multisigSigner,
} = await setupTest();

// CREATE PROPOSAL
const sov = await ethers.getContract("SOV", timelockOwnerSigner);
const whaleAmount = (await sov.totalSupply()).mul(ethers.BigNumber.from(5));
await sov.mint(deployer, whaleAmount);

await sov.connect(deployerSigner).approve(staking.address, whaleAmount);

if (await staking.paused()) await staking.connect(multisigSigner).pauseUnpause(false);
const kickoffTS = await staking.kickoffTS();
await staking.stake(whaleAmount, kickoffTS.add(MAX_DURATION), deployer, deployer);
await mine();

// CREATE PROPOSAL AND VERIFY
const proposalIdBeforeSIP = await governorOwner.latestProposalIds(deployer);
await hre.run("sips:create", { argsFunc: "getArgsSip0087" });
const proposalId = await governorOwner.latestProposalIds(deployer);
expect(
proposalId,
"Proposal was not created. Check the SIP creation is not commented out."
).is.gt(proposalIdBeforeSIP);

// VOTE FOR PROPOSAL

await mine();
await governorOwner.connect(deployerSigner).castVote(proposalId, true);

// QUEUE PROPOSAL
let proposal = await governorOwner.proposals(proposalId);
await mine(proposal.endBlock);
await governorOwner.queue(proposalId);

// EXECUTE PROPOSAL
proposal = await governorOwner.proposals(proposalId);
await time.increaseTo(proposal.eta);
await expect(governorOwner.execute(proposalId))
.to.emit(governorOwner, "ProposalExecuted")
.withArgs(proposalId);

// VERIFY execution
expect((await governorOwner.proposals(proposalId)).executed).to.be.true;

// Validate trove manager contracs upgrade
const troveManagerProxy = await ethers.getContract("TroveManager_Proxy");
const troveManagerImpl = await get("TroveManager_Implementation");

const troveManager = await ethers.getContract("TroveManager");
const troveManagerRedeemOps = await get("TroveManagerRedeemOps");

expect(await troveManagerProxy.getImplementation()).to.equal(troveManagerImpl.address);

expect(await troveManager.troveManagerRedeemOps()).to.equal(
troveManagerRedeemOps.address
);
});
});
});
Loading