// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)pragmasolidity ^0.8.20;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 2 of 8: FeeCollector.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.13;import"openzeppelin-contracts/contracts/access/Ownable.sol";
import"openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import"./interfaces/uniswap-v3-periphery/INonfungiblePositionManager.sol";
import"./interfaces/uniswap-v3-periphery/ISwapRouter.sol";
import"./interfaces/IEthCoin.sol";
import"./interfaces/IVRFCoordinator.sol";
contractFeeCollectorisOwnable{
/// @notice Uniswap v3 swapRouter
ISwapRouter publicimmutable swapRouter;
/// @notice Uniswap v3 nonfungiblePositionManager contract
INonfungiblePositionManager publicimmutable nonfungiblePositionManager;
/// @notice The address of Ethcoinaddresspublicimmutable ETHC;
/// @notice The address of WETHaddresspublicimmutable WETH;
/// @notice The token id of uniswap v3 ETHC/WETH position that this contract would add liquidity touint256publicimmutable tokenId;
/// @notice The fee tier of the ETHC/WETH uniswap v3 pooluint24publicimmutable fee;
/// @notice The address of the ChainLink VRF coordinator
IVRFCoordinator publicimmutable vrfCoordinator;
/// @notice The subscription id of the ChainLink VRF requestuint256public subscriptionId;
/// @notice The address of the operatoraddresspublic operator;
modifieronlyOperator() {
require(msg.sender== operator, "FeeCollector: not operator");
_;
}
constructor(address _ETHC,
address _WETH,
address _swapRouter,
address _nonfungiblePositionManager,
uint256 _tokenId,
address _vrfCoordinator,
uint256 _subscriptionId,
address _operator
) Ownable(msg.sender) {
ETHC = _ETHC;
WETH = _WETH;
swapRouter = ISwapRouter(_swapRouter);
nonfungiblePositionManager = INonfungiblePositionManager(_nonfungiblePositionManager);
tokenId = _tokenId;
(,,,, fee,,,,,,,) = nonfungiblePositionManager.positions(tokenId);
vrfCoordinator = IVRFCoordinator(_vrfCoordinator);
IERC20(ETHC).approve(address(nonfungiblePositionManager), type(uint256).max);
subscriptionId = _subscriptionId;
operator = _operator;
}
/**
* @notice Collect all ETH from Ethcoin.
* @param amount The amount of ETH to collect
*/functioncollect(uint256 amount) externalonlyOperator{
IEthCoin(ETHC).collect(amount);
}
/**
* @notice Fund the ChainLink VRF subscription with ETH.
* @param amount The amount of ETH to fund the subscription
*/functionfundSubscription(uint256 amount) externalonlyOperator{
vrfCoordinator.fundSubscriptionWithNative{value: amount}(subscriptionId);
}
/**
* @notice Buy Ethcoin with ETH.
* @param amountIn The amount of ETH to swap for Ethcoin
* @param amountOutMinimum The minimum amount of Ethcoin to receive
* @return The amount of Ethcoin bought
*/functionbuyEthcoin(uint256 amountIn, uint256 amountOutMinimum) externalonlyOperatorreturns (uint256) {
return swapRouter.exactInputSingle{value: amountIn}(
ISwapRouter.ExactInputSingleParams({
tokenIn: WETH,
tokenOut: ETHC,
fee: fee,
recipient: address(this),
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: amountOutMinimum,
sqrtPriceLimitX96: 0
})
);
}
/**
* @notice Withdraw Ethcoin to the owner.
* @param amount The amount of Ethcoin to withdraw
*/functionwithdrawEthcoin(uint256 amount) externalonlyOperator{
uint256 balance = IERC20(ETHC).balanceOf(address(this));
require(balance >= amount, "FeeCollector: insufficient balance");
IERC20(ETHC).transfer(owner(), amount);
}
/**
* @notice Increase the liquidity of the Ethcoin/WETH Uniswap v3 pool.
* @param amountEthcoinDesired The amount of ETHC that we want to add
* @param amountEthDesired The amount of WETH that we want to add
* @param amountEthcoinMin The minimum amount of ETHC that we want to add
* @param amountEthMin The minimum amount of WETH that we want to add
*/functionincreaseLiquidity(uint256 amountEthcoinDesired,
uint256 amountEthDesired,
uint256 amountEthcoinMin,
uint256 amountEthMin
) externalonlyOperator{
nonfungiblePositionManager.increaseLiquidity{value: address(this).balance}(
INonfungiblePositionManager.IncreaseLiquidityParams({
tokenId: tokenId,
amount0Desired: amountEthDesired,
amount1Desired: amountEthcoinDesired,
amount0Min: amountEthMin,
amount1Min: amountEthcoinMin,
deadline: block.timestamp
})
);
nonfungiblePositionManager.refundETH();
}
/**
* @notice deployer can rescue ETH
*/functionrescue() externalonlyOwner{
payable(owner()).transfer(address(this).balance);
}
/**
* @notice set operator
* @param _operator The address of the operator
*/functionsetOperator(address _operator) externalonlyOwner{
operator = _operator;
}
receive() externalpayable{}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)pragmasolidity ^0.8.20;import {Context} from"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/errorOwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/errorOwnableInvalidOwner(address owner);
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/constructor(address initialOwner) {
if (initialOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
if (newOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}