文件 1 的 8:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 2 的 8:EEFI_Furnace.sol
pragma solidity 0.8.9;
import {IWETH} from "IERCWETHInterfaces.sol";
import {IEEFIToken} from "IERCWETHInterfaces.sol";
import {ITokenRewards} from "ITokenRewards.sol";
import {IPodToken} from "IPodToken.sol";
import "Ownable.sol";
import "TransferHelper.sol";
contract EEFIFurnace is Ownable {
address private constant _WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address private constant _EEFI = 0x857FfC55B1Aa61A7fF847C82072790cAE73cd883;
address private constant _USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
address private constant _PEAS = 0x02f92800F57BCD74066F5709F1Daa1A4302Df875;
address public newPartnerAddress;
address payable immutable TREASURY =
payable(0xf950a86013bAA227009771181a885E369e158da3);
IWETH public constant weth = IWETH(_WETH);
IEEFIToken public constant eefi = IEEFIToken(_EEFI);
ITokenRewards public podTokenRewardsContract;
IPodToken public podTokenContract;
bool public sendToTreasury = false;
event EEFIBurn(address source, uint256 amount);
event PEASRewardsClaimed(address destination, uint256 amount);
event PEASRewardsTransferred(address destination, uint256 amount);
event PTokenUnwrapped(address asset, uint256 amount);
event PartnerAddressChanged(address newAddress);
event PodRewardsAndTokenContractsChanged(
ITokenRewards newpodTokenRewardsContract,
IPodToken newpodTokenContract
);
constructor(
ITokenRewards _podTokenRewardsContract,
IPodToken _podTokenContract
) {
require(
address(_podTokenRewardsContract) != address(0),
"EEFIFurnance: Invalid pod token rewards contract address."
);
require(
address(_podTokenContract) != address(0),
"EEFIFurnance: Invalid pod token contract address."
);
podTokenRewardsContract = _podTokenRewardsContract;
podTokenContract = _podTokenContract;
}
modifier multiSigOnly() {
require(msg.sender == TREASURY, "EEFIFurnance: Multisig not caller");
_;
}
function resetRewardsAndTokenAddresses(
ITokenRewards _newRewardsContract,
IPodToken _newPodTokenContract
) external onlyOwner {
podTokenRewardsContract = _newRewardsContract;
podTokenContract = _newPodTokenContract;
emit PodRewardsAndTokenContractsChanged(
_newRewardsContract,
_newPodTokenContract
);
}
function transferAssetsFromFurnance(
IERC20 token,
address to,
uint256 amount
) public multiSigOnly {
uint256 erc20balance = token.balanceOf(address(this));
require(
amount <= erc20balance,
"EEFIFurnance: Balance too low to transfer token"
);
TransferHelper.safeTransfer(address(token), to, amount);
}
function _convertAssetToWETH(
bytes calldata swapCallData,
address spender,
address payable swapTarget,
IERC20 sellToken,
IWETH buyToken,
uint256 sellAmount
) internal {
require(buyToken == weth, "EEFIFurnance: Buy token not WETH.");
if (address(sellToken) == _USDT) {
uint256 initialUSDTApprovalAmount = 0;
TransferHelper.safeApprove(
address(sellToken),
address(spender),
initialUSDTApprovalAmount
);
}
TransferHelper.safeApprove(
address(weth),
address(spender),
type(uint256).max
);
TransferHelper.safeApprove(
address(sellToken),
address(spender),
sellAmount
);
(bool success, ) = swapTarget.call{value: msg.value}(swapCallData);
require(success, "EEFIFurnance: Swap failed. Low balance / error.");
}
function convertAssetToWETH(
bytes calldata swapCallData,
address spender,
address payable swapTarget,
IERC20 sellToken,
IWETH buyToken,
uint256 sellAmount
) external payable onlyOwner {
_convertAssetToWETH(
swapCallData,
spender,
swapTarget,
sellToken,
buyToken,
sellAmount
);
}
function buyAndBurnEEFI(
bytes calldata swapCallData,
address spender,
address payable swapTarget,
IWETH sellToken,
IEEFIToken buyToken
) external payable onlyOwner {
require(sellToken == weth, "EEFIFurnance: Sell token not WETH.");
require(buyToken == eefi, "EEFIFurnance: Buy token not EEFI.");
require(
weth.balanceOf(address(this)) > 0,
"EEFIFurnance: No WETH available to trade"
);
TransferHelper.safeApprove(
address(weth),
address(spender),
type(uint256).max
);
(bool success, ) = swapTarget.call{value: msg.value}(swapCallData);
require(success, "EEFIFurnance: Swap failed. Low balance / error.");
uint256 _contractEEFIAmount = eefi.balanceOf(address(this));
require(
_contractEEFIAmount > 0,
"EEFIFurnance: Insufficient EEFI in contract to burn"
);
eefi.burn(_contractEEFIAmount);
emit EEFIBurn(address(this), _contractEEFIAmount);
}
function claimPEASAndConvertToWETH(
address claimAddress,
uint256 claimableReward,
bytes calldata swapCallData,
address spender,
address payable swapTarget,
IERC20 sellToken,
IWETH buyToken,
uint256 sellAmount,
uint256 buyAmount,
bool sendWETHToTreasury
) external payable onlyOwner {
require(claimableReward > 0, "EEFIFurnance: No rewards to claim");
require(buyToken == weth, "EEFIFurnance: Buy token not WETH");
podTokenRewardsContract.claimReward(claimAddress);
emit PEASRewardsClaimed(claimAddress, claimableReward);
uint256 peasTokenBalance = IERC20(_PEAS).balanceOf(address(this));
require(
peasTokenBalance > 0,
"EEFIFurnance: No rewards to convert"
);
_convertAssetToWETH(
swapCallData,
spender,
swapTarget,
sellToken,
buyToken,
sellAmount
);
if (sendWETHToTreasury == true) {
TransferHelper.safeTransfer(_WETH, TREASURY, buyAmount);
}
}
function claimLPRewardsAndSendToTreasury(
address claimAddress,
uint256 claimableReward
) external payable onlyOwner {
require(claimableReward > 0, "EEFIFurnance: No rewards to claim");
podTokenRewardsContract.claimReward(claimAddress);
emit PEASRewardsClaimed(claimAddress, claimableReward);
uint256 peasTokenBalance = IERC20(_PEAS).balanceOf(address(this));
if (peasTokenBalance > 0) {
TransferHelper.safeTransfer(_PEAS, TREASURY, peasTokenBalance);
emit PEASRewardsTransferred(TREASURY, peasTokenBalance);
}
}
function unWrapAndBurnPToken(
address pTokenToUnwrap,
uint8 tokenIndex,
bool sendPTokenToTreasury
) external onlyOwner {
uint256 pTokenAmount = podTokenContract.balanceOf(address(this));
address[] memory unwrappedPToken = new address[](1);
uint8[] memory unwrapPercentage = new uint8[](1);
unwrappedPToken[0] = pTokenToUnwrap;
unwrapPercentage[0] = 100;
require(
pTokenAmount > 0,
"EEFIFurnance: Not enough pToken in contract to unwrap"
);
podTokenContract.debond(
pTokenAmount,
unwrappedPToken,
unwrapPercentage
);
if (sendPTokenToTreasury == true) {
(address podTokenAddress, , , , ) = podTokenContract.indexTokens(
tokenIndex
);
uint256 unwrappedTokenAmount = IERC20(podTokenAddress).balanceOf(
address(this)
);
TransferHelper.safeTransfer(
podTokenAddress,
TREASURY,
unwrappedTokenAmount
);
}
uint256 _contractEEFIAmount = eefi.balanceOf(address(this));
if (_contractEEFIAmount > 0) {
eefi.burn(_contractEEFIAmount);
emit EEFIBurn(address(this), _contractEEFIAmount);
}
}
function resetPartnerAddress(address _newPartner) external onlyOwner {
newPartnerAddress = _newPartner;
podTokenContract.setPartner(newPartnerAddress);
emit PartnerAddressChanged(_newPartner);
}
}
文件 3 的 8:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 4 的 8:IERCWETHInterfaces.sol
pragma solidity >=0.4.23 <0.9.0;
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(
address owner,
address spender
) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
interface IWETH is IERC20 {
function deposit() external payable;
function withdraw(uint amount) external;
}
interface IEEFIToken is IERC20 {
function mint(address to, uint256 amount) external;
function burn(uint256 amount) external;
}
文件 5 的 8:IPodToken.sol
pragma solidity >=0.4.23 <0.9.0;
interface IPodToken {
function balanceOf(address account) external view returns (uint);
function approve(address spender, uint256 amount) external returns (bool);
function debond(uint256 _amount, address[] memory, uint8[] memory) external;
function indexTokens(uint256) external view returns (address _address, uint256 _weight, uint256 _basePrice, address _c1, uint256 _q1);
function transfer(address recipient, uint amount) external returns (bool);
function setPartner(address _partner) external;
}
文件 6 的 8:ITokenRewards.sol
pragma solidity >=0.4.23 <0.9.0;
interface ITokenRewards {
function getUnpaid(address _wallet) external returns (uint256);
function claimReward(address wallet) external;
}
文件 7 的 8:Ownable.sol
pragma solidity ^0.8.0;
import "Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 8 的 8:TransferHelper.sol
pragma solidity >=0.6.0;
import "IERC20.sol";
library TransferHelper {
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
}
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'STE');
}
}
{
"compilationTarget": {
"EEFI_Furnace.sol": "EEFIFurnace"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ITokenRewards","name":"_podTokenRewardsContract","type":"address"},{"internalType":"contract IPodToken","name":"_podTokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EEFIBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PEASRewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PEASRewardsTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PTokenUnwrapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"PartnerAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract ITokenRewards","name":"newpodTokenRewardsContract","type":"address"},{"indexed":false,"internalType":"contract IPodToken","name":"newpodTokenContract","type":"address"}],"name":"PodRewardsAndTokenContractsChanged","type":"event"},{"inputs":[{"internalType":"bytes","name":"swapCallData","type":"bytes"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"address payable","name":"swapTarget","type":"address"},{"internalType":"contract IWETH","name":"sellToken","type":"address"},{"internalType":"contract IEEFIToken","name":"buyToken","type":"address"}],"name":"buyAndBurnEEFI","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"claimAddress","type":"address"},{"internalType":"uint256","name":"claimableReward","type":"uint256"}],"name":"claimLPRewardsAndSendToTreasury","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"claimAddress","type":"address"},{"internalType":"uint256","name":"claimableReward","type":"uint256"},{"internalType":"bytes","name":"swapCallData","type":"bytes"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"address payable","name":"swapTarget","type":"address"},{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IWETH","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"bool","name":"sendWETHToTreasury","type":"bool"}],"name":"claimPEASAndConvertToWETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"swapCallData","type":"bytes"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"address payable","name":"swapTarget","type":"address"},{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IWETH","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"}],"name":"convertAssetToWETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"eefi","outputs":[{"internalType":"contract IEEFIToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newPartnerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"podTokenContract","outputs":[{"internalType":"contract IPodToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"podTokenRewardsContract","outputs":[{"internalType":"contract ITokenRewards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPartner","type":"address"}],"name":"resetPartnerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ITokenRewards","name":"_newRewardsContract","type":"address"},{"internalType":"contract IPodToken","name":"_newPodTokenContract","type":"address"}],"name":"resetRewardsAndTokenAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sendToTreasury","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferAssetsFromFurnance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pTokenToUnwrap","type":"address"},{"internalType":"uint8","name":"tokenIndex","type":"uint8"},{"internalType":"bool","name":"sendPTokenToTreasury","type":"bool"}],"name":"unWrapAndBurnPToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"}]