Skip to content

Commit

Permalink
feat: add reward speed by market view
Browse files Browse the repository at this point in the history
  • Loading branch information
coreyar committed Dec 1, 2022
1 parent 3148974 commit 5b639f9
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 2 deletions.
34 changes: 34 additions & 0 deletions contracts/Comptroller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ contract Comptroller is
uint256 shortfall;
}

struct RewardSpeeds {
address rewardToken;
uint256 supplySpeed;
uint256 borrowSpeed;
}

// closeFactorMantissa must be strictly greater than this value
uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05

Expand Down Expand Up @@ -1050,6 +1056,15 @@ contract Comptroller is

require(rewardsDistributorExists[address(_rewardsDistributor)] == false, "already exists");

uint256 rewardsDistributorsLength = rewardsDistributors.length;
for (uint256 i; i < rewardsDistributorsLength; ++i) {
address rewardToken = address(rewardsDistributors[i].rewardToken());
require(
rewardToken != address(_rewardsDistributor.rewardToken()),
"distributor already exists with this reward"
);
}

rewardsDistributors.push(_rewardsDistributor);
rewardsDistributorExists[address(_rewardsDistributor)] = true;

Expand Down Expand Up @@ -1125,6 +1140,25 @@ contract Comptroller is
return (uint256(Error.NO_ERROR), seizeTokens);
}

/**
* @notice Returns reward speed given a vToken
* @param vToken The vToken to get the reward speeds for
* @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors
*/
function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {
uint256 rewardsDistributorsLength = rewardsDistributors.length;
RewardSpeeds[] memory rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);
for (uint256 i; i < rewardsDistributorsLength; ++i) {
address rewardToken = address(rewardsDistributors[i].rewardToken());
rewardSpeeds[i] = RewardSpeeds({
rewardToken: rewardToken,
supplySpeed: rewardsDistributors[i].rewardTokenSupplySpeeds(vToken),
borrowSpeed: rewardsDistributors[i].rewardTokenBorrowSpeeds(vToken)
});
}
return rewardSpeeds;
}

function initialize() public initializer {
__WithAdmin_init();
}
Expand Down
2 changes: 2 additions & 0 deletions contracts/ComptrollerInterface.sol
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,6 @@ abstract contract ComptrollerViewInterface {
function liquidationIncentiveMantissa() external view virtual returns (uint256);

function minLiquidatableCollateral() external view virtual returns (uint256);

function getXVSRewardsByMarket(address) external view virtual returns (uint256, uint256);
}
2 changes: 1 addition & 1 deletion contracts/Rewards/RewardsDistributor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ contract RewardsDistributor is ExponentialNoError, OwnableUpgradeable {

Comptroller private comptroller;

IERC20 private rewardToken;
IERC20 public rewardToken;

/**
* @dev Initializes the deployer to owner.
Expand Down
35 changes: 34 additions & 1 deletion tests/hardhat/Rewards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,20 +202,31 @@ describe("Rewards: Tests", async function () {
//Configure rewards for pool
const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor");
rewardsDistributor = await RewardsDistributor.deploy();

const rewardsDistributor2 = await RewardsDistributor.deploy();

xvs = await MockToken.deploy("Venus Token", "XVS", 18);
const initialXvs = convertToUnit(1000000, 18);
await xvs.faucet(initialXvs);
await xvs.transfer(rewardsDistributor.address, initialXvs);

await rewardsDistributor.initialize(comptrollerProxy.address, xvs.address);
await rewardsDistributor2.initialize(comptrollerProxy.address, mockDAI.address);

await comptrollerProxy.addRewardsDistributor(rewardsDistributor.address);
await comptrollerProxy.addRewardsDistributor(rewardsDistributor2.address);

await rewardsDistributor._setRewardTokenSpeeds(
[vWBTC.address, vDAI.address],
[convertToUnit(0.5, 18), convertToUnit(0.5, 18)],
[convertToUnit(0.5, 18), convertToUnit(0.5, 18)],
);

await rewardsDistributor2._setRewardTokenSpeeds(
[vWBTC.address, vDAI.address],
[convertToUnit(0.4, 18), convertToUnit(0.3, 18)],
[convertToUnit(0.2, 18), convertToUnit(0.1, 18)],
);
});

it("Should have correct btc balance", async function () {
Expand All @@ -236,14 +247,36 @@ describe("Rewards: Tests", async function () {
expect(await xvs.balanceOf(rewardsDistributor.address)).equal(convertToUnit(1000000, 18));
});

it("Should have coorect market addresses", async function () {
it("Should have correct market addresses", async function () {
const [owner] = await ethers.getSigners();

const res = await comptrollerProxy.getAssetsIn(owner.address);
expect(res[0]).equal(vDAI.address);
expect(res[1]).equal(vWBTC.address);
});

it("Comptroller returns correct reward speeds", async function () {
const res = await comptrollerProxy.getRewardsByMarket(vDAI.address);
expect(res[0][0]).equal(xvs.address);
expect(res[0][1].toString()).equal(convertToUnit(0.5, 18));
expect(res[0][2].toString()).equal(convertToUnit(0.5, 18));
expect(res[1][0]).equal(mockDAI.address);
expect(res[1][1].toString()).equal(convertToUnit(0.3, 18));
expect(res[1][2].toString()).equal(convertToUnit(0.1, 18));
});

it("Cannot add reward distributors with duplicate reward tokens", async function () {
const RewardsDistributor = await ethers.getContractFactory("RewardsDistributor");
rewardsDistributor = await RewardsDistributor.deploy();

const rewardsDistributorDuplicate = await RewardsDistributor.deploy();
await rewardsDistributorDuplicate.initialize(comptrollerProxy.address, xvs.address);

await await expect(comptrollerProxy.addRewardsDistributor(rewardsDistributorDuplicate.address)).to.be.revertedWith(
"distributor already exists with this reward",
);
});

//TODO: Test reward accruals. This test used to pass before, but it
// was a false-positive. The correct test would need to mint or
// borrow some assets (or pretend to do so, using smock).
Expand Down

0 comments on commit 5b639f9

Please sign in to comment.