// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/spadefiannce/openzeppelin-contracts/blob/master/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol";
import "https://github.com/spadefiannce/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol";
import "https://github.com/spadefiannce/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol";
interface Vault{
function depositWithPid(uint256 _pid, uint256 _amount) external ;
function withdrawWithPid(uint256 _pid, uint256 _amount) external ;
function getPoolNumBySingleToken(address _singleToken) external view returns (uint256 num) ;
}
contract WapperToken is ERC20PresetMinterPauser{
uint8 tokenDecimals;
bytes32 public constant TRANSFER_ROLE = keccak256("TRANSFER_ROLE");
constructor(string memory name, string memory symbol,uint8 _decimals) ERC20PresetMinterPauser(name, symbol) {
_setupRole(TRANSFER_ROLE, address(this));
_setupRole(TRANSFER_ROLE, address(0));
tokenDecimals=_decimals;
}
//转账权限限制
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
super._beforeTokenTransfer(from, to, amount);
require(hasRole(TRANSFER_ROLE, _msgSender())||hasRole(TRANSFER_ROLE, from)||hasRole(TRANSFER_ROLE, to), "sToken: must have transfer role transfer");
}
function decimals() public view virtual override returns (uint8) {
return tokenDecimals;
}
function mint(address to, uint256 amount) public override {
require(false);
}
}
contract WapperTokenPool is WapperToken{
using SafeMath for uint256;
using SafeERC20 for IERC20;
bytes32 public constant WITHDRAW_ROLE= keccak256("WITHDRAW_ROLE");
uint256 public frozenStakingTime = 3;
address public bxhv2FundAddress;
IERC20 singleToken;
mapping(address => uint256) public lastStakeTime;
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
uint256 public pid;
address public vaultAddress;
constructor(
address singleToken_,
string memory name,
string memory symbol,
uint8 _decimals,
address _vaultAddress
) WapperToken(name, symbol,_decimals) {
singleToken =IERC20(singleToken_);
_setupRole(WITHDRAW_ROLE, _msgSender());
vaultAddress=_vaultAddress;
pid = Vault(vaultAddress).getPoolNumBySingleToken(singleToken_);
bxhv2FundAddress=_msgSender();
singleToken.safeApprove(vaultAddress,type(uint256).max);
}
function stake(uint256 amount)
public
{
if(amount==0){
return;
}
singleToken.safeTransferFrom(msg.sender, address(this), amount);
_mint(msg.sender,amount);//Mint sToken
lastStakeTime[msg.sender] = block.timestamp;
Vault(vaultAddress).depositWithPid(pid,amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount)
public
{
if(amount==0){
return;
}
require(block.timestamp >= unfrozenStakeTime(msg.sender), "wapperTokenPool: Cannot withdrawal during freezing");
Vault(vaultAddress).withdrawWithPid(pid,amount);
_burn(msg.sender, amount);
singleToken.safeTransfer(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}
function exit() external {
withdraw(balanceOf(msg.sender));
}
function unfrozenStakeTime(address account) public view returns (uint256) {
return lastStakeTime[account] + frozenStakingTime;
}
//----------------------- admin setting---------------------------------//
function withdrawRewardToFundAddress(address rewardTokenAddress,uint256 amount) external virtual {
require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "wapperTokenPool: must have DEFAULT_ADMIN_ROLE");
require(bxhv2FundAddress != address(0), 'wapperTokenPool: Zero address or self');
require(rewardTokenAddress!=address(singleToken),"this is rewardToken!");
IERC20(rewardTokenAddress).transfer(bxhv2FundAddress,amount);
}
function setbxhV2FundAddress(address bxhv2FundAddress_) external virtual {
require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "wapperTokenPool: must have DEFAULT_ADMIN_ROLE");
require(bxhv2FundAddress_ != address(0) && bxhv2FundAddress_ != address(this), 'wapperTokenPool: Zero address or self');
bxhv2FundAddress = bxhv2FundAddress_;
}
function setFrozenStakingTime(uint256 frozenStakingTime_) external virtual {
require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "wapperTokenPool: must have DEFAULT_ADMIN_ROLE");
require(frozenStakingTime_<60*60*24*3);
frozenStakingTime = frozenStakingTime_;
}
function withdrawEmergency(address tokenaddress,address to) public {
require(hasRole(WITHDRAW_ROLE, _msgSender()), "wapperTokenPool: must have withdraw role to withdraw");
require(tokenaddress!=address(singleToken),"this is rewardToken!");
require(to != address(0), 'wapperTokenPool: Zero address');
IERC20(tokenaddress).transfer(to,IERC20(tokenaddress).balanceOf(address(this)));
}
}
{
"compilationTarget": {
"contracts/PreWapperETH.sol": "WapperTokenPool"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"singleToken_","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"address","name":"_vaultAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANSFER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAW_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bxhv2FundAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"frozenStakingTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastStakeTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"frozenStakingTime_","type":"uint256"}],"name":"setFrozenStakingTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bxhv2FundAddress_","type":"address"}],"name":"setbxhV2FundAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unfrozenStakeTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenaddress","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawEmergency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rewardTokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawRewardToFundAddress","outputs":[],"stateMutability":"nonpayable","type":"function"}]