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

Post audit/treasury modifications #5

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"printWidth": 100,
"printWidth": 120,
"trailingComma": "es5",
"semi": true,
"singleQuote": true,
Expand All @@ -9,7 +9,7 @@
"files": "*.sol",
"options": {
"semi": true,
"printWidth": 100
"printWidth": 120
}
}
]
Expand Down
123 changes: 64 additions & 59 deletions contracts/buyback/Treasury.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,95 +3,100 @@ pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {IUniswapV2Router02} from './interfaces/IUniswapV2Router02.sol';
import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';

import {ICurve} from './interfaces/ICurve.sol';
import {ICurveFactory} from './interfaces/ICurveFactory.sol';
import 'hardhat/console.sol';
import {IUniswapV2Pair} from './interfaces/IUniswapV2Pair.sol';

contract Treasury is Ownable {
event RnbwBought(uint256 amount, address caller);
event RnbwSentToVesting(uint256 amount, address caller);
event RNBWBoughtAndSentToVesting(uint256 amountBought, address indexed caller);

using SafeMath for uint256;
using SafeERC20 for IERC20;

ICurveFactory public immutable curveFactory;

address public immutable rainbowPool;
address public immutable lendingPool;
address public immutable router;
address public immutable rnbw;
address public immutable vestingContract;
address public immutable curveFactory;
address public immutable USDC;
address public WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address public immutable usdc;
address public immutable usdcRnbwPairAddress;

constructor(
address _lendingPool,
address _router,
address _rnbw,
address _vestingContract,
address _rainbowPool,
address _curveFactory,
address _usdc
address _usdc,
address _usdcRnbwPairAddress
) public {
lendingPool = _lendingPool;
router = _router;
rnbw = _rnbw;
vestingContract = _vestingContract;
curveFactory = _curveFactory;
USDC = _usdc;
rainbowPool = _rainbowPool;
curveFactory = ICurveFactory(_curveFactory);
usdc = _usdc;
usdcRnbwPairAddress = _usdcRnbwPairAddress;
}

function buybackRnbw(address[] calldata _underlyings) external onlyOwner returns (uint256) {
uint256 rnbwBought;
/**
* @dev convert all fees collected to RNBW
* @param _underlyings all hTokens for conversion
* @param minRNBWAmount minimum RNBW amount expected, protection against price manipulation attacks
**/

function buybackRnbw(
address[] calldata _underlyings,
uint256 minRNBWAmount,
uint256 deadline
) external onlyOwner returns (uint256) {
// 1 - Withdraw and Convert to USDC
for (uint256 i = 0; i < _underlyings.length; i++) {
uint256 underlyingAmount =
ILendingPool(lendingPool).withdraw(_underlyings[i], type(uint256).max, address(this));
convertToUsdc(_underlyings[i], underlyingAmount);
uint256 underlyingAmount = ILendingPool(lendingPool).withdraw(_underlyings[i], type(uint256).max, address(this));
0xAplki marked this conversation as resolved.
Show resolved Hide resolved
_convertToUsdc(_underlyings[i], underlyingAmount, deadline);
}

uint256 usdcBalance = IERC20(USDC).balanceOf(address(this));

//approve uniswap to swap
IERC20(USDC).approve(router, usdcBalance);

//create swap path
address[] memory path = new address[](3);
path[0] = USDC;
path[1] = WETH9;
path[2] = rnbw;
rnbwBought = IUniswapV2Router02(router).swapExactTokensForTokens(
usdcBalance,
0,
path,
address(this),
block.timestamp + 60
)[0];

emit RnbwBought(rnbwBought, msg.sender);
return rnbwBought;
// 2 - Convert USDC to RNBW and send to vesting contract
uint256 rnbwAmount = _swap(IERC20(usdc).balanceOf(address(this)), rainbowPool);

require(rnbwAmount >= minRNBWAmount, 'Treasury: rnbwAmount is less than minRNBWAmount');

emit RNBWBoughtAndSentToVesting(rnbwAmount, msg.sender);
}

function convertToUsdc(address _underlying, uint256 _underlyingAmount)
internal
returns (uint256)
{
address curveAddress = ICurveFactory(curveFactory).getCurve(_underlying, USDC);
IERC20(_underlying).approve(curveAddress, _underlyingAmount);
uint256 targetAmount =
ICurve(curveAddress).originSwap(
_underlying,
USDC,
_underlyingAmount,
0,
block.timestamp + 60
);
/**
* @dev helper function to convert all underlying assets into usdc before swapping to RNBW
**/
function _convertToUsdc(
address _underlying,
uint256 _underlyingAmount,
uint256 deadline
) internal returns (uint256) {
// 1 - Get curve
ICurve curve = ICurve(curveFactory.getCurve(_underlying, usdc));
IERC20(_underlying).approve(address(curve), _underlyingAmount);

// 2 - Swap to USDC
uint256 targetAmount = curve.originSwap(_underlying, usdc, _underlyingAmount, 0, deadline);
return targetAmount;
}

function sendToVestingContract() external onlyOwner {
uint256 rnbwAmount = IERC20(rnbw).balanceOf(address(this));
IERC20(rnbw).transfer(vestingContract, rnbwAmount);
emit RnbwSentToVesting(rnbwAmount, msg.sender);
/**
* @dev Swaps usdc to rnbw from the USDC-RNBW Pool. fromToken will always be usdc and toToken will always be rainbow
we simplified this to make it more gas efficient
**/

function _swap(uint256 amountIn, address to) internal returns (uint256 amountOut) {
IUniswapV2Pair pair = IUniswapV2Pair(usdcRnbwPairAddress);

(uint256 reserve0, uint256 reserve1, ) = pair.getReserves();
uint256 amountInWithFee = amountIn.mul(997);

amountOut = amountInWithFee.mul(reserve1).div(reserve0.mul(1000).add(amountInWithFee));
IERC20(usdc).safeTransfer(address(pair), amountIn);
pair.swap(0, amountOut, to, new bytes(0));
}
}
30 changes: 30 additions & 0 deletions contracts/buyback/interfaces/IERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0;

interface IERC20Uniswap {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);

function name() external view returns (string memory);

function symbol() external view returns (string memory);

function decimals() external view returns (uint8);

function totalSupply() external view returns (uint256);

function balanceOf(address owner) external view returns (uint256);

function allowance(address owner, address spender) external view returns (uint256);

function approve(address spender, uint256 value) external returns (bool);

function transfer(address to, uint256 value) external returns (bool);

function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
12 changes: 12 additions & 0 deletions contracts/buyback/interfaces/IUniswapV2Callee.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0;

interface IUniswapV2Callee {
function uniswapV2Call(
address sender,
uint256 amount0,
uint256 amount1,
bytes calldata data
) external;
}
46 changes: 46 additions & 0 deletions contracts/buyback/interfaces/IUniswapV2ERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0;

interface IUniswapV2ERC20 {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);

function name() external pure returns (string memory);

function symbol() external pure returns (string memory);

function decimals() external pure returns (uint8);

function totalSupply() external view returns (uint256);

function balanceOf(address owner) external view returns (uint256);

function allowance(address owner, address spender) external view returns (uint256);

function approve(address spender, uint256 value) external returns (bool);

function transfer(address to, uint256 value) external returns (bool);

function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);

function DOMAIN_SEPARATOR() external view returns (bytes32);

function PERMIT_TYPEHASH() external pure returns (bytes32);

function nonces(address owner) external view returns (uint256);

function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
21 changes: 21 additions & 0 deletions contracts/buyback/interfaces/IUniswapV2Factory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0;

interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint256);

function feeTo() external view returns (address);

function feeToSetter() external view returns (address);

function migrator() external view returns (address);

function getPair(address tokenA, address tokenB) external view returns (address pair);

function allPairs(uint256) external view returns (address pair);

function allPairsLength() external view returns (uint256);

function createPair(address tokenA, address tokenB) external returns (address pair);
}
98 changes: 98 additions & 0 deletions contracts/buyback/interfaces/IUniswapV2Pair.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0;

interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);

function name() external pure returns (string memory);

function symbol() external pure returns (string memory);

function decimals() external pure returns (uint8);

function totalSupply() external view returns (uint256);

function balanceOf(address owner) external view returns (uint256);

function allowance(address owner, address spender) external view returns (uint256);

function approve(address spender, uint256 value) external returns (bool);

function transfer(address to, uint256 value) external returns (bool);

function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);

function DOMAIN_SEPARATOR() external view returns (bytes32);

function PERMIT_TYPEHASH() external pure returns (bytes32);

function nonces(address owner) external view returns (uint256);

function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;

event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);

function MINIMUM_LIQUIDITY() external pure returns (uint256);

function factory() external view returns (address);

function token0() external view returns (address);

function token1() external view returns (address);

function getReserves()
external
view
returns (
uint112 reserve0,
uint112 reserve1,
uint32 blockTimestampLast
);

function price0CumulativeLast() external view returns (uint256);

function price1CumulativeLast() external view returns (uint256);

function kLast() external view returns (uint256);

function mint(address to) external returns (uint256 liquidity);

function burn(address to) external returns (uint256 amount0, uint256 amount1);

function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;

function skim(address to) external;

function sync() external;

function initialize(address, address) external;
}
Loading