Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VEN-1474]: Harvest BNB Income #289

Merged
merged 48 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
87790de
feat: vBNBAdmin contract created
web3rover Jun 16, 2023
88f5adf
feat: tests for VBNBAdmin
web3rover Jun 16, 2023
0ea1ed1
fix: fixed recieve due to 23000 gas limit
web3rover Jun 18, 2023
d8b1c9c
feat: added fork tests
web3rover Jun 19, 2023
2866fd6
chore: added netspec
web3rover Jun 19, 2023
8b55821
fix: removed console.log
web3rover Jun 20, 2023
197f4c7
chore: update netspec
web3rover Jul 6, 2023
04ea03f
feat: add setter for PSR
web3rover Jul 6, 2023
fd7c9a0
Merge branch 'feat/harvest-bnb-income' of github.com:VenusProtocol/ve…
web3rover Jul 6, 2023
9bd845f
fix: remove ownable init
web3rover Jul 10, 2023
43fd668
fix: get comptroller from vBNB
web3rover Jul 10, 2023
7f54165
fix: remove Ownable2StepUpgradeable
web3rover Jul 26, 2023
6e21a37
fix: add ReservesReduced event
web3rover Jul 26, 2023
511d66c
fix: changed storage gap
web3rover Jul 26, 2023
25d45cb
chore: fix error message
web3rover Jul 27, 2023
8e63e9a
fix: remove unwanted import
web3rover Jul 27, 2023
74d03cc
fix: only timelock can invoke reduce reserves
web3rover Aug 7, 2023
3a0afdb
chore: naming consistency
web3rover Aug 7, 2023
08cd99c
revert: "fix: only timelock can invoke reduce reserves"
web3rover Aug 7, 2023
bc6fd4e
fix: VBB-01
web3rover Aug 22, 2023
c2656c6
fix: VPI-01
web3rover Aug 22, 2023
04d5e1c
fix: VBN-02
web3rover Aug 23, 2023
61afb57
chore: fixed lint
web3rover Aug 24, 2023
1992f80
fix: optimise gas when setting PSR
web3rover Aug 24, 2023
52f8efd
fix: use onlyowner
web3rover Aug 25, 2023
b11d297
fix: remove acceptVBNBAdmin
web3rover Aug 25, 2023
348955d
refactor: VPI-02 use onlyOwner instead of require
chechu Aug 29, 2023
df315ff
fix: trigger ci
web3rover Oct 5, 2023
1e309af
chore: resolved conflict
web3rover Oct 5, 2023
a8450bc
fix: deployment for testnet
web3rover Oct 5, 2023
dacce20
fix: updated proxy address
web3rover Oct 6, 2023
a237adc
fix: mainnet deployment
web3rover Oct 6, 2023
e9dfd67
chore: fixed lint
web3rover Oct 6, 2023
831222d
fix: redeployed contracts
web3rover Oct 6, 2023
86677d4
fix: redeploy with correct PSR and Admin proxy
web3rover Oct 11, 2023
4e4dcbc
fix: revert mainnet url
web3rover Oct 11, 2023
9a5ea84
fix: added old mainnet proxy admin
web3rover Oct 12, 2023
dc3cc54
chore: fix lint
web3rover Oct 12, 2023
f832640
fix: fix yarn.lock
web3rover Oct 12, 2023
8a27466
fix: remove @nomiclabs/hardhat-ethers
web3rover Oct 12, 2023
8039d2c
fix: redeployed mainnet contracts
web3rover Oct 13, 2023
a1aaa20
fix: redeployed mainnet contracts
web3rover Oct 16, 2023
b672d29
docs: add natspec comments to VBNBAdmin contract
chechu Oct 19, 2023
9e223f1
fix: revert config changes
web3rover Oct 19, 2023
cac6b1c
fix: resolved conflict
web3rover Oct 19, 2023
67a3ac8
fix: fixed tests
web3rover Oct 19, 2023
ebe0b54
chore: fixed lint
web3rover Oct 19, 2023
65e79e5
fix: fixed tests
web3rover Oct 19, 2023
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
119 changes: 119 additions & 0 deletions contracts/Admin/VBNBAdmin.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// SPDX-License-Identifier: BSD-3-Clause

pragma solidity 0.8.13;
chechu marked this conversation as resolved.
Show resolved Hide resolved

import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol";
import "./VBNBAdminStorage.sol";

