Skip to content

Commit

Permalink
✨ vote: get voting power from velodrome and extra
Browse files Browse the repository at this point in the history
  • Loading branch information
cruzdanilo committed Oct 11, 2023
1 parent 6179c24 commit 3b40526
Show file tree
Hide file tree
Showing 7 changed files with 738 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/twenty-peas-hug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@exactly/protocol": patch
---

✨ vote: get voting power from velodrome and extra
3 changes: 2 additions & 1 deletion .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -400,4 +400,5 @@ SwapperTest:testSwapWithKeepAmount() (gas: 201230)
SwapperTest:testSwapWithKeepEqualToValue() (gas: 41783)
SwapperTest:testSwapWithKeepHigherThanValue() (gas: 41804)
SwapperTest:testSwapWithPermit() (gas: 566299)
SwapperTest:testSwapWithPermit2() (gas: 560666)
SwapperTest:testSwapWithPermit2() (gas: 560666)
VotePreviewerTest:testExternalVotes() (gas: 97572)
66 changes: 66 additions & 0 deletions contracts/periphery/VotePreviewer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.17;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { FixedPointMathLib } from "solmate/src/utils/FixedPointMathLib.sol";

/// @title Vote Previewer
/// @notice Contract to be consumed by voting strategies.
contract VotePreviewer {
using FixedPointMathLib for uint256;

/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address public immutable exa;
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
IPool public immutable pool;
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
IERC20 public immutable gauge;
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
IExtraLending public immutable extraLending;
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
uint256 public immutable extraReserveId;

/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address exa_, IPool pool_, IERC20 gauge_, IExtraLending extraLending_, uint256 extraReserveId_) {
exa = exa_;
pool = pool_;
gauge = gauge_;
extraLending = extraLending_;
extraReserveId = extraReserveId_;

Check warning on line 29 in contracts/periphery/VotePreviewer.sol

View check run for this annotation

Codecov / codecov/patch

contracts/periphery/VotePreviewer.sol#L25-L29

Added lines #L25 - L29 were not covered by tests
}

function externalVotes(address account) external view returns (uint256 votes) {
uint256 liquidity = pool.balanceOf(account) + gauge.balanceOf(account);
votes += liquidity.mulDivDown(exa == pool.token0() ? pool.reserve0() : pool.reserve1(), pool.totalSupply());

uint256[] memory reserveIds = new uint256[](1);
reserveIds[0] = extraReserveId;
IExtraLending.PositionStatus[] memory e = extraLending.getPositionStatus(reserveIds, account);
votes += extraLending.exchangeRateOfReserve(extraReserveId).mulWadDown(e[0].eTokenStaked + e[0].eTokenUnStaked);
}
}

interface IPool is IERC20 {
function token0() external view returns (address);

function reserve0() external view returns (uint256);

function reserve1() external view returns (uint256);
}

interface IExtraLending {
struct PositionStatus {
uint256 reserveId;
address user;
uint256 eTokenStaked;
uint256 eTokenUnStaked;
uint256 liquidity;
}

function getPositionStatus(
uint256[] memory reserveIds,
address account
) external view returns (PositionStatus[] memory);

function exchangeRateOfReserve(uint256 reserveId) external view returns (uint256);
}
27 changes: 26 additions & 1 deletion deploy/Previewers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,34 @@ import type { DeployFunction } from "hardhat-deploy/types";
import validateUpgrade from "./.utils/validateUpgrade";

const func: DeployFunction = async ({
network: {
config: {
finance: { periphery },
},
},
ethers: {
constants: { AddressZero },
},
deployments: { deploy, get, getOrNull },
getNamedAccounts,
}) => {
const [{ address: auditor }, { address: debtManager }, { address: priceFeedETH }, { deployer }] = await Promise.all([
const [
{ address: auditor },
{ address: debtManager },
{ address: exa },
{ address: exaPool },
{ address: exaGauge },
{ address: priceFeedETH },
{ address: extraLending },
{ deployer },
] = await Promise.all([
get("Auditor"),
get("DebtManager"),
get("EXA"),
getOrNull("EXAPool").then((d) => d ?? { address: AddressZero }),
getOrNull("EXAGauge").then((d) => d ?? { address: AddressZero }),
getOrNull("PriceFeedETH").then((d) => d ?? { address: AddressZero }),
getOrNull("ExtraLending").then((d) => d ?? { address: AddressZero }),
getNamedAccounts(),
]);
await validateUpgrade("Previewer", { args: [auditor, priceFeedETH], envKey: "PREVIEWER" }, async (name, opts) =>
Expand All @@ -25,6 +43,13 @@ const func: DeployFunction = async ({
log: true,
}),
);

await validateUpgrade(
"VotePreviewer",
{ args: [exa, exaPool, exaGauge, extraLending, periphery.extraReserve], envKey: "VOTE_PREVIEWER" },
async (name, opts) =>
deploy(name, { ...opts, proxy: { proxyContract: "TransparentUpgradeableProxy" }, from: deployer, log: true }),
);
};

func.tags = ["Previewers"];
Expand Down
Loading

0 comments on commit 3b40526

Please sign in to comment.