文件 1 的 10: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 的 10:IConditional.sol
pragma solidity ^0.8.4;
interface IConditional {
function passesTest(address wallet) external view returns (bool);
}
文件 3 的 10:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 4 的 10:IMultiplier.sol
pragma solidity ^0.8.4;
interface IMultiplier {
function getMultiplier(address wallet) external view returns (uint256);
}
文件 5 的 10:IUniswapV2Router01.sol
pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
文件 6 的 10:IUniswapV2Router02.sol
pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
文件 7 的 10:OKLGDividendDistributor.sol
pragma solidity ^0.8.4;
import '@openzeppelin/contracts/utils/math/SafeMath.sol';
import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';
import './interfaces/IConditional.sol';
import './interfaces/IMultiplier.sol';
import './OKLGWithdrawable.sol';
contract OKLGDividendDistributor is OKLGWithdrawable {
using SafeMath for uint256;
struct Dividend {
uint256 totalExcluded;
uint256 totalRealised;
uint256 lastClaim;
}
address public shareholderToken;
uint256 public totalSharesDeposited;
address wrappedNative;
IUniswapV2Router02 router;
address[] public tokens;
mapping(address => bool) tokenAwareness;
mapping(address => uint256) shareholderClaims;
mapping(address => uint256) public shares;
mapping(address => mapping(address => Dividend)) public dividends;
address public boostContract;
address public boostMultiplierContract;
uint256 public floorBoostClaimTimeSeconds = 60 * 60 * 12;
uint256 public ceilBoostClaimTimeSeconds = 60 * 60 * 24;
mapping(address => uint256) public totalDividends;
mapping(address => uint256) public totalDistributed;
mapping(address => uint256) public dividendsPerShare;
uint256 public constant ACC_FACTOR = 10**36;
address public constant DEAD = 0x000000000000000000000000000000000000dEaD;
constructor(
address _dexRouter,
address _shareholderToken,
address _wrappedNative
) {
router = IUniswapV2Router02(_dexRouter);
shareholderToken = _shareholderToken;
wrappedNative = _wrappedNative;
}
function stake(address token, uint256 amount) external {
_stake(msg.sender, token, amount, false);
}
function _stake(
address shareholder,
address token,
uint256 amount,
bool contractOverride
) private {
if (shares[shareholder] > 0 && !contractOverride) {
distributeDividend(token, shareholder, false);
}
IERC20 shareContract = IERC20(shareholderToken);
uint256 stakeAmount = amount == 0
? shareContract.balanceOf(shareholder)
: amount;
uint256 finalAmount = amount;
if (!contractOverride) {
uint256 shareBalanceBefore = shareContract.balanceOf(address(this));
shareContract.transferFrom(shareholder, address(this), stakeAmount);
finalAmount = shareContract.balanceOf(address(this)).sub(
shareBalanceBefore
);
}
totalSharesDeposited = totalSharesDeposited.add(finalAmount);
shares[shareholder] += finalAmount;
dividends[shareholder][token].totalExcluded = getCumulativeDividends(
token,
shares[shareholder]
);
}
function unstake(address token, uint256 amount) external {
require(
shares[msg.sender] > 0 && (amount == 0 || shares[msg.sender] <= amount),
'you can only unstake if you have some staked'
);
distributeDividend(token, msg.sender, false);
IERC20 shareContract = IERC20(shareholderToken);
uint256 baseWithdrawAmount = amount == 0 ? shares[msg.sender] : amount;
uint256 totalSharesBalance = shareContract.balanceOf(address(this)).sub(
totalDividends[shareholderToken].sub(totalDistributed[shareholderToken])
);
uint256 appreciationRatio18 = totalSharesBalance.mul(10**18).div(
totalSharesDeposited
);
uint256 finalWithdrawAmount = baseWithdrawAmount
.mul(appreciationRatio18)
.div(10**18);
shareContract.transfer(msg.sender, finalWithdrawAmount);
totalSharesDeposited = totalSharesDeposited.sub(baseWithdrawAmount);
shares[msg.sender] -= baseWithdrawAmount;
dividends[msg.sender][token].totalExcluded = getCumulativeDividends(
token,
shares[msg.sender]
);
}
function depositDividends(address tokenAddress, uint256 erc20DirectAmount)
external
payable
{
require(
erc20DirectAmount > 0 || msg.value > 0,
'value must be greater than 0'
);
require(
totalSharesDeposited > 0,
'must be shares deposited to be rewarded dividends'
);
if (!tokenAwareness[tokenAddress]) {
tokenAwareness[tokenAddress] = true;
tokens.push(tokenAddress);
}
IERC20 token;
uint256 amount;
if (tokenAddress == address(0)) {
payable(address(this)).call{ value: msg.value }('');
amount = msg.value;
} else if (erc20DirectAmount > 0) {
token = IERC20(tokenAddress);
uint256 balanceBefore = token.balanceOf(address(this));
token.transferFrom(msg.sender, address(this), erc20DirectAmount);
amount = token.balanceOf(address(this)).sub(balanceBefore);
} else {
token = IERC20(tokenAddress);
uint256 balanceBefore = token.balanceOf(address(this));
address[] memory path = new address[](2);
path[0] = wrappedNative;
path[1] = tokenAddress;
router.swapExactETHForTokensSupportingFeeOnTransferTokens{
value: msg.value
}(0, path, address(this), block.timestamp);
amount = token.balanceOf(address(this)).sub(balanceBefore);
}
totalDividends[tokenAddress] = totalDividends[tokenAddress].add(amount);
dividendsPerShare[tokenAddress] = dividendsPerShare[tokenAddress].add(
ACC_FACTOR.mul(amount).div(totalSharesDeposited)
);
}
function distributeDividend(
address token,
address shareholder,
bool compound
) internal {
if (shares[shareholder] == 0) {
return;
}
uint256 amount = getUnpaidEarnings(token, shareholder);
if (amount > 0) {
totalDistributed[token] = totalDistributed[token].add(amount);
if (token == address(0)) {
if (compound) {
IERC20 shareToken = IERC20(shareholderToken);
uint256 balBefore = shareToken.balanceOf(address(this));
address[] memory path = new address[](2);
path[0] = wrappedNative;
path[1] = shareholderToken;
router.swapExactETHForTokensSupportingFeeOnTransferTokens{
value: amount
}(0, path, address(this), block.timestamp);
uint256 amountReceived = shareToken.balanceOf(address(this)).sub(
balBefore
);
if (amountReceived > 0) {
_stake(shareholder, token, amountReceived, true);
}
} else {
payable(shareholder).call{ value: amount }('');
}
} else {
IERC20(token).transfer(shareholder, amount);
}
_payBoostedRewards(token, shareholder);
shareholderClaims[shareholder] = block.timestamp;
dividends[shareholder][token].totalRealised = dividends[shareholder][
token
].totalRealised.add(amount);
dividends[shareholder][token].totalExcluded = getCumulativeDividends(
token,
shares[shareholder]
);
dividends[shareholder][token].lastClaim = block.timestamp;
}
}
function _payBoostedRewards(address token, address shareholder) internal {
bool canCurrentlyClaim = canClaimBoostedRewards(token, shareholder) &&
eligibleForRewardBooster(shareholder);
if (!canCurrentlyClaim) {
return;
}
uint256 amount = calculateBoostRewards(token, shareholder);
if (amount > 0) {
if (token == address(0)) {
payable(shareholder).call{ value: amount }('');
} else {
IERC20(token).transfer(shareholder, amount);
}
}
}
function claimDividend(address token, bool compound) external {
distributeDividend(token, msg.sender, compound);
}
function canClaimBoostedRewards(address token, address shareholder)
public
view
returns (bool)
{
return
dividends[shareholder][token].lastClaim == 0 ||
(block.timestamp >
dividends[shareholder][token].lastClaim.add(
floorBoostClaimTimeSeconds
) &&
block.timestamp <=
dividends[shareholder][token].lastClaim.add(ceilBoostClaimTimeSeconds));
}
function getDividendTokens() external view returns (address[] memory) {
return tokens;
}
function getBoostMultiplier(address wallet) public view returns (uint256) {
return
boostMultiplierContract == address(0)
? 0
: IMultiplier(boostMultiplierContract).getMultiplier(wallet);
}
function calculateBoostRewards(address token, address shareholder)
public
view
returns (uint256)
{
IERC20 shareToken = IERC20(shareholderToken);
uint256 totalCirculatingShareTokens = shareToken.totalSupply() -
shareToken.balanceOf(DEAD);
uint256 availableBoostRewards = address(this).balance;
if (token != address(0)) {
availableBoostRewards = IERC20(token).balanceOf(address(this));
}
uint256 excluded = totalDividends[token].sub(totalDistributed[token]);
uint256 finalAvailableBoostRewards = availableBoostRewards.sub(excluded);
uint256 userShareBoostRewards = finalAvailableBoostRewards
.mul(shares[shareholder])
.div(totalCirculatingShareTokens);
uint256 rewardsWithBooster = eligibleForRewardBooster(shareholder)
? userShareBoostRewards.add(
userShareBoostRewards.mul(getBoostMultiplier(shareholder)).div(10**2)
)
: userShareBoostRewards;
return
rewardsWithBooster > finalAvailableBoostRewards
? finalAvailableBoostRewards
: rewardsWithBooster;
}
function eligibleForRewardBooster(address shareholder)
public
view
returns (bool)
{
return
boostContract != address(0) &&
IConditional(boostContract).passesTest(shareholder);
}
function getUnpaidEarnings(address token, address shareholder)
public
view
returns (uint256)
{
if (shares[shareholder] == 0) {
return 0;
}
uint256 earnedDividends = getCumulativeDividends(
token,
shares[shareholder]
);
uint256 dividendsExcluded = dividends[shareholder][token].totalExcluded;
if (earnedDividends <= dividendsExcluded) {
return 0;
}
return earnedDividends.sub(dividendsExcluded);
}
function getCumulativeDividends(address token, uint256 share)
internal
view
returns (uint256)
{
return share.mul(dividendsPerShare[token]).div(ACC_FACTOR);
}
function setShareholderToken(address _token) external onlyOwner {
shareholderToken = _token;
}
function setBoostClaimTimeInfo(uint256 floor, uint256 ceil)
external
onlyOwner
{
floorBoostClaimTimeSeconds = floor;
ceilBoostClaimTimeSeconds = ceil;
}
function setBoostContract(address _contract) external onlyOwner {
if (_contract != address(0)) {
IConditional _contCheck = IConditional(_contract);
require(
_contCheck.passesTest(address(0)) == true ||
_contCheck.passesTest(address(0)) == false,
'contract does not implement interface'
);
}
boostContract = _contract;
}
function setBoostMultiplierContract(address _contract) external onlyOwner {
if (_contract != address(0)) {
IMultiplier _contCheck = IMultiplier(_contract);
require(
_contCheck.getMultiplier(address(0)) >= 0,
'contract does not implement interface'
);
}
boostMultiplierContract = _contract;
}
receive() external payable {}
}
文件 8 的 10:OKLGWithdrawable.sol
pragma solidity ^0.8.4;
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/interfaces/IERC20.sol';
contract OKLGWithdrawable is Ownable {
function withdrawTokens(address _tokenAddy, uint256 _amount)
external
onlyOwner
{
IERC20 _token = IERC20(_tokenAddy);
_amount = _amount > 0 ? _amount : _token.balanceOf(address(this));
require(_amount > 0, 'make sure there is a balance available to withdraw');
_token.transfer(owner(), _amount);
}
function withdrawETH() external onlyOwner {
payable(owner()).call{ value: address(this).balance }('');
}
}
文件 9 的 10:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
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);
}
}
文件 10 的 10:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
{
"compilationTarget": {
"contracts/OKLGDividendDistributor.sol": "OKLGDividendDistributor"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_dexRouter","type":"address"},{"internalType":"address","name":"_shareholderToken","type":"address"},{"internalType":"address","name":"_wrappedNative","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"ACC_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEAD","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boostContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boostMultiplierContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"shareholder","type":"address"}],"name":"calculateBoostRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"shareholder","type":"address"}],"name":"canClaimBoostedRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ceilBoostClaimTimeSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"compound","type":"bool"}],"name":"claimDividend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"erc20DirectAmount","type":"uint256"}],"name":"depositDividends","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"dividends","outputs":[{"internalType":"uint256","name":"totalExcluded","type":"uint256"},{"internalType":"uint256","name":"totalRealised","type":"uint256"},{"internalType":"uint256","name":"lastClaim","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"dividendsPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"shareholder","type":"address"}],"name":"eligibleForRewardBooster","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"floorBoostClaimTimeSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getBoostMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDividendTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"shareholder","type":"address"}],"name":"getUnpaidEarnings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"floor","type":"uint256"},{"internalType":"uint256","name":"ceil","type":"uint256"}],"name":"setBoostClaimTimeInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"}],"name":"setBoostContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"}],"name":"setBoostMultiplierContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"setShareholderToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shareholderToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalDividends","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSharesDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddy","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]