@mstable/protocol
Version:
mStable Contracts
260 lines • 18.5 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = __importDefault(require("axios"));
const config_1 = require("hardhat/config");
const generated_1 = require("types/generated");
const RewardsDistributorEth__factory_1 = require("types/generated/factories/RewardsDistributorEth__factory");
const math_1 = require("@utils/math");
const utils_1 = require("ethers/lib/utils");
const constants_1 = require("@utils/constants");
const tokens_1 = require("./utils/tokens");
const defender_utils_1 = require("./utils/defender-utils");
const deploy_utils_1 = require("./utils/deploy-utils");
const networkAddressFactory_1 = require("./utils/networkAddressFactory");
const utils_2 = require("./utils");
const snap_utils_1 = require("./utils/snap-utils");
config_1.task("eject-stakers", "Ejects expired stakers from Meta staking contract (vMTA)")
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "average", config_1.types.string)
.setAction(async (taskArgs, { ethers, hardhatArguments, network }) => {
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const chain = networkAddressFactory_1.getChain(network.name, hardhatArguments.config);
const ejectorAddress = networkAddressFactory_1.getChainAddress("Ejector", chain);
const ejector = generated_1.IEjector__factory.connect(ejectorAddress, signer);
// TODO check the last time the eject was run
// Check it's been more than 7 days since the last eject has been run
// get stakers from API
const response = await axios_1.default.get("https://api-dot-mstable.appspot.com/stakers");
const stakers = response.data.ejected;
if (stakers.length === 0) {
console.error(`No stakers to eject`);
process.exit(0);
}
console.log(`${stakers.length} stakers to be ejected: ${stakers}`);
const tx = await ejector.ejectMany(stakers);
await deploy_utils_1.logTxDetails(tx, "ejectMany");
});
config_1.task("collect-interest", "Collects and streams interest from platforms")
.addParam("asset", "Token symbol of main or feeder pool asset. eg mUSD, mBTC, fpmBTC/HBTC or fpmUSD/GUSD", undefined, config_1.types.string, false)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "average", config_1.types.string)
.setAction(async (taskArgs, { ethers, hardhatArguments, network }) => {
const chain = networkAddressFactory_1.getChain(network.name, hardhatArguments.config);
const asset = tokens_1.tokens.find((t) => t.symbol === taskArgs.asset);
if (!asset) {
console.error(`Failed to find main or feeder pool asset with token symbol ${taskArgs.asset}`);
process.exit(1);
}
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const savingsManagerAddress = networkAddressFactory_1.getChainAddress("SavingsManager", chain);
const savingsManager = generated_1.SavingsManager__factory.connect(savingsManagerAddress, signer);
const lastBatchCollected = await savingsManager.lastBatchCollected(asset.address);
const lastBatchDate = new Date(lastBatchCollected.mul(1000).toNumber());
console.log(`The last interest collection was ${lastBatchDate.toUTCString()}, epoch ${lastBatchCollected} seconds`);
const currentEpoc = new Date().getTime() / 1000;
if (currentEpoc - lastBatchCollected.toNumber() < 60 * 60 * 6) {
console.error(`Can not run again as the last run was less then 6 hours ago`);
process.exit(3);
}
const tx = await savingsManager.collectAndStreamInterest(asset.address);
await deploy_utils_1.logTxDetails(tx, "collectAndStreamInterest");
});
config_1.task("polly-daily", "Runs the daily jobs against the contracts on Polygon mainnet")
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", config_1.types.string)
.setAction(async (taskArgs, { ethers, hardhatArguments, network }) => {
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const chain = networkAddressFactory_1.getChain(network.name, hardhatArguments.config);
const aave = generated_1.PAaveIntegration__factory.connect(tokens_1.PmUSD.integrator, signer);
const aaveTx = await aave.claimRewards({ gasLimit: 200000 });
await deploy_utils_1.logTxDetails(aaveTx, "claimRewards");
const liquidatorAddress = networkAddressFactory_1.getChainAddress("Liquidator", chain);
const liquidator = generated_1.PLiquidator__factory.connect(liquidatorAddress, signer);
const liquidatorTx = await liquidator.triggerLiquidation(tokens_1.PmUSD.integrator, { gasLimit: 2000000 });
await deploy_utils_1.logTxDetails(liquidatorTx, "triggerLiquidation");
const savingsManagerAddress = networkAddressFactory_1.getChainAddress("SavingsManager", chain);
const savingsManager = generated_1.SavingsManager__factory.connect(savingsManagerAddress, signer);
const savingsManagerTx = await savingsManager.collectAndStreamInterest(tokens_1.PmUSD.address, {
gasLimit: 2000000,
});
await deploy_utils_1.logTxDetails(savingsManagerTx, "collectAndStreamInterest");
});
config_1.task("polly-stake-imusd", "Stakes imUSD into the v-imUSD vault on Polygon")
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", config_1.types.string)
.setAction(async (taskArgs, { ethers }) => {
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const amount = math_1.simpleToExactAmount(20);
const imUSD = generated_1.ERC20__factory.connect(tokens_1.PmUSD.savings, signer);
const tx1 = await imUSD.approve(tokens_1.PmUSD.vault, amount);
await deploy_utils_1.logTxDetails(tx1, "Relay approves v-imUSD vault to transfer imUSD");
const vault = generated_1.StakingRewards__factory.connect(tokens_1.PmUSD.vault, signer);
const tx2 = await vault["stake(uint256)"](amount);
await deploy_utils_1.logTxDetails(tx2, `stake ${utils_2.usdFormatter(amount)} imUSD in v-imUSD vault`);
});
config_1.task("polly-dis-rewards", "Distributes MTA and WMATIC rewards to the imUSD vault on Polygon")
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", config_1.types.string)
.addOptionalParam("mtaAmount", "MTA tokens", 20833, config_1.types.int)
.addOptionalParam("wmaticAmount", "WMATIC tokens", 18666, config_1.types.int)
.setAction(async (taskArgs, { ethers, hardhatArguments, network }) => {
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const chain = networkAddressFactory_1.getChain(network.name, hardhatArguments.config);
const mtaAmount = math_1.simpleToExactAmount(taskArgs.mtaAmount);
const wmaticAmount = math_1.simpleToExactAmount(taskArgs.wmaticAmount);
const rewardsDistributorAddress = networkAddressFactory_1.getChainAddress("RewardsDistributor", chain);
const rewardsDistributor = generated_1.RewardsDistributor__factory.connect(rewardsDistributorAddress, signer);
const mtaToken = generated_1.ERC20__factory.connect(tokens_1.PMTA.address, signer);
const tx1 = await mtaToken.approve(rewardsDistributorAddress, mtaAmount);
await deploy_utils_1.logTxDetails(tx1, `Relay account approve RewardsDistributor contract to transfer ${utils_2.usdFormatter(mtaAmount)} MTA`);
const wmaticToken = generated_1.ERC20__factory.connect(tokens_1.PWMATIC.address, signer);
const tx2 = await wmaticToken.approve(rewardsDistributorAddress, wmaticAmount);
await deploy_utils_1.logTxDetails(tx2, `Relay account approve RewardsDistributor contract to transfer ${utils_2.usdFormatter(wmaticAmount)} WMATIC`);
const tx3 = await rewardsDistributor.distributeRewards([tokens_1.PmUSD.vault], [mtaAmount], [wmaticAmount]);
await deploy_utils_1.logTxDetails(tx3, `distributeRewards ${utils_2.usdFormatter(mtaAmount)} MTA and ${utils_2.usdFormatter(wmaticAmount)} WMATIC`);
});
config_1.task("dis-rewards", "Distributes MTA rewards to a vault on Mainnet")
.addParam("vaultAsset", "Symbol of asset that is staked. eg mUSD, MTA, GUSD, alUSD", undefined, config_1.types.string)
.addOptionalParam("amount", "MTA tokens", 20833, config_1.types.int)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", config_1.types.string)
.setAction(async (taskArgs, { ethers, hardhatArguments, network }) => {
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const chain = networkAddressFactory_1.getChain(network.name, hardhatArguments.config);
const vaultAsset = tokens_1.tokens.find((t) => t.symbol === taskArgs.vaultAsset && t.chain === chain);
if (!vaultAsset)
throw Error(`Could not find vault asset with symbol ${taskArgs.vaultAsset}`);
const rewardsDistributorAddress = networkAddressFactory_1.getChainAddress("RewardsDistributor", chain);
const rewardsDistributor = RewardsDistributorEth__factory_1.RewardsDistributorEth__factory.connect(rewardsDistributorAddress, signer);
const mtaAmount = math_1.simpleToExactAmount(taskArgs.amount);
const tx = await rewardsDistributor.distributeRewards([vaultAsset.vault], [mtaAmount]);
await deploy_utils_1.logTxDetails(tx, `distributeRewards ${utils_1.formatUnits(mtaAmount)} MTA to vault with asset ${vaultAsset.symbol} and address ${vaultAsset.vault}`);
});
config_1.task("rewards", "Get Compound and Aave platform reward tokens")
.addOptionalParam("block", "Block number to compare rates at. (default: current block)", 0, config_1.types.int)
.setAction(async (taskArgs, { ethers }) => {
const signer = await defender_utils_1.getSigner(ethers);
const block = await snap_utils_1.getBlock(ethers, taskArgs.block);
console.log(`\nGetting platform tokens at block ${block.blockNumber}, ${block.blockTime.toUTCString()}`);
await snap_utils_1.getCompTokens(signer, block);
await snap_utils_1.getAaveTokens(signer, block);
await snap_utils_1.getAlcxTokens(signer, block);
});
config_1.task("proxy-upgrades", "Proxy implementation changes")
.addParam("asset", "Token symbol of main or feeder pool asset. eg mUSD, mBTC, fpmBTC/HBTC or fpmUSD/GUSD", undefined, config_1.types.string, false)
.addOptionalParam("from", "Block to query transaction events from. (default: deployment block)", 10148031, config_1.types.int)
.addOptionalParam("to", "Block to query transaction events to. (default: current block)", 0, config_1.types.int)
.setAction(async (taskArgs, { ethers }) => {
const asset = tokens_1.tokens.find((t) => t.symbol === taskArgs.asset);
if (!asset) {
console.error(`Failed to find main or feeder pool asset with token symbol ${taskArgs.asset}`);
process.exit(1);
}
const signer = await defender_utils_1.getSigner(ethers);
const { fromBlock, toBlock } = await snap_utils_1.getBlockRange(ethers, taskArgs.from, taskArgs.to);
const proxy = generated_1.AssetProxy__factory.connect(asset.address, signer);
const filter = await proxy.filters.Upgraded();
const logs = await proxy.queryFilter(filter, fromBlock.blockNumber, toBlock.blockNumber);
console.log(`${asset.symbol} proxy ${asset.address}`);
logs.forEach((log) => {
console.log(`Upgraded at block ${log.blockNumber} to ${log.args.implementation}`);
});
});
config_1.task("vault-stake", "Stake into a vault")
.addParam("asset", "Symbol of the asset that has a mStable vault. eg mUSD, alUSD, MTA", undefined, config_1.types.string)
.addParam("amount", "Amount to be staked", undefined, config_1.types.int)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", config_1.types.string)
.setAction(async (taskArgs, { ethers, network }) => {
const chain = networkAddressFactory_1.getChain(network.name);
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const signerAddress = await signer.getAddress();
const assetSymbol = taskArgs.asset;
const assetToken = tokens_1.tokens.find((t) => t.symbol === assetSymbol && t.chain === chain);
if (!assetToken)
throw Error(`Could not find asset with symbol ${assetSymbol}`);
if (!assetToken.vault)
throw Error(`No vault is configured for asset ${assetSymbol}`);
const vault = generated_1.StakingRewards__factory.connect(assetToken.vault, signer);
const amount = math_1.simpleToExactAmount(taskArgs.amount);
const tx = await vault["stake(uint256)"](amount);
await deploy_utils_1.logTxDetails(tx, `${signerAddress} stakes ${amount} ${assetSymbol} in vault`);
});
config_1.task("vault-withdraw", "Withdraw from a vault")
.addParam("asset", "Symbol of the asset that has a mStable vault. eg mUSD, alUSD, MTA", undefined, config_1.types.string)
.addParam("amount", "Amount to be withdrawn", undefined, config_1.types.int)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", config_1.types.string)
.setAction(async (taskArgs, { ethers, network }) => {
const chain = networkAddressFactory_1.getChain(network.name);
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const signerAddress = await signer.getAddress();
const assetSymbol = taskArgs.asset;
const assetToken = tokens_1.tokens.find((t) => t.symbol === assetSymbol && t.chain === chain);
if (!assetToken)
throw Error(`Could not find asset with symbol ${assetSymbol}`);
if (!assetToken.vault)
throw Error(`No vault is configured for asset ${assetSymbol}`);
const vault = generated_1.StakingRewards__factory.connect(assetToken.vault, signer);
const amount = math_1.simpleToExactAmount(taskArgs.amount);
const tx = await vault.withdraw(amount);
await deploy_utils_1.logTxDetails(tx, `${signerAddress} withdraw ${amount} ${assetSymbol} from vault`);
});
config_1.task("vault-exit", "Exit from vault claiming rewards")
.addParam("asset", "Symbol of the asset that has a mStable vault. eg mUSD, alUSD, MTA", undefined, config_1.types.string)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", config_1.types.string)
.setAction(async (taskArgs, { ethers, network }) => {
const chain = networkAddressFactory_1.getChain(network.name);
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const signerAddress = await signer.getAddress();
const assetSymbol = taskArgs.asset;
const assetToken = tokens_1.tokens.find((t) => t.symbol === assetSymbol && t.chain === chain);
if (!assetToken)
throw Error(`Could not find asset with symbol ${assetSymbol}`);
if (!assetToken.vault)
throw Error(`No vault is configured for asset ${assetSymbol}`);
const vault = generated_1.StakingRewards__factory.connect(assetToken.vault, signer);
const tx = await vault.exit();
await deploy_utils_1.logTxDetails(tx, `${signerAddress} exits ${assetSymbol} vault`);
});
config_1.task("vault-claim", "Claim rewards from vault")
.addParam("asset", "Symbol of the asset that has a mStable vault. eg mUSD, alUSD, MTA", undefined, config_1.types.string)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", config_1.types.string)
.setAction(async (taskArgs, { ethers, network }) => {
const chain = networkAddressFactory_1.getChain(network.name);
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const signerAddress = await signer.getAddress();
const assetSymbol = taskArgs.asset;
const assetToken = tokens_1.tokens.find((t) => t.symbol === assetSymbol && t.chain === chain);
if (!assetToken)
throw Error(`Could not find asset with symbol ${assetSymbol}`);
if (!assetToken.vault)
throw Error(`No vault is configured for asset ${assetSymbol}`);
const vault = generated_1.StakingRewards__factory.connect(assetToken.vault, signer);
const tx = await vault.claimReward();
await deploy_utils_1.logTxDetails(tx, `${signerAddress} claim rewards from ${assetSymbol} vault`);
});
config_1.task("approve", "Approve account to transfer token from the Defender Relay account")
.addParam("asset", "Symbol of the asset being approved. eg mUSD, imUSD, PmUSD, GUSD, alUSD, MTA", undefined, config_1.types.string)
// TODO support the account being a contract name
.addParam("account", "Address of the account that is approved to transferFrom", undefined, config_1.types.string)
.addOptionalParam("tokenType", "Token address, savings, vault or feederPool.", "address", config_1.types.string)
.addOptionalParam("amount", "Amount to approve. Default is max unit128", undefined, config_1.types.int)
.addOptionalParam("speed", "Defender Relayer speed param: 'safeLow' | 'average' | 'fast' | 'fastest'", "fast", config_1.types.string)
.setAction(async (taskArgs, { ethers, network }) => {
const chain = networkAddressFactory_1.getChain(network.name);
const signer = await defender_utils_1.getSigner(ethers, taskArgs.speed);
const signerAddress = await signer.getAddress();
const assetSymbol = taskArgs.asset;
const assetToken = tokens_1.tokens.find((t) => t.symbol === assetSymbol && t.chain === chain);
if (!assetToken)
throw Error(`Could not find asset with symbol ${assetSymbol}`);
const approveAccount = taskArgs.account;
// TODO validate address using a regex
if (!approveAccount)
throw Error(`Invalid approve address ${approveAccount}`);
const { tokenType } = taskArgs;
if (!assetToken[tokenType])
throw Error(`Can not fine ${tokenType} for token ${assetSymbol}`);
const token = generated_1.ERC20__factory.connect(assetToken[tokenType], signer);
const amount = taskArgs.amount ? math_1.simpleToExactAmount(taskArgs.amount) : constants_1.MAX_INT128;
const tx = await token.approve(approveAccount, amount);
await deploy_utils_1.logTxDetails(tx, `${signerAddress} approves ${approveAccount} to transfer ${utils_1.formatUnits(amount)} ${assetSymbol}`);
});
module.exports = {};
//# sourceMappingURL=ops.js.map