Skip to content
5 changes: 3 additions & 2 deletions src/util/ALE.sol
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ contract ALE is

constructor(
address _exchangeProxy,
address _pool
) Ownable(msg.sender) CurveDBRHelper(_pool) {
address _pool,
address _gov
) Ownable(msg.sender) CurveDBRHelper(_pool, _gov) {
exchangeProxy = payable(address(_exchangeProxy));
_approveDola(address(flash), type(uint).max);
}
Expand Down
5 changes: 3 additions & 2 deletions src/util/ALEV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,9 @@ contract ALEV2 is
mapping(address => Market) public markets;

constructor(
address _pool
) Ownable(msg.sender) CurveDBRHelper(_pool) {
address _pool,
address _gov
) Ownable(_gov) CurveDBRHelper(_pool, _gov) {
dola.approve(address(flash), type(uint).max);
}

Expand Down
74 changes: 58 additions & 16 deletions src/util/CurveDBRHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,27 @@ interface ICurvePool {
uint j,
uint dx,
uint min_dy,
bool use_eth
) external payable returns (uint);

function exchange(
uint i,
uint j,
uint dx,
uint min_dy,
bool use_eth,
address receiver
) external payable returns (uint);
) external returns (uint);
}

contract CurveDBRHelper {
ICurvePool public immutable curvePool;
ICurvePool public curvePool;
address public gov;
address public pendingGov;
IDola constant dola = IDola(0x865377367054516e17014CcdED1e7d814EDC9ce4);
IERC20 constant dbr = IERC20(0xAD038Eb671c44b853887A7E32528FaB35dC5D710);

uint dbrIndex;
uint dolaIndex;
uint public dbrIndex;
uint public dolaIndex;

constructor(address _pool) {
event NewPendingGov(address indexed oldPendingGov, address indexed newPendingGov);
event NewGov(address indexed oldGov, address indexed newGov);
event NewCurvePool(address indexed newPool, uint256 dolaIndex, uint256 dbrIndex);

constructor(address _pool, address _gov) {
curvePool = ICurvePool(_pool);
gov = _gov;
dola.approve(_pool, type(uint).max);
dbr.approve(_pool, type(uint).max);
if (ICurvePool(_pool).coins(0) == address(dola)) {
Expand All @@ -47,6 +45,11 @@ contract CurveDBRHelper {
}
}

modifier onlyGov() {
require(msg.sender == gov, "CurveHelper: only gov");
_;
}

/**
@notice Sells an exact amount of DBR for DOLA in a curve pool
@param amount Amount of DBR to sell
Expand All @@ -59,7 +62,6 @@ contract CurveDBRHelper {
dolaIndex,
amount,
minOut,
false,
receiver
);
}
Expand All @@ -77,7 +79,6 @@ contract CurveDBRHelper {
dbrIndex,
amount,
minOut,
false,
receiver
);
}
Expand Down Expand Up @@ -129,4 +130,45 @@ contract CurveDBRHelper {
}
return (amountIn, ((dolaBorrowAmount + amountIn) * period) / 365 days);
}

/**
* @notice Set a new pending gov. The new pending gov then has to call `acceptGov`.
* @dev Can only be called by the gov.
* @param _pendingGov address of the new pending gov
*/
function setPendingGov(address _pendingGov) external onlyGov {
emit NewPendingGov(pendingGov, _pendingGov);
pendingGov = _pendingGov;
}

/**
* @notice Accept the new pending gov.
* @dev Can only be called by the pending gov.
*/
function acceptGov() external {
require(msg.sender == pendingGov, "Only pending gov");
emit NewGov(gov, pendingGov);
gov = pendingGov;
pendingGov = address(0);
}

/**
@notice Sets a new curve pool
@dev Can only be called by the gov
@param _pool Address of the new curve pool
@param _dolaIndex Index of DOLA in the new curve pool
@param _dbrIndex Index of DBR in the new curve pool
*/
function setCurvePool(address _pool, uint256 _dolaIndex, uint256 _dbrIndex) external onlyGov {
dola.approve(address(curvePool), 0);
dbr.approve(address(curvePool), 0);

curvePool = ICurvePool(_pool);
dola.approve(_pool, type(uint).max);
dbr.approve(_pool, type(uint).max);

dolaIndex = _dolaIndex;
dbrIndex = _dbrIndex;
emit NewCurvePool(_pool, _dolaIndex, _dbrIndex);
}
}
69 changes: 60 additions & 9 deletions src/util/CurveHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@ import "src/util/OffchainAbstractHelper.sol";
interface ICurvePool {
function coins(uint index) external view returns(address);
function get_dy(uint i, uint j, uint dx) external view returns(uint);
function exchange(uint i, uint j, uint dx, uint min_dy, bool use_eth) external payable returns(uint);
function exchange(uint i, uint j, uint dx, uint min_dy, bool use_eth, address receiver) external payable returns(uint);
function exchange(uint i, uint j, uint dx, uint min_dy, address receiver) external returns(uint);
function exchange(uint i, uint j, uint dx, uint min_dy) external returns(uint);
}

contract CurveHelper is OffchainAbstractHelper{
contract CurveHelper is OffchainAbstractHelper {

ICurvePool public immutable curvePool;
uint dbrIndex;
uint dolaIndex;
ICurvePool public curvePool;
address public pendingGov;
address public gov;
uint public dbrIndex;
uint public dolaIndex;

constructor(address _pool) {
event NewPendingGov(address indexed oldPendingGov, address indexed newPendingGov);
event NewGov(address indexed oldGov, address indexed newGov);
event NewCurvePool(address indexed newPool, uint256 dolaIndex, uint256 dbrIndex);

constructor(address _pool, address _gov) {
curvePool = ICurvePool(_pool);
gov = _gov;
DOLA.approve(_pool, type(uint).max);
DBR.approve(_pool, type(uint).max);
if(ICurvePool(_pool).coins(0) == address(DOLA)){
Expand All @@ -27,14 +34,19 @@ contract CurveHelper is OffchainAbstractHelper{
}
}

modifier onlyGov() {
require(msg.sender == gov, "CurveHelper: only gov");
_;
}

/**
@notice Sells an exact amount of DBR for DOLA in a curve pool
@param amount Amount of DBR to sell
@param minOut minimum amount of DOLA to receive
*/
function _sellDbr(uint amount, uint minOut) internal override {
if(amount > 0){
curvePool.exchange(dbrIndex, dolaIndex, amount, minOut, false);
curvePool.exchange(dbrIndex, dolaIndex, amount, minOut);
}
}

Expand All @@ -45,7 +57,7 @@ contract CurveHelper is OffchainAbstractHelper{
*/
function _buyDbr(uint amount, uint minOut, address receiver) internal override {
if(amount > 0) {
curvePool.exchange(dolaIndex, dbrIndex, amount, minOut, false, receiver);
curvePool.exchange(dolaIndex, dbrIndex, amount, minOut, receiver);
}
}

Expand Down Expand Up @@ -82,4 +94,43 @@ contract CurveHelper is OffchainAbstractHelper{
}
return (amountIn, (dolaBorrowAmount + amountIn) * period / 365 days);
}

/**
* @notice Set a new pending gov. The new pending gov then has to call `acceptGov`.
* @dev Can only be called by the gov.
* @param _pendingGov address of the new pending gov
*/
function setPendingGov(address _pendingGov) external onlyGov {
emit NewPendingGov(pendingGov, _pendingGov);
pendingGov = _pendingGov;
}

/**
* @notice Accept the new pending gov.
* @dev Can only be called by the pending gov.
*/
function acceptGov() external {
require(msg.sender == pendingGov, "Only pending gov");
emit NewGov(gov, pendingGov);
gov = pendingGov;
pendingGov = address(0);
}

/**
@notice Sets a new curve pool
@dev Can only be called by the gov
@param _pool Address of the new curve pool
@param _dolaIndex Index of DOLA in the new curve pool
@param _dbrIndex Index of DBR in the new curve pool
*/
function setCurvePool(address _pool, uint256 _dolaIndex, uint256 _dbrIndex) external onlyGov {
DOLA.approve(address(curvePool), 0);
DBR.approve(address(curvePool), 0);
curvePool = ICurvePool(_pool);
DOLA.approve(_pool, type(uint).max);
DBR.approve(_pool, type(uint).max);
dolaIndex = _dolaIndex;
dbrIndex = _dbrIndex;
emit NewCurvePool(_pool, _dolaIndex, _dbrIndex);
}
}
82 changes: 67 additions & 15 deletions src/util/DbrHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ interface ICurvePool {
uint j,
uint dx,
uint min_dy,
bool use_eth,
address receiver
) external payable returns (uint);
) external returns (uint);
}

interface IINVEscrow {
Expand Down Expand Up @@ -44,20 +43,22 @@ contract DbrHelper is Ownable, ReentrancyGuard {

IMarket public constant INV_MARKET =
IMarket(0xb516247596Ca36bf32876199FBdCaD6B3322330B);
ICurvePool public constant CURVE_POOL =
ICurvePool(0xC7DE47b9Ca2Fc753D6a2F167D8b3e19c6D18b19a);
IERC20 public constant DOLA =
IERC20(0x865377367054516e17014CcdED1e7d814EDC9ce4);
IERC20 public constant DBR =
IERC20(0xAD038Eb671c44b853887A7E32528FaB35dC5D710);
IERC20 public constant INV =
IERC20(0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68);

uint256 public constant DOLA_INDEX = 0;
uint256 public constant DBR_INDEX = 1;
uint256 public constant INV_INDEX = 2;
uint256 public dolaIndex = 0;
uint256 public dbrIndex = 1;
uint256 public invIndex = 2;
uint256 public constant DENOMINATOR = 10000; // 100% in basis points

ICurvePool public curvePool;
address public gov;
address public pendingGov;

event Sell(
address indexed claimer,
uint amountIn,
Expand All @@ -77,12 +78,21 @@ contract DbrHelper is Ownable, ReentrancyGuard {
uint invAmount
);
event MarketApproved(address indexed market);
event NewPendingGov(address indexed oldPendingGov, address indexed newPendingGov);
event NewGov(address indexed oldGov, address indexed newGov);
event NewCurvePool(address indexed newPool, uint256 dolaIndex, uint256 dbrIndex, uint256 invIndex);

constructor() Ownable(msg.sender) {
DBR.approve(address(CURVE_POOL), type(uint).max);
constructor(address _curvePool) Ownable(msg.sender) {
curvePool = ICurvePool(_curvePool);
DBR.approve(address(curvePool), type(uint).max);
INV.approve(address(INV_MARKET), type(uint).max);
}

modifier onlyGov() {
require(msg.sender == gov, "CurveHelper: only gov");
_;
}

struct ClaimAndSell {
address toDbr; // Address to receive leftover DBR
address toDola; // Address to receive DOLA
Expand Down Expand Up @@ -174,7 +184,7 @@ contract DbrHelper is Ownable, ReentrancyGuard {
dolaAmount = _sellDbr(
sellAmountForDola,
params.minOutDola,
DOLA_INDEX,
dolaIndex,
params.toDola
);
}
Expand Down Expand Up @@ -209,7 +219,7 @@ contract DbrHelper is Ownable, ReentrancyGuard {
address to
) internal returns (uint256 invAmount) {
// Sell DBR for INV
_sellDbr(amount, minOutInv, INV_INDEX, address(this));
_sellDbr(amount, minOutInv, invIndex, address(this));
// Deposit INV
invAmount = INV.balanceOf(address(this));
INV_MARKET.deposit(to, invAmount);
Expand All @@ -229,7 +239,7 @@ contract DbrHelper is Ownable, ReentrancyGuard {
Repay calldata repay
) internal returns (uint256 dolaAmount, uint256 repaidAmount) {
// Sell DBR for DOLA
dolaAmount = _sellDbr(amount, minOutDola, DOLA_INDEX, address(this));
dolaAmount = _sellDbr(amount, minOutDola, dolaIndex, address(this));
// Repay debt
repaidAmount = _repay(repay, dolaAmount);
}
Expand Down Expand Up @@ -282,12 +292,11 @@ contract DbrHelper is Ownable, ReentrancyGuard {
uint indexOut,
address receiver
) internal returns (uint256 amountOut) {
amountOut = CURVE_POOL.exchange(
DBR_INDEX,
amountOut = curvePool.exchange(
dbrIndex,
indexOut,
amountIn,
minOut,
false,
receiver
);
emit Sell(msg.sender, amountIn, amountOut, indexOut, receiver);
Expand Down Expand Up @@ -325,4 +334,47 @@ contract DbrHelper is Ownable, ReentrancyGuard {
revert SellPercentageTooHigh();
if (repay.percentage > DENOMINATOR) revert RepayPercentageTooHigh();
}


/**
* @notice Set a new pending gov. The new pending gov then has to call `acceptGov`.
* @dev Can only be called by the gov.
* @param _pendingGov address of the new pending gov
*/
function setPendingGov(address _pendingGov) external onlyGov {
emit NewPendingGov(pendingGov, _pendingGov);
pendingGov = _pendingGov;
}

/**
* @notice Accept the new pending gov.
* @dev Can only be called by the pending gov.
*/
function acceptGov() external {
require(msg.sender == pendingGov, "Only pending gov");
emit NewGov(gov, pendingGov);
gov = pendingGov;
pendingGov = address(0);
}

/**
@notice Sets a new curve pool
@dev Can only be called by the gov
@param _pool Address of the new curve pool
@param _dolaIndex Index of DOLA in the new curve pool
@param _dbrIndex Index of DBR in the new curve pool
@param _invIndex Index of INV in the new curve pool
*/
function setCurvePool(address _pool, uint256 _dolaIndex, uint256 _dbrIndex, uint256 _invIndex) external onlyGov {
DBR.approve(address(curvePool), 0);

curvePool = ICurvePool(_pool);

DBR.approve(_pool, type(uint).max);

dolaIndex = _dolaIndex;
dbrIndex = _dbrIndex;
invIndex = _invIndex;
emit NewCurvePool(_pool, _dolaIndex, _dbrIndex, _invIndex);
}
}
Loading
Loading