编译器
0.8.24+commit.e11b9ed9
文件 1 的 11:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 11:Arrays.sol
pragma solidity ^0.8.0;
library Arrays {
function sort(
bytes32[] memory array,
function(bytes32, bytes32) pure returns (bool) comp
) internal pure returns (bytes32[] memory) {
_quickSort(_begin(array), _end(array), comp);
return array;
}
function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {
return sort(array, _defaultComp);
}
function sort(
address[] memory array,
function(address, address) pure returns (bool) comp
) internal pure returns (address[] memory) {
sort(_castToBytes32Array(array), _castToBytes32Comp(comp));
return array;
}
function sort(address[] memory array) internal pure returns (address[] memory) {
sort(_castToBytes32Array(array), _defaultComp);
return array;
}
function sort(
uint256[] memory array,
function(uint256, uint256) pure returns (bool) comp
) internal pure returns (uint256[] memory) {
sort(_castToBytes32Array(array), _castToBytes32Comp(comp));
return array;
}
function sort(uint256[] memory array) internal pure returns (uint256[] memory) {
sort(_castToBytes32Array(array), _defaultComp);
return array;
}
function _quickSort(uint256 begin, uint256 end, function(bytes32, bytes32) pure returns (bool) comp) private pure {
unchecked {
if (end - begin < 0x40) return;
bytes32 pivot = _mload(begin);
uint256 pos = begin;
for (uint256 it = begin + 0x20; it < end; it += 0x20) {
if (comp(_mload(it), pivot)) {
pos += 0x20;
_swap(pos, it);
}
}
_swap(begin, pos);
_quickSort(begin, pos, comp);
_quickSort(pos + 0x20, end, comp);
}
}
function _begin(bytes32[] memory array) private pure returns (uint256 ptr) {
assembly {
ptr := add(array, 0x20)
}
}
function _end(bytes32[] memory array) private pure returns (uint256 ptr) {
unchecked {
return _begin(array) + array.length * 0x20;
}
}
function _mload(uint256 ptr) private pure returns (bytes32 value) {
assembly {
value := mload(ptr)
}
}
function _swap(uint256 ptr1, uint256 ptr2) private pure {
assembly {
let value1 := mload(ptr1)
let value2 := mload(ptr2)
mstore(ptr1, value2)
mstore(ptr2, value1)
}
}
function _defaultComp(bytes32 a, bytes32 b) private pure returns (bool) {
return a < b;
}
function _castToBytes32Array(address[] memory input) private pure returns (bytes32[] memory output) {
assembly {
output := input
}
}
function _castToBytes32Array(uint256[] memory input) private pure returns (bytes32[] memory output) {
assembly {
output := input
}
}
function _castToBytes32Comp(
function(address, address) pure returns (bool) input
) private pure returns (function(bytes32, bytes32) pure returns (bool) output) {
assembly {
output := input
}
}
function _castToBytes32Comp(
function(uint256, uint256) pure returns (bool) input
) private pure returns (function(bytes32, bytes32) pure returns (bool) output) {
assembly {
output := input
}
}
}
文件 3 的 11:Counters.sol
pragma solidity ^0.8.0;
library Counters {
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}
文件 4 的 11:Helper.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/utils/Address.sol";
library Helper {
enum Status {
LISTED,
UPDATED,
APPROVED_LISTING,
APPROVED_FUNDING,
REJECTED,
REPLACED
}
enum TokenType {
ERC20,
ERC721,
ERC1155
}
function safeApprove(
address token,
address to,
uint256 value
) internal {
require(Address.isContract(token), "C");
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeApprove: approve failed");
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
require(Address.isContract(token), "C");
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), "VabbleDAO::safeTransfer: transfer failed");
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
require(Address.isContract(token), "C");
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), "VabbleDAO::transferFrom: transferFrom failed");
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "VabbleDAO::safeTransferETH: ETH transfer failed");
}
function safeTransferAsset(
address token,
address to,
uint256 value
) internal {
if (token == address(0)) {
safeTransferETH(to, value);
} else {
safeTransfer(token, to, value);
}
}
function isContract(address _address) internal view returns(bool){
return Address.isContract(_address);
}
function isTestNet() internal view returns (bool) {
uint256 id = block.chainid;
return id == 1337 || id == 80001 || id == 80002 || id == 31337 || id == 84532;
}
}
文件 5 的 11: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);
}
文件 6 的 11:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 7 的 11:IOwnablee.sol
pragma solidity ^0.8.4;
interface IOwnablee {
function auditor() external view returns (address);
function deployer() external view returns (address);
function replaceAuditor(address _newAuditor) external;
function transferAuditor(address _newAuditor) external;
function isDepositAsset(address _asset) external view returns (bool);
function getDepositAssetList() external view returns (address[] memory);
function VAB_WALLET() external view returns (address);
function USDC_TOKEN() external view returns (address);
function PAYOUT_TOKEN() external view returns (address);
function addToStudioPool(uint256 _amount) external;
function withdrawVABFromEdgePool(address _to) external returns (uint256);
}
文件 8 的 11:IProperty.sol
pragma solidity ^0.8.4;
import "../libraries/Helper.sol";
interface IProperty {
function filmVotePeriod() external view returns (uint256);
function agentVotePeriod() external view returns (uint256);
function disputeGracePeriod() external view returns (uint256);
function propertyVotePeriod() external view returns (uint256);
function lockPeriod() external view returns (uint256);
function rewardRate() external view returns (uint256);
function filmRewardClaimPeriod() external view returns (uint256);
function maxAllowPeriod() external view returns (uint256);
function proposalFeeAmount() external view returns (uint256);
function fundFeePercent() external view returns (uint256);
function minDepositAmount() external view returns (uint256);
function maxDepositAmount() external view returns (uint256);
function maxMintFeePercent() external view returns (uint256);
function minVoteCount() external view returns (uint256);
function minStakerCountPercent() external view returns (uint256);
function availableVABAmount() external view returns (uint256);
function boardVotePeriod() external view returns (uint256);
function boardVoteWeight() external view returns (uint256);
function rewardVotePeriod() external view returns (uint256);
function subscriptionAmount() external view returns (uint256);
function boardRewardRate() external view returns (uint256);
function DAO_FUND_REWARD() external view returns (address);
function updateLastVoteTime(address _member) external;
function getPropertyProposalInfo(uint256 _index, uint256 _flag) external view returns (uint256, uint256, uint256, uint256, address, Helper.Status);
function getGovProposalInfo(uint256 _index, uint256 _flag) external view returns (uint256, uint256, uint256, address, address, Helper.Status);
function updatePropertyProposal(uint256 _index, uint256 _flag, uint256 _approveStatus) external;
function updateGovProposal(uint256 _index, uint256 _flag, uint256 _approveStatus) external;
function checkGovWhitelist(uint256 _flag, address _address) external view returns (uint256);
function checkPropertyWhitelist(uint256 _flag, uint256 _property) external view returns (uint256);
function getAgentProposerStakeAmount(uint256 _index) external view returns (uint256);
}
文件 9 的 11:IVabbleDAO.sol
pragma solidity ^0.8.4;
import "../libraries/Helper.sol";
interface IVabbleDAO {
struct Film {
string title;
string description;
uint256[] sharePercents;
address[] studioPayees;
uint256 raiseAmount;
uint256 fundPeriod;
uint256 fundType;
uint256 rewardPercent;
uint256 noVote;
uint256 enableClaimer;
uint256 pCreateTime;
uint256 pApproveTime;
address studio;
Helper.Status status;
}
function getFilmFund(uint256 _filmId)
external
view
returns (uint256 raiseAmount_, uint256 fundPeriod_, uint256 fundType_, uint256 rewardPercent_);
function getFilmStatus(uint256 _filmId) external view returns (Helper.Status status_);
function getFilmOwner(uint256 _filmId) external view returns (address owner_);
function getFilmProposalTime(uint256 _filmId) external view returns (uint256 cTime_, uint256 aTime_);
function approveFilmByVote(uint256 _filmId, uint256 _flag) external;
function isEnabledClaimer(uint256 _filmId) external view returns (bool enable_);
function getFilmShare(uint256 _filmId)
external
view
returns (uint256[] memory sharePercents_, address[] memory studioPayees_);
function getUserFilmListForMigrate(address _user) external view returns (Film[] memory filmList_);
function withdrawVABFromStudioPool(address _to) external returns (uint256);
}
文件 10 的 11:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
文件 11 的 11:StakingPool.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "../libraries/Helper.sol";
import "../libraries/Arrays.sol";
import "../interfaces/IVabbleDAO.sol";
import "../interfaces/IProperty.sol";
import "../interfaces/IOwnablee.sol";
contract StakingPool is ReentrancyGuard {
using Counters for Counters.Counter;
using Arrays for uint256[];
event TokenStaked(address indexed staker, uint256 stakeAmount);
event TokenUnstaked(address indexed unstaker, uint256 unStakeAmount);
event RewardWithdraw(address indexed staker, uint256 rewardAmount);
event RewardContinued(address indexed staker, uint256 isCompound, uint256 rewardAmount);
event AllFundWithdraw(address to, uint256 amount);
event RewardAdded(uint256 totalRewardAmount, uint256 rewardAmount, address indexed contributor);
event VABDeposited(address indexed customer, uint256 amount);
event WithdrawPending(address indexed customer, uint256 amount);
event PendingWithdrawApproved(address[] customers, uint256[] withdrawAmounts);
event PendingWithdrawDenied(address[] customers);
struct Staker {
address[] keys;
mapping(address => uint256) indexOf;
}
struct Stake {
uint256 stakeAmount;
uint256 stakeTime;
uint256 outstandingReward;
}
struct UserRent {
uint256 vabAmount;
uint256 withdrawAmount;
bool pending;
}
struct Props {
address creator;
uint256 cTime;
uint256 period;
uint256 proposalID;
}
address private immutable OWNABLE;
address private VOTE;
address private VABBLE_DAO;
address private DAO_PROPERTY;
uint256 public totalStakingAmount;
uint256 public totalRewardAmount;
uint256 public totalRewardIssuedAmount;
uint256 public lastfundProposalCreateTime;
uint256 public migrationStatus = 0;
uint256 public totalMigrationVAB = 0;
mapping(address => mapping(uint256 => uint256)) private votedTime;
mapping(address => Stake) public stakeInfo;
mapping(address => uint256) public receivedRewardAmount;
mapping(address => UserRent) public userRentInfo;
mapping(address => uint256) public minProposalIndex;
Counters.Counter public proposalCount;
Staker private stakerMap;
Props[] private propsList;
modifier onlyVote() {
require(msg.sender == VOTE, "not vote");
_;
}
modifier onlyDAO() {
require(msg.sender == VABBLE_DAO, "not dao");
_;
}
modifier onlyAuditor() {
require(msg.sender == IOwnablee(OWNABLE).auditor(), "not auditor");
_;
}
modifier onlyDeployer() {
require(msg.sender == IOwnablee(OWNABLE).deployer(), "not deployer");
_;
}
modifier onlyNormal() {
require(migrationStatus < 1, "Migration is on going");
_;
}
constructor(address _ownable) {
require(_ownable != address(0), "zero ownable");
OWNABLE = _ownable;
}
function initialize(address _vabbleDAO, address _property, address _vote) external onlyDeployer {
require(VABBLE_DAO == address(0), "init: initialized");
require(_vabbleDAO != address(0), "init: zero dao");
VABBLE_DAO = _vabbleDAO;
require(_property != address(0), "init: zero property");
DAO_PROPERTY = _property;
require(_vote != address(0), "init: zero vote");
VOTE = _vote;
}
function addRewardToPool(uint256 _amount) external onlyNormal nonReentrant {
require(_amount > 0, "aRTP: zero amount");
Helper.safeTransferFrom(IOwnablee(OWNABLE).PAYOUT_TOKEN(), msg.sender, address(this), _amount);
totalRewardAmount = totalRewardAmount + _amount;
emit RewardAdded(totalRewardAmount, _amount, msg.sender);
}
function stakeVAB(uint256 _amount) external onlyNormal nonReentrant {
require(_amount > 0, "sVAB: zero amount");
uint256 minAmount = 10 ** IERC20Metadata(IOwnablee(OWNABLE).PAYOUT_TOKEN()).decimals();
require(_amount > minAmount, "sVAB: min 1");
Helper.safeTransferFrom(IOwnablee(OWNABLE).PAYOUT_TOKEN(), msg.sender, address(this), _amount);
Stake storage si = stakeInfo[msg.sender];
if (si.stakeAmount == 0 && si.stakeTime == 0) {
__stakerSet(msg.sender);
}
si.outstandingReward += calcRealizedRewards(msg.sender);
si.stakeAmount += _amount;
si.stakeTime = block.timestamp;
totalStakingAmount += _amount;
__updateMinProposalIndex(msg.sender);
emit TokenStaked(msg.sender, _amount);
}
function unstakeVAB(uint256 _amount) external nonReentrant {
require(msg.sender != address(0), "usVAB: zero staker");
Stake storage si = stakeInfo[msg.sender];
uint256 withdrawTime = si.stakeTime + IProperty(DAO_PROPERTY).lockPeriod();
require(si.stakeAmount >= _amount, "usVAB: insufficient");
require(migrationStatus > 0 || block.timestamp > withdrawTime, "usVAB: lock");
uint256 rewardAmount = calcRewardAmount(msg.sender);
if (totalRewardAmount >= rewardAmount && rewardAmount > 0) {
__withdrawReward(rewardAmount);
}
Helper.safeTransfer(IOwnablee(OWNABLE).PAYOUT_TOKEN(), msg.sender, _amount);
si.stakeTime = block.timestamp;
si.stakeAmount -= _amount;
totalStakingAmount -= _amount;
if (si.stakeAmount == 0) {
delete stakeInfo[msg.sender];
__stakerRemove(msg.sender);
}
emit TokenUnstaked(msg.sender, _amount);
}
function withdrawReward(uint256 _isCompound) external nonReentrant {
require(_isCompound == 0 || _isCompound == 1, "wR: compound");
require(stakeInfo[msg.sender].stakeAmount > 0, "wR: zero amount");
uint256 withdrawTime = stakeInfo[msg.sender].stakeTime + IProperty(DAO_PROPERTY).lockPeriod();
require(migrationStatus > 0 || block.timestamp > withdrawTime, "wR: lock");
if (migrationStatus > 0) {
require(_isCompound == 0, "migration is on going");
}
uint256 rewardAmount = calcRewardAmount(msg.sender);
require(rewardAmount > 0, "wR: zero reward");
if (_isCompound == 1) {
Stake storage si = stakeInfo[msg.sender];
si.stakeAmount = si.stakeAmount + rewardAmount;
si.stakeTime = block.timestamp;
si.outstandingReward = 0;
totalStakingAmount += rewardAmount;
__updateMinProposalIndex(msg.sender);
emit RewardContinued(msg.sender, _isCompound, rewardAmount);
} else {
require(totalRewardAmount >= rewardAmount, "wR: insufficient total");
__withdrawReward(rewardAmount);
}
}
function __withdrawReward(uint256 _amount) private {
Helper.safeTransfer(IOwnablee(OWNABLE).PAYOUT_TOKEN(), msg.sender, _amount);
totalRewardAmount -= _amount;
receivedRewardAmount[msg.sender] += _amount;
totalRewardIssuedAmount += _amount;
stakeInfo[msg.sender].stakeTime = block.timestamp;
stakeInfo[msg.sender].outstandingReward = 0;
emit RewardWithdraw(msg.sender, _amount);
__updateMinProposalIndex(msg.sender);
}
function calcRewardAmount(address _user) public view returns (uint256) {
Stake memory si = stakeInfo[_user];
if (si.stakeAmount == 0) return 0;
if (migrationStatus > 0) {
return si.outstandingReward;
} else {
return si.outstandingReward + calcRealizedRewards(_user);
}
}
function __calcProposalTimeIntervals(address _user) public view returns (uint256[] memory times_) {
uint256 pLength = propsList.length;
Props memory pData;
uint256 stakeTime = stakeInfo[_user].stakeTime;
uint256 end = block.timestamp;
uint256 count = 0;
uint256 minIndex = minProposalIndex[_user];
for (uint256 i = minIndex; i < pLength; ++i) {
if (propsList[i].cTime + propsList[i].period >= stakeInfo[_user].stakeTime) {
count++;
}
}
times_ = new uint256[](2 * count + 2);
times_[0] = stakeTime;
count = 0;
for (uint256 i = minIndex; i < pLength; ++i) {
pData = propsList[i];
if (pData.cTime + pData.period >= stakeTime) {
times_[2 * count + 1] = pData.cTime;
times_[2 * count + 2] = pData.cTime + pData.period;
if (times_[2 * count + 2] > end) {
times_[2 * count + 2] = end;
}
count++;
}
}
times_[2 * count + 1] = end;
times_.sort();
}
function __getProposalVoteCount(
address _user,
uint256 minIndex,
uint256 _start,
uint256 _end
)
public
view
returns (uint256, uint256, uint256)
{
uint256 pCount = 0;
uint256 vCount = 0;
uint256 pendingVoteCount = 0;
Props memory pData;
uint256 pLength = propsList.length;
for (uint256 j = minIndex; j < pLength; ++j) {
pData = propsList[j];
if (pData.cTime <= _start && _end <= pData.cTime + pData.period) {
pCount++;
if (pData.creator == _user || votedTime[_user][pData.proposalID] > 0) {
if (_start >= stakeInfo[_user].stakeTime) {
vCount += 1;
} else {
if (pData.creator == _user || votedTime[_user][pData.proposalID] <= stakeInfo[_user].stakeTime)
{
} else {
vCount += 1;
}
}
} else {
if (block.timestamp <= pData.cTime + pData.period) {
pendingVoteCount += 1;
}
}
}
}
return (pCount, vCount, pendingVoteCount);
}
function __updateMinProposalIndex(address _user) private {
uint256 pLength = propsList.length;
uint256 minIndex = minProposalIndex[_user];
for (uint256 i = minIndex; i < pLength; ++i) {
if (propsList[i].cTime + propsList[i].period >= stakeInfo[_user].stakeTime) {
minProposalIndex[_user] = i;
break;
}
}
}
function calcRealizedRewards(address _user) public view returns (uint256) {
uint256 realizeReward = 0;
uint256[] memory times = __calcProposalTimeIntervals(_user);
uint256 minIndex = minProposalIndex[_user];
uint256 intervalCount = times.length - 1;
uint256 start;
uint256 end;
uint256 amount = 0;
for (uint256 i = 0; i < intervalCount; ++i) {
start = times[i];
end = times[i + 1];
(uint256 pCount, uint256 vCount,) = __getProposalVoteCount(_user, minIndex, start, end);
amount = __calcRewards(_user, start, end);
if (pCount > 0) {
uint256 countRate = (vCount * 1e4) / pCount;
amount = (amount * countRate) / 1e4;
}
realizeReward += amount;
}
return realizeReward;
}
function calcPendingRewards(address _user) public view returns (uint256) {
uint256 pendingReward = 0;
uint256[] memory times = __calcProposalTimeIntervals(_user);
uint256 minIndex = minProposalIndex[_user];
uint256 intervalCount = times.length - 1;
uint256 start;
uint256 end;
uint256 amount = 0;
for (uint256 i = 0; i < intervalCount; ++i) {
start = times[i];
end = times[i + 1];
(uint256 pCount,, uint256 pendingVoteCount) = __getProposalVoteCount(_user, minIndex, start, end);
amount = __calcRewards(_user, start, end);
if (pCount > 0) {
uint256 countRate = (pendingVoteCount * 1e4) / pCount;
amount = (amount * countRate) / 1e4;
} else {
amount = 0;
}
pendingReward += amount;
}
return pendingReward;
}
function __calcRewards(address _user, uint256 startTime, uint256 endTime) private view returns (uint256 amount_) {
Stake memory si = stakeInfo[_user];
if (si.stakeAmount == 0) return 0;
if (startTime == 0) return 0;
uint256 rewardPercent = __rewardPercent(si.stakeAmount);
uint256 period = ((endTime - startTime) * 1e4) / 1 days;
amount_ = (totalRewardAmount * rewardPercent * period) / 1e10 / 1e4;
if (IProperty(DAO_PROPERTY).checkGovWhitelist(2, _user) == 2) {
amount_ += (amount_ * IProperty(DAO_PROPERTY).boardRewardRate()) / 1e10;
}
}
function __rewardPercent(uint256 _stakingAmount) private view returns (uint256 percent_) {
uint256 poolPercent = (_stakingAmount * 1e10) / totalStakingAmount;
percent_ = (IProperty(DAO_PROPERTY).rewardRate() * poolPercent) / 1e10;
}
function calculateAPR(
uint256 _period,
uint256 _stakeAmount,
uint256 _proposalCount,
uint256 _voteCount,
bool isBoardMember
)
external
view
returns (uint256 amount_)
{
require(_period > 0, "apr: zero period");
require(_stakeAmount > 0, "apr: zero staker");
require(_proposalCount >= _voteCount, "apr: bad vote count");
uint256 rewardPercent = __rewardPercent(_stakeAmount);
uint256 stakingRewards = (totalRewardAmount * rewardPercent * _period) / 1e10;
if (isBoardMember) {
stakingRewards += (stakingRewards * IProperty(DAO_PROPERTY).boardRewardRate()) / 1e10;
}
uint256 pendingRewards;
if (_proposalCount > 0) {
if (_voteCount == 0) {
pendingRewards = 0;
} else {
uint256 countVal = (_voteCount * 1e4) / _proposalCount;
pendingRewards = (stakingRewards * countVal) / 1e4;
}
}
amount_ = stakingRewards + pendingRewards;
}
function depositVAB(uint256 _amount) external onlyNormal nonReentrant {
_depositVAB(msg.sender, _amount);
}
function depositVABTo(address subscriber, uint256 _amount) external onlyNormal nonReentrant {
_depositVAB(subscriber, _amount);
}
function _depositVAB(address subscriber, uint256 _amount) private {
require(subscriber != address(0), "dVAB: zero address");
require(_amount > 0, "dVAB: zero amount");
Helper.safeTransferFrom(IOwnablee(OWNABLE).PAYOUT_TOKEN(), msg.sender, address(this), _amount);
userRentInfo[subscriber].vabAmount += _amount;
emit VABDeposited(subscriber, _amount);
}
function pendingWithdraw(uint256 _amount) external nonReentrant {
require(msg.sender != address(0), "pW: zero address");
require(_amount > 0, "pW: zero VAB");
require(!userRentInfo[msg.sender].pending, "pW: pending");
uint256 cAmount = userRentInfo[msg.sender].vabAmount;
uint256 wAmount = userRentInfo[msg.sender].withdrawAmount;
require(_amount <= cAmount - wAmount, "pW: insufficient VAB");
userRentInfo[msg.sender].withdrawAmount += _amount;
userRentInfo[msg.sender].pending = true;
emit WithdrawPending(msg.sender, _amount);
}
function approvePendingWithdraw(address[] calldata _customers) external onlyAuditor nonReentrant {
require(_customers.length > 0 && _customers.length < 1000, "aPW: No customer");
uint256[] memory withdrawAmounts = new uint256[](_customers.length);
uint256 customerLength = _customers.length;
for (uint256 i = 0; i < customerLength; ++i) {
withdrawAmounts[i] = __transferVABWithdraw(_customers[i]);
}
emit PendingWithdrawApproved(_customers, withdrawAmounts);
}
function __transferVABWithdraw(address _to) private returns (uint256) {
uint256 payAmount = userRentInfo[_to].withdrawAmount;
require(payAmount > 0, "aW: zero withdraw");
require(payAmount <= userRentInfo[_to].vabAmount, "aW: insufficuent");
require(userRentInfo[_to].pending, "aW: no pending");
Helper.safeTransfer(IOwnablee(OWNABLE).PAYOUT_TOKEN(), _to, payAmount);
userRentInfo[_to].vabAmount -= payAmount;
userRentInfo[_to].withdrawAmount = 0;
userRentInfo[_to].pending = false;
return payAmount;
}
function checkApprovePendingWithdraw(address[] calldata _customers) external view returns (bool) {
address _to;
uint256 payAmount;
uint256 sum = 0;
uint256 customerLength = _customers.length;
for (uint256 i = 0; i < customerLength; ++i) {
_to = _customers[i];
payAmount = userRentInfo[_to].withdrawAmount;
if (payAmount == 0) {
return false;
}
if (payAmount > userRentInfo[_to].vabAmount) {
return false;
}
if (!userRentInfo[_to].pending) {
return false;
}
sum += payAmount;
}
address vabToken = IOwnablee(OWNABLE).PAYOUT_TOKEN();
if (IERC20(vabToken).balanceOf(address(this)) < sum) {
return false;
}
return true;
}
function denyPendingWithdraw(address[] calldata _customers) external onlyAuditor nonReentrant {
require(_customers.length > 0 && _customers.length < 1000, "denyW: bad customers");
uint256 customerLength = _customers.length;
for (uint256 i = 0; i < customerLength; ++i) {
require(userRentInfo[_customers[i]].withdrawAmount > 0, "denyW: zero withdraw");
require(userRentInfo[_customers[i]].pending, "denyW: no pending");
userRentInfo[_customers[i]].withdrawAmount = 0;
userRentInfo[_customers[i]].pending = false;
}
emit PendingWithdrawDenied(_customers);
}
function checkDenyPendingWithDraw(address[] calldata _customers) external view returns (bool) {
uint256 customerLength = _customers.length;
for (uint256 i = 0; i < customerLength; ++i) {
if (userRentInfo[_customers[i]].withdrawAmount == 0) {
return false;
}
if (!userRentInfo[_customers[i]].pending) {
return false;
}
}
return true;
}
function sendVAB(
address[] calldata _users,
address _to,
uint256[] calldata _amounts
)
external
onlyDAO
returns (uint256)
{
require(_users.length == _amounts.length && _users.length < 1000, "sendVAB: bad array");
uint256 sum;
uint256 userLength = _users.length;
for (uint256 i = 0; i < userLength; ++i) {
require(userRentInfo[_users[i]].vabAmount >= _amounts[i], "sendVAB: insufficient");
userRentInfo[_users[i]].vabAmount -= _amounts[i];
sum += _amounts[i];
}
Helper.safeTransfer(IOwnablee(OWNABLE).PAYOUT_TOKEN(), _to, sum);
return sum;
}
function checkAllocateToPool(address[] calldata _users, uint256[] calldata _amounts) external view returns (bool) {
uint256 sum;
uint256 userLength = _users.length;
for (uint256 i = 0; i < userLength; ++i) {
if (userRentInfo[_users[i]].vabAmount < _amounts[i]) {
return false;
}
sum += _amounts[i];
}
address vabToken = IOwnablee(OWNABLE).PAYOUT_TOKEN();
if (IERC20(vabToken).balanceOf(address(this)) < sum) {
return false;
}
return true;
}
function withdrawAllFund() external onlyAuditor nonReentrant {
address to = IProperty(DAO_PROPERTY).DAO_FUND_REWARD();
require(to != address(0), "wAF: zero address");
require(migrationStatus == 1, "Migration is not on going");
address vabToken = IOwnablee(OWNABLE).PAYOUT_TOKEN();
uint256 sumAmount;
if (IERC20(vabToken).balanceOf(address(this)) >= totalMigrationVAB && totalMigrationVAB > 0) {
Helper.safeTransfer(vabToken, to, totalMigrationVAB);
sumAmount += sumAmount + totalMigrationVAB;
totalRewardAmount = totalRewardAmount - totalMigrationVAB;
totalMigrationVAB = 0;
}
sumAmount += IOwnablee(OWNABLE).withdrawVABFromEdgePool(to);
sumAmount += IVabbleDAO(VABBLE_DAO).withdrawVABFromStudioPool(to);
migrationStatus = 2;
emit AllFundWithdraw(to, sumAmount);
}
function calcMigrationVAB() external onlyNormal nonReentrant {
require(msg.sender == DAO_PROPERTY, "not Property");
uint256 amount = 0;
uint256 totalAmount = 0;
for (uint256 i = 0; i < stakerCount(); ++i) {
amount = calcRewardAmount(stakerMap.keys[i]);
stakeInfo[stakerMap.keys[i]].outstandingReward = amount;
totalAmount = totalAmount + amount;
}
if (totalRewardAmount >= totalAmount) {
totalMigrationVAB = totalRewardAmount - totalAmount;
}
migrationStatus = 1;
}
function addVotedData(address _user, uint256 _time, uint256 _proposalID) external onlyVote {
votedTime[_user][_proposalID] = _time;
}
function updateLastfundProposalCreateTime(uint256 _time) external onlyDAO {
lastfundProposalCreateTime = _time;
}
function addProposalData(address _creator, uint256 _cTime, uint256 _period) external returns (uint256) {
require(msg.sender == VABBLE_DAO || msg.sender == DAO_PROPERTY, "not dao/property");
proposalCount.increment();
uint256 proposalID = proposalCount.current();
propsList.push(Props(_creator, _cTime, _period, proposalID));
return proposalID;
}
function getStakeAmount(address _user) external view returns (uint256 amount_) {
amount_ = stakeInfo[_user].stakeAmount;
}
function getRentVABAmount(address _user) external view returns (uint256 amount_) {
amount_ = userRentInfo[_user].vabAmount;
}
function getLimitCount() external view returns (uint256 count_) {
uint256 limitPercent = IProperty(DAO_PROPERTY).minStakerCountPercent();
uint256 minVoteCount = IProperty(DAO_PROPERTY).minVoteCount();
uint256 limitStakerCount = (stakerCount() * limitPercent * 1e4) / 1e10;
if (limitStakerCount <= minVoteCount * 1e4) {
count_ = minVoteCount;
} else {
count_ = limitStakerCount / 1e4;
}
}
function getWithdrawableTime(address _user) external view returns (uint256 time_) {
time_ = stakeInfo[_user].stakeTime + IProperty(DAO_PROPERTY).lockPeriod();
}
function getOwnableAddress() public view returns (address) {
return OWNABLE;
}
function getVoteAddress() public view returns (address) {
return VOTE;
}
function getVabbleDaoAddress() public view returns (address) {
return VABBLE_DAO;
}
function getPropertyAddress() public view returns (address) {
return DAO_PROPERTY;
}
function getStakerList() external view returns (address[] memory) {
return stakerMap.keys;
}
function stakerCount() public view returns (uint256) {
return stakerMap.keys.length;
}
function __stakerSet(address key) private {
if (stakerMap.indexOf[key] > 0) return;
stakerMap.indexOf[key] = stakerMap.keys.length + 1;
stakerMap.keys.push(key);
}
function __stakerRemove(address key) private {
if (stakerMap.indexOf[key] == 0) return;
uint256 index = stakerMap.indexOf[key];
address lastKey = stakerMap.keys[stakerMap.keys.length - 1];
stakerMap.indexOf[lastKey] = index;
delete stakerMap.indexOf[key];
stakerMap.keys[index - 1] = lastKey;
stakerMap.keys.pop();
}
}
{
"compilationTarget": {
"contracts/dao/StakingPool.sol": "StakingPool"
},
"evmVersion": "cancun",
"libraries": {
"contracts/libraries/DAOOperations.sol:DAOOperations": "0xdaf27e7ad131c8d2b3e7d3f25342a201e11c88a4"
},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@ensdomains/=node_modules/@ensdomains/",
":@ethereum-waffle/=node_modules/@ethereum-waffle/",
":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
":ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":eth-gas-reporter/=node_modules/eth-gas-reporter/",
":forge-std/=lib/forge-std/src/",
":foundry-devops/=lib/foundry-devops/",
":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
":hardhat-deploy/=node_modules/hardhat-deploy/",
":hardhat/=node_modules/hardhat/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/"
]
}
[{"inputs":[{"internalType":"address","name":"_ownable","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AllFundWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"customers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"withdrawAmounts","type":"uint256[]"}],"name":"PendingWithdrawApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"customers","type":"address[]"}],"name":"PendingWithdrawDenied","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalRewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"contributor","type":"address"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"isCompound","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"RewardContinued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"RewardWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakeAmount","type":"uint256"}],"name":"TokenStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"unstaker","type":"address"},{"indexed":false,"internalType":"uint256","name":"unStakeAmount","type":"uint256"}],"name":"TokenUnstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"customer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VABDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"customer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawPending","type":"event"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"__calcProposalTimeIntervals","outputs":[{"internalType":"uint256[]","name":"times_","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"minIndex","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"__getProposalVoteCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"uint256","name":"_cTime","type":"uint256"},{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"addProposalData","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addRewardToPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_time","type":"uint256"},{"internalType":"uint256","name":"_proposalID","type":"uint256"}],"name":"addVotedData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_customers","type":"address[]"}],"name":"approvePendingWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"calcMigrationVAB","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"calcPendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"calcRealizedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"calcRewardAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_period","type":"uint256"},{"internalType":"uint256","name":"_stakeAmount","type":"uint256"},{"internalType":"uint256","name":"_proposalCount","type":"uint256"},{"internalType":"uint256","name":"_voteCount","type":"uint256"},{"internalType":"bool","name":"isBoardMember","type":"bool"}],"name":"calculateAPR","outputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"checkAllocateToPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_customers","type":"address[]"}],"name":"checkApprovePendingWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_customers","type":"address[]"}],"name":"checkDenyPendingWithDraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_customers","type":"address[]"}],"name":"denyPendingWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositVAB","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"subscriber","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositVABTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getLimitCount","outputs":[{"internalType":"uint256","name":"count_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwnableAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPropertyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getRentVABAmount","outputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getStakeAmount","outputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakerList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVabbleDaoAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVoteAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getWithdrawableTime","outputs":[{"internalType":"uint256","name":"time_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vabbleDAO","type":"address"},{"internalType":"address","name":"_property","type":"address"},{"internalType":"address","name":"_vote","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastfundProposalCreateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrationStatus","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minProposalIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"pendingWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proposalCount","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"receivedRewardAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"sendVAB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakeInfo","outputs":[{"internalType":"uint256","name":"stakeAmount","type":"uint256"},{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"outstandingReward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeVAB","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMigrationVAB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRewardAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRewardIssuedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakingAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstakeVAB","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_time","type":"uint256"}],"name":"updateLastfundProposalCreateTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRentInfo","outputs":[{"internalType":"uint256","name":"vabAmount","type":"uint256"},{"internalType":"uint256","name":"withdrawAmount","type":"uint256"},{"internalType":"bool","name":"pending","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAllFund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_isCompound","type":"uint256"}],"name":"withdrawReward","outputs":[],"stateMutability":"nonpayable","type":"function"}]