diff --git a/simulations/vip-183/abi/IERC20UpgradableAbi.json b/simulations/vip-183/abi/IERC20UpgradableAbi.json new file mode 100644 index 000000000..374b04c75 --- /dev/null +++ b/simulations/vip-183/abi/IERC20UpgradableAbi.json @@ -0,0 +1,295 @@ +[ + { + "inputs": [ + { "internalType": "string", "name": "name_", "type": "string" }, + { "internalType": "string", "name": "symbol_", "type": "string" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "userAddress", "type": "address" }, + { "indexed": false, "internalType": "address payable", "name": "relayerAddress", "type": "address" }, + { "indexed": false, "internalType": "bytes", "name": "functionSignature", "type": "bytes" } + ], + "name": "MetaTransactionExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "indexed": true, "internalType": "bytes32", "name": "previousAdminRole", "type": "bytes32" }, + { "indexed": true, "internalType": "bytes32", "name": "newAdminRole", "type": "bytes32" } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "indexed": true, "internalType": "address", "name": "account", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "sender", "type": "address" } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "indexed": true, "internalType": "address", "name": "account", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "sender", "type": "address" } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERC712_VERSION", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREDICATE_ROLE", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "subtractedValue", "type": "uint256" } + ], + "name": "decreaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "userAddress", "type": "address" }, + { "internalType": "bytes", "name": "functionSignature", "type": "bytes" }, + { "internalType": "bytes32", "name": "sigR", "type": "bytes32" }, + { "internalType": "bytes32", "name": "sigS", "type": "bytes32" }, + { "internalType": "uint8", "name": "sigV", "type": "uint8" } + ], + "name": "executeMetaTransaction", + "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "getChainId", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getDomainSeperator", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "user", "type": "address" }], + "name": "getNonce", + "outputs": [{ "internalType": "uint256", "name": "nonce", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes32", "name": "role", "type": "bytes32" }], + "name": "getRoleAdmin", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "uint256", "name": "index", "type": "uint256" } + ], + "name": "getRoleMember", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes32", "name": "role", "type": "bytes32" }], + "name": "getRoleMemberCount", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "hasRole", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "addedValue", "type": "uint256" } + ], + "name": "increaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "user", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "role", "type": "bytes32" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "sender", "type": "address" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-183/simulations.ts b/simulations/vip-183/simulations.ts new file mode 100644 index 000000000..38e35eed4 --- /dev/null +++ b/simulations/vip-183/simulations.ts @@ -0,0 +1,292 @@ +import { expect } from "chai"; +import { BigNumber } from "ethers"; +import { parseEther, parseUnits } from "ethers/lib/utils"; +import { ethers } from "hardhat"; + +import { forking, testVip } from "../../src/vip-framework"; +import { vip183 } from "../../vips/vip-183"; +import IERC20 from "./abi/IERC20UpgradableAbi.json"; + +const BUYBACK_WALLET = "0x6657911F7411765979Da0794840D671Be55bA273"; +const TREASURY = "0xF322942f644A996A617BD29c16bd7d231d9F35E9"; + +const USDT_TREASURY_SHARE = parseUnits("166002.633177563169056472", 18); +const USDT_BUYBACK_SHARE = parseUnits("18444.737019729241006274", 18); +const LIQUIDATIONS_USDT_BUYBACK = parseUnits("22793.63", 18); + +const USDT_BUYBACK_WALLET_DELTA = USDT_BUYBACK_SHARE.add(LIQUIDATIONS_USDT_BUYBACK); +const USDT_TREASURY_DELTA = USDT_TREASURY_SHARE.sub(LIQUIDATIONS_USDT_BUYBACK); + +const EXPECTED_BUYBACK_WALLET_DELTAS = [ + { symbol: "BNB", token: "0x0", expectedDelta: parseEther("601.182823510592987636") }, + { + symbol: "USDC", + token: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", + expectedDelta: parseUnits("9849.892678925547383615", 18), + }, + { symbol: "USDT", token: "0x55d398326f99059fF775485246999027B3197955", expectedDelta: USDT_BUYBACK_WALLET_DELTA }, + { + symbol: "BUSD", + token: "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56", + expectedDelta: parseUnits("0", 18), + }, + { + symbol: "SXP", + token: "0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A", + expectedDelta: parseUnits("893.459209473801674349", 18), + }, + { + symbol: "BTCB", + token: "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c", + expectedDelta: parseUnits("0.156117301714591397", 18), + }, + { + symbol: "ETH", + token: "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", + expectedDelta: parseUnits("4.0252435119110084050", 18), + }, + { + symbol: "LTC", + token: "0x4338665CBB7B2485A8855A139b75D5e34AB0DB94", + expectedDelta: parseUnits("0.718882603181826473", 18), + }, + { + symbol: "XRP", + token: "0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE", + expectedDelta: parseUnits("95.402950261235556118", 18), + }, + { + symbol: "BCH", + token: "0x8fF795a6F4D97E7887C79beA79aba5cc76444aDf", + expectedDelta: parseUnits("1.3399846260516787700", 18), + }, + { + symbol: "DOT", + token: "0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402", + expectedDelta: parseUnits("120.313518932470783189", 18), + }, + { + symbol: "LINK", + token: "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD", + expectedDelta: parseUnits("5.053638935414816654", 18), + }, + { + symbol: "DAI", + token: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3", + expectedDelta: parseUnits("584.635968797372328176", 18), + }, + { + symbol: "FIL", + token: "0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153", + expectedDelta: parseUnits("9.983630213346555867", 18), + }, + { + symbol: "BETH", + token: "0x250632378E573c6Be1AC2f97Fcdf00515d0Aa91B", + expectedDelta: parseUnits("0.000367437792277355", 18), + }, + { + symbol: "ADA", + token: "0x3EE2200Efb3400fAbB9AacF31297cBdD1d435D47", + expectedDelta: parseUnits("813.848060964751798590", 18), + }, + { + symbol: "DOGE", + token: "0xbA2aE424d960c26247Dd6c32edC70B295c744C43", + expectedDelta: parseUnits("325.21377918", 8), + }, + { + symbol: "MATIC", + token: "0xCC42724C6683B7E57334c4E856f4c9965ED682bD", + expectedDelta: parseUnits("110.139757401443688148", 18), + }, + { + symbol: "Cake", + token: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82", + expectedDelta: parseUnits("561.881225811358897070", 18), + }, + { + symbol: "AAVE", + token: "0xfb6115445Bff7b52FeB98650C87f44907E58f802", + expectedDelta: parseUnits("0.311130908263443924", 18), + }, + { + symbol: "TRXOLD", + token: "0x85EAC5Ac2F758618dFa09bDbe0cf174e7d574D5B", + expectedDelta: parseUnits("1486.623013103118100397", 18), + }, + { + symbol: "TRX", + token: "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3", + expectedDelta: parseUnits("1271.900699", 6), + }, + { + symbol: "wBETH", + token: "0xa2E3356610840701BDf5611a53974510Ae27E2e1", + expectedDelta: parseUnits("0.040631499467635465", 18), + }, + { + symbol: "TUSD", + token: "0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9", + expectedDelta: parseUnits("218.043441287091666248", 18), + }, +]; + +const EXPECTED_TREASURY_DELTAS = [ + { symbol: "BNB", token: "0x0", expectedDelta: parseEther("5410.645411595336888731") }, + { + symbol: "USDC", + token: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", + expectedDelta: parseUnits("88649.034110329926452542", 18), + }, + { symbol: "USDT", token: "0x55d398326f99059fF775485246999027B3197955", expectedDelta: USDT_TREASURY_DELTA }, + { + symbol: "BUSD", + token: "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56", + expectedDelta: parseUnits("0", 18), + }, + { + symbol: "SXP", + token: "0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A", + expectedDelta: parseUnits("8041.132885264215069142", 18), + }, + { + symbol: "BTCB", + token: "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c", + expectedDelta: parseUnits("1.405055715431322576", 18), + }, + { + symbol: "ETH", + token: "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", + expectedDelta: parseUnits("36.227191607199075645", 18), + }, + { + symbol: "LTC", + token: "0x4338665CBB7B2485A8855A139b75D5e34AB0DB94", + expectedDelta: parseUnits("6.469943428636438264", 18), + }, + { + symbol: "XRP", + token: "0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE", + expectedDelta: parseUnits("858.626552351120005070", 18), + }, + { + symbol: "BCH", + token: "0x8fF795a6F4D97E7887C79beA79aba5cc76444aDf", + expectedDelta: parseUnits("12.059861634465108930", 18), + }, + { + symbol: "DOT", + token: "0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402", + expectedDelta: parseUnits("1082.821670392237048709", 18), + }, + { + symbol: "LINK", + token: "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD", + expectedDelta: parseUnits("45.482750418733349894", 18), + }, + { + symbol: "DAI", + token: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3", + expectedDelta: parseUnits("5261.723719176350953593", 18), + }, + { + symbol: "FIL", + token: "0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153", + expectedDelta: parseUnits("89.852671920119002804", 18), + }, + { + symbol: "BETH", + token: "0x250632378E573c6Be1AC2f97Fcdf00515d0Aa91B", + expectedDelta: parseUnits("0.003306940130496201", 18), + }, + { + symbol: "ADA", + token: "0x3EE2200Efb3400fAbB9AacF31297cBdD1d435D47", + expectedDelta: parseUnits("7324.632548682766187312", 18), + }, + { + symbol: "DOGE", + token: "0xbA2aE424d960c26247Dd6c32edC70B295c744C43", + expectedDelta: parseUnits("2926.92401269", 8), + }, + { + symbol: "MATIC", + token: "0xCC42724C6683B7E57334c4E856f4c9965ED682bD", + expectedDelta: parseUnits("991.257816612993193333", 18), + }, + { + symbol: "Cake", + token: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82", + expectedDelta: parseUnits("5056.931032302230073636", 18), + }, + { + symbol: "AAVE", + token: "0xfb6115445Bff7b52FeB98650C87f44907E58f802", + expectedDelta: parseUnits("2.800178174370995318", 18), + }, + { + symbol: "TRXOLD", + token: "0x85EAC5Ac2F758618dFa09bDbe0cf174e7d574D5B", + expectedDelta: parseUnits("13379.607117928062903581", 18), + }, + { + symbol: "TRX", + token: "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3", + expectedDelta: parseUnits("11447.106298", 6), + }, + { + symbol: "wBETH", + token: "0xa2E3356610840701BDf5611a53974510Ae27E2e1", + expectedDelta: parseUnits("0.365683495208719188", 18), + }, + { + symbol: "TUSD", + token: "0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9", + expectedDelta: parseUnits("1962.390971583824996239", 18), + }, +]; + +const balanceOf = async (token: string, address: string) => { + if (token === "0x0") { + return await ethers.provider.getBalance(address); + } + const tokenContract = await ethers.getContractAt(IERC20, token); + return await tokenContract.balanceOf(address); +}; + +forking(32364940, () => { + const originalTreasuryBalances: { [address: string]: BigNumber } = {}; + const originalBuybackWalletBalances: { [address: string]: BigNumber } = {}; + + before(async () => { + EXPECTED_TREASURY_DELTAS.forEach(async ({ token }) => { + originalTreasuryBalances[token] = await balanceOf(token, TREASURY); + }); + EXPECTED_BUYBACK_WALLET_DELTAS.forEach(async ({ token }) => { + originalBuybackWalletBalances[token] = await balanceOf(token, BUYBACK_WALLET); + }); + }); + + testVip("VIP-182", vip183(), { + proposer: "0x97a32d4506f6a35de68e0680859cdf41d077a9a9", + }); + + describe("Post-VIP balances", async () => { + EXPECTED_TREASURY_DELTAS.forEach(({ symbol, token, expectedDelta }) => { + it(`should have the correct balance for ${symbol} in treasury`, async () => { + const balance = await balanceOf(token, TREASURY); + const expectedBalance = expectedDelta.add(originalTreasuryBalances[token]); + expect(balance).to.equal(expectedBalance); + }); + }); + + EXPECTED_BUYBACK_WALLET_DELTAS.forEach(({ symbol, token, expectedDelta }) => { + it(`should have the correct balance for ${symbol} in buyback wallet`, async () => { + const balance = await balanceOf(token, BUYBACK_WALLET); + const expectedBalance = expectedDelta.add(originalBuybackWalletBalances[token]); + expect(balance).to.equal(expectedBalance); + }); + }); + }); +}); diff --git a/vips/vip-183.ts b/vips/vip-183.ts new file mode 100644 index 000000000..766848725 --- /dev/null +++ b/vips/vip-183.ts @@ -0,0 +1,292 @@ +import { parseUnits } from "@ethersproject/units"; +import { BigNumber, BigNumberish } from "ethers"; + +import { Command, ProposalType } from "../src/types"; +import { makeProposal } from "../src/utils"; + +const BUYBACK_WALLET = "0x6657911F7411765979Da0794840D671Be55bA273"; +const TREASURY = "0xF322942f644A996A617BD29c16bd7d231d9F35E9"; + +const USDT = "0x55d398326f99059fF775485246999027B3197955"; +const USDT_FOR_BUYBACK = parseUnits("22793.63", 18); +const PERCENT_OF_RESERVES_FOR_BUYBACK = "10"; // % + +interface ReservesRecord { + vToken: string; + underlying: string; + reservesMantissa: BigNumberish; +} + +// All vTokens except: +// * vXVS (the amount is too small) +// * vCAN, vLUNA, vUST (all three are deprecated), +// * vBUSD (the reserves for this token will be used to repay the shortfall), +// * vTUSDOLD (not enough liquidity) +// * IL pool assets +// Snapshot taken at block 32208206 (2023-09-30 23:59:59 UTC) +const RESERVES = [ + { + vToken: "0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8", + underlying: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", + reservesMantissa: "98498926789255473836157", + }, + { + vToken: "0xfD5840Cd36d94D7229439859C0112a4185BC0255", + underlying: "0x55d398326f99059fF775485246999027B3197955", + reservesMantissa: "184447370197292410062746", + }, + { + vToken: "0x2fF3d0F6990a40261c66E1ff2017aCBc282EB6d0", + underlying: "0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A", + reservesMantissa: "8934592094738016743491", + }, + { + vToken: "0xA07c5b74C9B40447a954e1466938b865b6BBea36", + underlying: "0x0", + reservesMantissa: "6011828235105929876367", + }, + { + vToken: "0x882C173bC7Ff3b7786CA16dfeD3DFFfb9Ee7847B", + underlying: "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c", + reservesMantissa: "1561173017145913973", + }, + { + vToken: "0xf508fCD89b8bd15579dc79A6827cB4686A3592c8", + underlying: "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", + reservesMantissa: "40252435119110084050", + }, + { + vToken: "0x57A5297F2cB2c0AaC9D554660acd6D385Ab50c6B", + underlying: "0x4338665CBB7B2485A8855A139b75D5e34AB0DB94", + reservesMantissa: "7188826031818264737", + }, + { + vToken: "0xB248a295732e0225acd3337607cc01068e3b9c10", + underlying: "0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE", + reservesMantissa: "954029502612355561188", + }, + { + vToken: "0x5F0388EBc2B94FA8E123F404b79cCF5f40b29176", + underlying: "0x8fF795a6F4D97E7887C79beA79aba5cc76444aDf", + reservesMantissa: "13399846260516787700", + }, + { + vToken: "0x1610bc33319e9398de5f57B33a5b184c806aD217", + underlying: "0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402", + reservesMantissa: "1203135189324707831898", + }, + { + vToken: "0x650b940a1033B8A1b1873f78730FcFC73ec11f1f", + underlying: "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD", + reservesMantissa: "50536389354148166548", + }, + { + vToken: "0x334b3eCB4DCa3593BCCC3c7EBD1A1C1d1780FBF1", + underlying: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3", + reservesMantissa: "5846359687973723281769", + }, + { + vToken: "0xf91d58b5aE142DAcC749f58A49FCBac340Cb0343", + underlying: "0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153", + reservesMantissa: "99836302133465558671", + }, + { + vToken: "0x972207A639CC1B374B893cc33Fa251b55CEB7c07", + underlying: "0x250632378E573c6Be1AC2f97Fcdf00515d0Aa91B", + reservesMantissa: "3674377922773556", + }, + { + vToken: "0x9A0AF7FDb2065Ce470D72664DE73cAE409dA28Ec", + underlying: "0x3EE2200Efb3400fAbB9AacF31297cBdD1d435D47", + reservesMantissa: "8138480609647517985902", + }, + { + vToken: "0xec3422Ef92B2fb59e84c8B02Ba73F1fE84Ed8D71", + underlying: "0xbA2aE424d960c26247Dd6c32edC70B295c744C43", + reservesMantissa: "325213779187", + }, + { + vToken: "0x5c9476FcD6a4F9a3654139721c949c2233bBbBc8", + underlying: "0xCC42724C6683B7E57334c4E856f4c9965ED682bD", + reservesMantissa: "1101397574014436881481", + }, + { + vToken: "0x86aC3974e2BD0d60825230fa6F355fF11409df5c", + underlying: "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82", + reservesMantissa: "5618812258113588970706", + }, + { + vToken: "0x26DA28954763B92139ED49283625ceCAf52C6f94", + underlying: "0xfb6115445Bff7b52FeB98650C87f44907E58f802", + reservesMantissa: "3111309082634439242", + }, + { + vToken: "0x61eDcFe8Dd6bA3c891CB9bEc2dc7657B3B422E93", + underlying: "0x85EAC5Ac2F758618dFa09bDbe0cf174e7d574D5B", + reservesMantissa: "14866230131031181003978", + }, + { + vToken: "0xC5D3466aA484B040eE977073fcF337f2c00071c1", + underlying: "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3", + reservesMantissa: "12719006997", + }, + { + vToken: "0x6CFdEc747f37DAf3b87a35a1D9c8AD3063A1A8A0", + underlying: "0xa2E3356610840701BDf5611a53974510Ae27E2e1", + reservesMantissa: "406314994676354653", + }, + { + vToken: "0xBf762cd5991cA1DCdDaC9ae5C638F5B5Dc3Bee6E", + underlying: "0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9", + reservesMantissa: "2180434412870916662487", + }, +]; + +export const vip183 = () => { + const meta = { + version: "v2", + title: "VIP-183 Quarterly XVS Buyback and Funds Allocation", + description: `#### Description + +VIP-183 relates to the Quarterly Venus Protocol XVS Buyback & Funds allocation as indicated in our Tokenomics. + +#### Specifications + +As per our Tokenomics v.3.1, this VIP will proceed to withdraw funds for our Quarterly Buyback and distributions. The complete details on our latest tokenomics are available here: [Revision of Venus Tokenomics](https://community.venus.io/t/proposal-for-revision-of-venus-protocol-tokenomics/3599) + +Exceptionally for this quarter, we are proposing sending the BNB exploiter liquidation fees to the risk fund to be used towards active shortfalls repayment which will greatly benefit Venus in the long term. + +Due to the depreciation of BUSD and TUSD (OLD), we will not be able to withdraw those reserves as there is no available liquidity. They will be withdrawn at a later date and we can proceed to adjust the distributions then. + +Q3 Revenues Denominated in USD Were as Follows: + +1 Liquidation Fee Revenue: + +- vUSDC: $1,894.17 +- vUSDT: $29,912.92 +- vBUSD: $2,359.87 +- vSXP: $1.19 +- vXVS: $5,226.87 +- vBNB: $23,566.01 +- vBTC: $111,688.80 +- vETH: $27,118.88 +- vLTC: $4,887.78 +- vXRP: $13,857.77 +- vBCH: $166.37 +- vDOT: $1,141.84 +- vLINK: $1,491.03 +- vDAI: $0.76 +- vFIL: $250.98 +- vBETH: $320.29 +- vADA: $413.54 +- vDOGE: $154.68 +- vMATIC: $203.79 +- vCAKE: $2,659.70 +- vAAVE: $206.47 +- vTUSDOLD: $267.97 +- vTRXOLD: $114.49 +- vTRX: $30.11 + +**Total: $227,936.29** + +2 Reserve Revenue: + +- USDC: $98,497.51 +- USDT: $184,479.76 +- SXP: $2,589.48 +- BNB: $1,289,916.01 +- BTCB: $42,098.59 +- ETH: $67,272.47 +- LTC: $474.64 +- XRP: $491.37 +- BCH: $3,141.49 +- DOT: $4,935.95 +- LINK: $413.64 +- DAI: $5,845.55 +- FIL: $334.99 +- BETH: $6.14 +- ADA: $2,066.92 +- DOGE: $201.89 +- MATIC: $587.02 +- Cake: $6,568.77 +- AAVE: $210.09 +- TRXOLD: $1,317.43 +- TRX: $1,127.14 +- wBETH: $690.96 +- TUSD: $2,177.59 + +**Total: $1,715,445.40** + +**Total Protocol Revenues: 1,2 : $1,943,381.69** + +- *Considering USD token prices from October 1, 2023* + +**Estimated buyback values:** + +- $194,338 USD for approximately 38k XVS +- 96K XVS from legacy rewards + +Total: 135k XVS for Vault rewards + +**Estimated Q4 2023 XVS Vault APR: 1480 XVS per day or 8.2% APR**`, + forDescription: "I agree that Venus Protocol should proceed with the Buyback & Tokenomics Distribution", + againstDescription: "I do not think that Venus Protocol should proceed with the Buyback & Tokenomics Distribution", + abstainDescription: + "I am indifferent to whether Venus Protocol proceeds with the Buyback & Tokenomics Distribution", + }; + + const transferBNB = (target: string, amount: BigNumberish): Command => { + return { + target: target, + signature: "", + params: [], + value: amount.toString(), + }; + }; + + const transferTokens = (token: string, target: string, amount: BigNumberish): Command => ({ + target: token, + signature: "transfer(address,uint256)", + params: [target, amount], + }); + + const transfer = (token: string, target: string, amount: BigNumberish): Command => { + if (token === "0x0") { + return transferBNB(target, amount); + } + return transferTokens(token, target, amount); + }; + + return makeProposal( + [ + ...RESERVES.flatMap(({ vToken, underlying, reservesMantissa }: ReservesRecord) => { + const reserve = BigNumber.from(reservesMantissa); + const buybackShare = reserve.mul(PERCENT_OF_RESERVES_FOR_BUYBACK).div(100); + const treasuryShare = reserve.sub(buybackShare); + + console.log(`underlying: ${underlying}`); + console.log(` reserves: ${reservesMantissa}`); + console.log(` buyback: ${buybackShare.toString()}`); + console.log(` treasury: ${treasuryShare.toString()}`); + + return [ + { + target: vToken, + signature: "_reduceReserves(uint256)", + params: [reservesMantissa], + }, + transfer(underlying, BUYBACK_WALLET, buybackShare), + transfer(underlying, TREASURY, treasuryShare), + ]; + }), + + { + target: TREASURY, + signature: "withdrawTreasuryBEP20(address,uint256,address)", + params: [USDT, USDT_FOR_BUYBACK, BUYBACK_WALLET], + }, + ], + meta, + ProposalType.REGULAR, + ); +};