/**
* @title VBNBAdmin
* @author Venus
* @notice This contract is the "admin" of the vBNB market, reducing the reserves of the market, sending them to the `ProtocolShareReserve` contract,
* and allowing the executions of the rest of the privileged functions in the vBNB contract (after checking if the sender has the required permissions).
*/
contract VBNBAdmin is ReentrancyGuardUpgradeable, AccessControlledV8, VBNBAdminStorage {
using SafeERC20Upgradeable for IWBNB;

/// @notice address of vBNB
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
VTokenInterface public immutable vBNB;

/// @notice address of WBNB contract
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
IWBNB public immutable WBNB;

/// @notice Emitted when PSR is updated
event ProtocolShareReserveUpdated(
IProtocolShareReserve indexed oldProtocolShareReserve,
IProtocolShareReserve indexed newProtocolShareReserve
);

/// @notice Emitted reserves are reduced
event ReservesReduced(uint256 reduceAmount);

/// @param _vBNB Address of the vBNB contract
/// @param _WBNB Address of the WBNB token
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(VTokenInterface _vBNB, IWBNB _WBNB) {
require(address(_WBNB) != address(0), "WBNB address invalid");
require(address(_vBNB) != address(0), "vBNB address invalid");

vBNB = _vBNB;
WBNB = _WBNB;

// Note that the contract is upgradeable. Use initialize() or reinitializers
// to set the state variables.
_disableInitializers();
}

/// @notice Used to initialize non-immutable variables
function initialize(
IProtocolShareReserve _protocolShareReserve,
address accessControlManager
) external initializer {
require(address(_protocolShareReserve) != address(0), "PSR address invalid");
protocolShareReserve = _protocolShareReserve;

__ReentrancyGuard_init();
__AccessControlled_init(accessControlManager);
}

/**
* @notice PSR setter.
* @param protocolShareReserve_ Address of the PSR contract
* @custom:access Only owner (Governance)
* @custom:event Emits ProtocolShareReserveUpdated event.
*/
function setProtocolShareReserve(IProtocolShareReserve protocolShareReserve_) external onlyOwner {
require(address(protocolShareReserve_) != address(0), "PSR address invalid");
emit ProtocolShareReserveUpdated(protocolShareReserve, protocolShareReserve_);
protocolShareReserve = protocolShareReserve_;
}

/**
* @notice Reduce reserves of vBNB, wrap them and send them to the PSR contract
* @param reduceAmount amount of reserves to reduce
* @custom:event Emits ReservesReduced event.
*/
function reduceReserves(uint reduceAmount) external nonReentrant {
web3rover marked this conversation as resolved.
Show resolved Hide resolved
require(vBNB._reduceReserves(reduceAmount) == 0, "reduceReserves failed");
_wrapBNB();

uint256 balance = WBNB.balanceOf(address(this));
WBNB.safeTransfer(address(protocolShareReserve), balance);
protocolShareReserve.updateAssetsState(
vBNB.comptroller(),
address(WBNB),
IProtocolShareReserve.IncomeType.SPREAD
);

emit ReservesReduced(reduceAmount);
}

/**
* @notice Wraps BNB into WBNB
*/
function _wrapBNB() internal {
uint256 bnbBalance = address(this).balance;
WBNB.deposit{ value: bnbBalance }();
}

/**
* @notice Invoked when BNB is sent to this contract
* @custom:access Only vBNB is considered a valid sender
*/
receive() external payable {
require(msg.sender == address(vBNB), "only vBNB can send BNB to this contract");
web3rover marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @notice Invoked when called function does not exist in the contract. The function will be executed in the vBNB contract.
* @custom:access Only owner (Governance)
*/
fallback(bytes calldata data) external payable onlyOwner returns (bytes memory) {
(bool ok, bytes memory res) = address(vBNB).call{ value: msg.value }(data);
require(ok, "call failed");
return res;
}
}
33 changes: 33 additions & 0 deletions contracts/Admin/VBNBAdminStorage.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.13;

import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";

interface VTokenInterface {
function _reduceReserves(uint reduceAmount) external returns (uint);

function _acceptAdmin() external returns (uint);

function comptroller() external returns (address);
}

interface IWBNB is IERC20Upgradeable {
function deposit() external payable;
}

interface IProtocolShareReserve {
enum IncomeType {
SPREAD,
LIQUIDATION
}

function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;
}

contract VBNBAdminStorage {
/// @notice address of protocol share reserve contract
IProtocolShareReserve public protocolShareReserve;
chechu marked this conversation as resolved.
Show resolved Hide resolved

/// @dev gap to prevent collision in inheritence
uint256[49] private __gap;
}
4 changes: 4 additions & 0 deletions contracts/test/MockVBNB.sol
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ contract MockVBNB is VToken {
requireNoError(err, "liquidateBorrow failed");
}

function setTotalReserves(uint totalReserves_) external payable {
totalReserves = totalReserves_;
}

/*** Safe Token ***/

/**
Expand Down
67 changes: 67 additions & 0 deletions deploy/007-deploy-VBNBAdmin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { ethers } from "hardhat";
import { Address, DeployFunction } from "hardhat-deploy/types";
import { HardhatRuntimeEnvironment } from "hardhat/types";

import { Contracts as Mainnet } from "../networks/mainnet.json";
import { Contracts as Testnet } from "../networks/testnet.json";

interface AddressConfig {
[key: string]: {
[key: string]: Address;
};
}

const ADDRESSES: AddressConfig = {
bsctestnet: Testnet,
bscmainnet: Mainnet,
};

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, network, getNamedAccounts } = hre;
const { deploy } = deployments;
const { deployer } = await getNamedAccounts();

const networkName = network.name === "bscmainnet" ? "bscmainnet" : "bsctestnet";
const vBNB = ADDRESSES[networkName].vBNB;
const WBNB = ADDRESSES[networkName].WBNB;

const acmAddresses: { [network: string]: string } = {
bsctestnet: "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA",
bscmainnet: "0x4788629ABc6cFCA10F9f969efdEAa1cF70c23555",
};

const protocolShareReserve: { [network: string]: string } = {
bsctestnet: "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E3",
bscmainnet: "0xCa01D5A9A248a830E9D93231e791B1afFed7c446",
};

await deploy("VBNBAdmin", {
contract: "VBNBAdmin",
from: deployer,
args: [vBNB, WBNB],
log: true,
autoMine: true,
proxy: {
owner: ADDRESSES[networkName].Timelock,
proxyContract: "OpenZeppelinTransparentProxy",
execute: {
methodName: "initialize",
args: [protocolShareReserve[networkName], acmAddresses[networkName]],
},
},
});

const vBNBAdmin = await ethers.getContract("VBNBAdmin");

if (network.name !== "hardhat") {
const timelockAddress = ADDRESSES[networkName].Timelock;
await vBNBAdmin.transferOwnership(timelockAddress);
console.log(`VBNBAdmin Contract (${vBNBAdmin.address}) owner changed from ${deployer} to ${timelockAddress}`);
}
return hre.network.live; // when live network, record the script as executed to prevent rexecution
};

func.id = "vbnbadmin_deploy"; // id required to prevent re-execution
func.tags = ["VBNBAdmin"];

export default func;
3 changes: 2 additions & 1 deletion deployments/bscmainnet/.migrations.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"psm_initial_deploy": 1690981284
"psm_initial_deploy": 1690981284,
"vbnbadmin_deploy": 1697477430
}
32 changes: 16 additions & 16 deletions deployments/bscmainnet/DefaultProxyAdmin.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"address": "0x3f918bA9446552AB184C6Ffd2e2fcB1FA5ee1e59",
"address": "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4",
"abi": [
{
"inputs": [
Expand Down Expand Up @@ -162,34 +162,34 @@
"type": "function"
}
],
"transactionHash": "0xad7e189b2375d6cd981880ad905006abb531d2935b9ea5ce1cb3bab65146ba37",
"transactionHash": "0xad6ac5a87976826e994ec930ab979ae330345d828e1ee6926635ce11eb645e95",
"receipt": {
"to": null,
"from": "0xa05f990d647287e4E84715b813BC000aEA970467",
"contractAddress": "0x3f918bA9446552AB184C6Ffd2e2fcB1FA5ee1e59",
"transactionIndex": 45,
"from": "0x55A9f5374Af30E3045FB491f1da3C2E8a74d168D",
"contractAddress": "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4",
"transactionIndex": 51,
"gasUsed": "642683",
"logsBloom": "0x00000000000000000000000000000000000001000000000000800000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000220000000000000000000800000002000000000000000000000000400000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000000000000000000000000000",
"blockHash": "0xbf164b826398a95757702f2951b8422f1023875f8f7e46d2aaf1bcd2fe26cb01",
"transactionHash": "0xad7e189b2375d6cd981880ad905006abb531d2935b9ea5ce1cb3bab65146ba37",
"logsBloom": "0x00000000000000000000000000000000000001000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000002000008000000000000000000400000000000000000000000000000000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000010000000000000000000000000000",
"blockHash": "0xf8f6cb1dd8c033affe5227c67647ff04ec6524b3d512cdff2c571504d79b4a6b",
"transactionHash": "0xad6ac5a87976826e994ec930ab979ae330345d828e1ee6926635ce11eb645e95",
"logs": [
{
"transactionIndex": 45,
"blockNumber": 29298107,
"transactionHash": "0xad7e189b2375d6cd981880ad905006abb531d2935b9ea5ce1cb3bab65146ba37",
"address": "0x3f918bA9446552AB184C6Ffd2e2fcB1FA5ee1e59",
"transactionIndex": 51,
"blockNumber": 29334996,
"transactionHash": "0xad6ac5a87976826e994ec930ab979ae330345d828e1ee6926635ce11eb645e95",
"address": "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4",
"topics": [
"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab6396"
],
"data": "0x",
"logIndex": 84,
"blockHash": "0xbf164b826398a95757702f2951b8422f1023875f8f7e46d2aaf1bcd2fe26cb01"
"logIndex": 92,
"blockHash": "0xf8f6cb1dd8c033affe5227c67647ff04ec6524b3d512cdff2c571504d79b4a6b"
}
],
"blockNumber": 29298107,
"cumulativeGasUsed": "4279153",
"blockNumber": 29334996,
"cumulativeGasUsed": "4717348",
"status": 1,
"byzantium": true
},
Expand Down
Loading
Loading