hi all, please find code you can try to deploy it on both Kovan and Ganache-cli using above deployment script.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
/**
* RewardPool:
* Pool that issues rewards after a minimum duration of 7 days
*/
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "./RewardToken.sol";
import "./WETH.sol";
import "./AccountingToken.sol";
contract ETHPoolV1 is Initializable, ERC20Upgradeable, UUPSUpgradeable, OwnableUpgradeable {
// Token deposited into the pool by users.Note this is wrapped ETH.
WETH public liquidityToken;
// Token used for internal accounting
// Pegged 1:1 with the liquidity token
AccountingToken public accToken;
// Token in which rewards are issued
RewardToken public rewardToken;
// Events
event LiquidityTokenDeposit(address indexed depositor, uint256 amount);
// Initialize the deposit token address(WETH)
function initialize(address tokenAddress) public initializer {
liquidityToken = WETH(tokenAddress);
accToken = new AccountingToken();
rewardToken = new RewardToken();
__Ownable_init();
}
// UUPS function to allow only owner to upgrade
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
/**
* @notice sender must have approved `amountToDeposit` liquidity tokens in advance
*/
function deposit(uint256 amountToDeposit) external {
require(amountToDeposit > 0, "Must deposit tokens");
accToken.mint(msg.sender, amountToDeposit);
require(
liquidityToken.transferFrom(msg.sender, address(this), amountToDeposit)
);
emit LiquidityTokenDeposit(msg.sender,amountToDeposit);
}
function withdraw(uint256 amountToWithdraw) virtual external {
accToken.burn(msg.sender, amountToWithdraw);
require(liquidityToken.transfer(msg.sender, amountToWithdraw));
}
}
WETH.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract WETH is ERC20 {
constructor() ERC20("Wrapped ETH", "WETH") public {}
function mint() external payable {
_mint(msg.sender, msg.value);
}
function burn(uint amount) external {
(bool success,) = msg.sender.call{value:amount}("");
require(success, "failed to send WETH");
_burn(msg.sender, amount);
}
}
RewardToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
/**
* @notice A mintable ERC20 token to issue rewards
*/
contract RewardToken is ERC20, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
constructor() public ERC20("Reward Token", "DEGENFORLIFE") {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(MINTER_ROLE, msg.sender);
}
function mint(address to, uint256 amount) external {
require(hasRole(MINTER_ROLE, msg.sender));
_mint(to, amount);
}
}
AccountingToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Snapshot.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
/**
* A limited pseudo-ERC20 token to keep track of deposits and withdrawals
* with snapshotting capabilities
*/
contract AccountingToken is ERC20Snapshot, AccessControl {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant SNAPSHOT_ROLE = keccak256("SNAPSHOT_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
constructor() public ERC20("rToken", "ACC") {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(MINTER_ROLE, msg.sender);
_setupRole(SNAPSHOT_ROLE, msg.sender);
_setupRole(BURNER_ROLE, msg.sender);
}
function mint(address to, uint256 amount) external {
require(hasRole(MINTER_ROLE, msg.sender), "Forbidden");
_mint(to, amount);
}
function burn(address from, uint256 amount) external {
require(hasRole(BURNER_ROLE, msg.sender), "Forbidden");
_burn(from, amount);
}
function snapshot() external returns (uint256) {
require(hasRole(SNAPSHOT_ROLE, msg.sender), "Forbidden");
return _snapshot();
}
// Do not need transfer of this token
function _transfer(address, address, uint256) internal override {
revert("Not implemented");
}
// Do not need allowance of this token
function _approve(address, address, uint256) internal override {
revert("Not implemented");
}
}
hardhat.config
/**
* @type import('hardhat/config').HardhatUserConfig
*/
require("dotenv").config();
require("@nomiclabs/hardhat-waffle");
require('@nomiclabs/hardhat-ethers');
require("@nomiclabs/hardhat-etherscan");
require('@openzeppelin/hardhat-upgrades');
module.exports = {
solidity: { compilers:[{version:"0.8.2"},{version:"0.6.9"},{version:"0.6.2"}],
settings: {
optimizer: {
enabled: true,
runs: 1
}
}
},
etherscan: {
apiKey: process.env.ETHERSCAN_ETH
},
networks: {
hardhat: { allowUnlimitedContractSize: true },
localhost: { url: "http://localhost:8545" },
Kovan: {
url: process.env.KOVAN_ALCHEMY,
accounts: [process.env.PRIVATE_KEY_FF],
gas: 100000000,
allowUnlimitedContractSize: true,
timeout: 30000
},
},
};