文件 1 的 6:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(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) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(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) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 6:IERC20.sol
pragma solidity >=0.6.0 <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);
}
文件 3 的 6:IVesting.sol
pragma solidity ^0.7.6;
interface IVesting {
enum ReleaseMethod {
IntervalEnd,
LinearlyPerSecond
}
function addVestingGrant(
address account,
uint256 grantAmount,
bool isRevocable
) external;
function revokeVestingGrant(address account) external;
function release() external;
function transferUnusedTokens() external;
function addVestingGrantsBatch(
address[] memory accounts,
uint256[] memory grantAmounts,
bool[] memory isRevocables
) external;
function setScheduleStartTimestamp(uint256 scheduleStartTimestamp_)
external;
function setGovernanceAccount(address account) external;
function setVestingAdmin(address account) external;
function getVestingSchedule()
external
view
returns (
uint256 cliffDurationDays,
uint256 percentReleaseAtGrantStart,
uint256 percentReleaseAtIntervalStart,
uint256 intervalDays,
uint256 gapDays,
uint256 numberOfIntervals,
ReleaseMethod releaseMethod
);
function vestingGrantFor(address account)
external
view
returns (
uint256 grantAmount,
bool isRevocable,
bool isRevoked,
bool isActive
);
function revoked(address account) external view returns (bool isRevoked);
function releasedAmountFor(address account)
external
view
returns (uint256 releasedAmount);
function releasableAmountFor(address account)
external
view
returns (uint256 unreleasedAmount);
function vestedAmountFor(address account)
external
view
returns (uint256 vestedAmount);
function unvestedAmountFor(address account)
external
view
returns (uint256 unvestedAmount);
event VestingGrantAdded(
address indexed account,
uint256 indexed grantAmount,
bool isRevocable
);
event VestingGrantRevoked(
address indexed account,
uint256 remainderAmount,
uint256 grantAmount,
uint256 releasedAmount
);
event TokensReleased(address indexed account, uint256 amount);
event ScheduleStartTimestampSet(
address indexed account,
uint256 newScheduleStartTimestamp,
uint256 oldScheduleStartTimestamp
);
}
文件 4 的 6:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 5 的 6:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
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) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 6 的 6:Vesting.sol
pragma solidity ^0.7.6;
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "./interfaces/IVesting.sol";
contract Vesting is IVesting {
using SafeMath for uint256;
using SafeERC20 for IERC20;
struct VestingSchedule {
uint256 cliffDurationDays;
uint256 percentReleaseAtScheduleStart;
uint256 percentReleaseForEachInterval;
uint256 intervalDays;
uint256 gapDays;
uint256 numberOfIntervals;
ReleaseMethod releaseMethod;
}
struct VestingGrant {
uint256 grantAmount;
bool isRevocable;
bool isRevoked;
bool isActive;
}
uint256 public constant BATCH_MAX_NUM = 200;
uint256 public constant PERCENT_100_WEI = 100 ether;
uint256 public constant SECONDS_IN_DAY = 86400;
address public governanceAccount;
address public vestingAdmin;
address public tokenAddress;
uint256 public totalGrantAmount;
uint256 public totalReleasedAmount;
uint256 public scheduleStartTimestamp;
bool public allowAccumulate;
VestingSchedule private _vestingSchedule;
mapping(address => VestingGrant) private _vestingGrants;
mapping(address => uint256) private _released;
constructor(
address tokenAddress_,
uint256 cliffDurationDays,
uint256 percentReleaseAtScheduleStart,
uint256 percentReleaseForEachInterval,
uint256 intervalDays,
uint256 gapDays,
uint256 numberOfIntervals,
ReleaseMethod releaseMethod,
bool allowAccumulate_
) {
require(tokenAddress_ != address(0), "Vesting: zero token address");
require(
percentReleaseAtScheduleStart <= PERCENT_100_WEI,
"Vesting: percent release at grant start > 100%"
);
require(
percentReleaseForEachInterval <= PERCENT_100_WEI,
"Vesting: percent release for each interval > 100%"
);
require(
intervalDays.add(gapDays) > 0,
"Vesting: zero interval and gap"
);
require(
percentReleaseAtScheduleStart.add(
percentReleaseForEachInterval.mul(numberOfIntervals)
) <= PERCENT_100_WEI,
"Vesting: total percent release > 100%"
);
governanceAccount = msg.sender;
vestingAdmin = msg.sender;
tokenAddress = tokenAddress_;
_vestingSchedule.cliffDurationDays = cliffDurationDays;
_vestingSchedule
.percentReleaseAtScheduleStart = percentReleaseAtScheduleStart;
_vestingSchedule
.percentReleaseForEachInterval = percentReleaseForEachInterval;
_vestingSchedule.intervalDays = intervalDays;
_vestingSchedule.gapDays = gapDays;
_vestingSchedule.numberOfIntervals = numberOfIntervals;
_vestingSchedule.releaseMethod = releaseMethod;
allowAccumulate = allowAccumulate_;
}
modifier onlyBy(address account) {
require(msg.sender == account, "Vesting: sender unauthorized");
_;
}
function addVestingGrant(
address account,
uint256 grantAmount,
bool isRevocable
) external override onlyBy(vestingAdmin) {
_addVestingGrant(account, grantAmount, isRevocable);
}
function revokeVestingGrant(address account)
external
override
onlyBy(vestingAdmin)
{
_revokeVestingGrant(account);
}
function release() external override {
uint256 releasableAmount = releasableAmountFor(msg.sender);
_release(msg.sender, releasableAmount);
}
function transferUnusedTokens()
external
override
onlyBy(governanceAccount)
{
uint256 unusedAmount = IERC20(tokenAddress)
.balanceOf(address(this))
.add(totalReleasedAmount)
.sub(totalGrantAmount);
require(unusedAmount > 0, "Vesting: nothing to transfer");
IERC20(tokenAddress).safeTransfer(governanceAccount, unusedAmount);
}
function addVestingGrantsBatch(
address[] memory accounts,
uint256[] memory grantAmounts,
bool[] memory isRevocables
) external override onlyBy(vestingAdmin) {
require(accounts.length > 0, "Vesting: empty");
require(accounts.length <= BATCH_MAX_NUM, "Vesting: exceed max");
require(
grantAmounts.length == accounts.length,
"Vesting: grant amounts length different"
);
require(
isRevocables.length == accounts.length,
"Vesting: is revocables length different"
);
for (uint256 i = 0; i < accounts.length; i++) {
_addVestingGrant(accounts[i], grantAmounts[i], isRevocables[i]);
}
}
function setScheduleStartTimestamp(uint256 scheduleStartTimestamp_)
external
override
onlyBy(vestingAdmin)
{
require(
scheduleStartTimestamp_ > block.timestamp,
"Vesting: start before current timestamp"
);
uint256 oldScheduleStartTimestamp = scheduleStartTimestamp;
require(
oldScheduleStartTimestamp == 0 ||
block.timestamp < oldScheduleStartTimestamp,
"Vesting: already started"
);
scheduleStartTimestamp = scheduleStartTimestamp_;
emit ScheduleStartTimestampSet(
msg.sender,
scheduleStartTimestamp_,
oldScheduleStartTimestamp
);
}
function setGovernanceAccount(address account)
external
override
onlyBy(governanceAccount)
{
require(account != address(0), "Vesting: zero account");
governanceAccount = account;
}
function setVestingAdmin(address account)
external
override
onlyBy(governanceAccount)
{
require(account != address(0), "Vesting: zero account");
vestingAdmin = account;
}
function getVestingSchedule()
external
view
override
returns (
uint256 cliffDurationDays,
uint256 percentReleaseAtScheduleStart,
uint256 percentReleaseForEachInterval,
uint256 intervalDays,
uint256 gapDays,
uint256 numberOfIntervals,
ReleaseMethod releaseMethod
)
{
VestingSchedule memory vestingSchedule = _vestingSchedule;
cliffDurationDays = vestingSchedule.cliffDurationDays;
percentReleaseAtScheduleStart = vestingSchedule
.percentReleaseAtScheduleStart;
percentReleaseForEachInterval = vestingSchedule
.percentReleaseForEachInterval;
intervalDays = vestingSchedule.intervalDays;
gapDays = vestingSchedule.gapDays;
numberOfIntervals = vestingSchedule.numberOfIntervals;
releaseMethod = vestingSchedule.releaseMethod;
}
function vestingGrantFor(address account)
external
view
override
returns (
uint256 grantAmount,
bool isRevocable,
bool isRevoked,
bool isActive
)
{
require(account != address(0), "Vesting: zero account");
VestingGrant memory vestingGrant = _vestingGrants[account];
grantAmount = vestingGrant.grantAmount;
isRevocable = vestingGrant.isRevocable;
isRevoked = vestingGrant.isRevoked;
isActive = vestingGrant.isActive;
}
function revoked(address account)
public
view
override
returns (bool isRevoked)
{
require(account != address(0), "Vesting: zero account");
isRevoked = _vestingGrants[account].isRevoked;
}
function releasedAmountFor(address account)
public
view
override
returns (uint256 releasedAmount)
{
require(account != address(0), "Vesting: zero account");
releasedAmount = _released[account];
}
function releasableAmountFor(address account)
public
view
override
returns (uint256 releasableAmount)
{
require(account != address(0), "Vesting: zero account");
uint256 startTimestamp = scheduleStartTimestamp;
require(startTimestamp > 0, "Vesting: undefined start time");
require(block.timestamp >= startTimestamp, "Vesting: not started");
require(!revoked(account), "Vesting: revoked");
uint256 vestedAmount = vestedAmountFor(account);
releasableAmount = vestedAmount.sub(releasedAmountFor(account));
}
function vestedAmountFor(address account)
public
view
override
returns (uint256 vestedAmount)
{
require(account != address(0), "Vesting: zero account");
VestingGrant memory vestingGrant = _vestingGrants[account];
require(vestingGrant.isActive, "Vesting: inactive");
uint256 startTimestamp = scheduleStartTimestamp;
if (startTimestamp == 0) {
return 0;
}
if (block.timestamp < startTimestamp) {
return 0;
}
if (revoked(account)) {
return releasedAmountFor(account);
}
VestingSchedule memory vestingSchedule = _vestingSchedule;
vestedAmount = 0;
if (vestingSchedule.percentReleaseAtScheduleStart > 0) {
vestedAmount = vestingGrant
.grantAmount
.mul(vestingSchedule.percentReleaseAtScheduleStart)
.div(PERCENT_100_WEI);
}
uint256 cliffEndTimestamp = startTimestamp.add(
vestingSchedule.cliffDurationDays.mul(SECONDS_IN_DAY)
);
if (block.timestamp < cliffEndTimestamp) {
return vestedAmount;
}
uint256 intervalSeconds = vestingSchedule.intervalDays.mul(
SECONDS_IN_DAY
);
uint256 gapSeconds = vestingSchedule.gapDays.mul(SECONDS_IN_DAY);
uint256 scheduleEndTimestamp = vestingSchedule.numberOfIntervals > 0
? cliffEndTimestamp
.add(intervalSeconds.mul(vestingSchedule.numberOfIntervals))
.add(gapSeconds.mul(vestingSchedule.numberOfIntervals.sub(1)))
: cliffEndTimestamp;
if (block.timestamp >= scheduleEndTimestamp) {
vestedAmount = vestingGrant.grantAmount;
return vestedAmount;
}
uint256 intervalNumber = block.timestamp.sub(cliffEndTimestamp).div(
intervalSeconds.add(gapSeconds)
);
require(
intervalNumber < vestingSchedule.numberOfIntervals,
"Vesting: unexpected interval number"
);
uint256 totalPercentage = vestingSchedule
.percentReleaseForEachInterval
.mul(intervalNumber);
if (vestingSchedule.releaseMethod == ReleaseMethod.IntervalEnd) {
} else if (
vestingSchedule.releaseMethod == ReleaseMethod.LinearlyPerSecond
) {
uint256 secondsInInterval = block.timestamp.sub(
cliffEndTimestamp.add(
intervalSeconds.add(gapSeconds).mul(intervalNumber)
)
);
totalPercentage = secondsInInterval >= intervalSeconds
? totalPercentage.add(
vestingSchedule.percentReleaseForEachInterval
)
: totalPercentage.add(
vestingSchedule
.percentReleaseForEachInterval
.mul(secondsInInterval)
.div(intervalSeconds)
);
} else {
require(false, "Vesting: unexpected release method");
}
uint256 maxPercentage = PERCENT_100_WEI.sub(
vestingSchedule.percentReleaseAtScheduleStart
);
if (totalPercentage > maxPercentage) {
totalPercentage = maxPercentage;
}
vestedAmount = vestedAmount.add(
vestingGrant.grantAmount.mul(totalPercentage).div(PERCENT_100_WEI)
);
}
function unvestedAmountFor(address account)
external
view
override
returns (uint256 unvestedAmount)
{
require(account != address(0), "Vesting: zero account");
VestingGrant memory vestingGrant = _vestingGrants[account];
require(vestingGrant.isActive, "Vesting: inactive");
if (revoked(account)) {
unvestedAmount = 0;
} else {
unvestedAmount = vestingGrant.grantAmount.sub(
vestedAmountFor(account)
);
}
}
function _addVestingGrant(
address account,
uint256 grantAmount,
bool isRevocable
) private {
require(account != address(0), "Vesting: zero account");
require(grantAmount > 0, "Vesting: zero grant amount");
uint256 startTimestamp = scheduleStartTimestamp;
require(
startTimestamp == 0 || block.timestamp < startTimestamp,
"Vesting: already started"
);
VestingGrant memory vestingGrant = _vestingGrants[account];
require(
allowAccumulate || !vestingGrant.isActive,
"Vesting: already added"
);
require(!revoked(account), "Vesting: already revoked");
totalGrantAmount = totalGrantAmount.add(grantAmount);
require(
totalGrantAmount <= IERC20(tokenAddress).balanceOf(address(this)),
"Vesting: total grant amount exceed balance"
);
if (vestingGrant.isActive) {
_vestingGrants[account].grantAmount = vestingGrant.grantAmount.add(
grantAmount
);
} else {
_vestingGrants[account] = VestingGrant({
grantAmount: grantAmount,
isRevocable: isRevocable,
isRevoked: false,
isActive: true
});
}
emit VestingGrantAdded(account, grantAmount, isRevocable);
}
function _revokeVestingGrant(address account) private {
require(account != address(0), "Vesting: zero account");
VestingGrant memory vestingGrant = _vestingGrants[account];
require(vestingGrant.isActive, "Vesting: inactive");
require(vestingGrant.isRevocable, "Vesting: not revocable");
require(!revoked(account), "Vesting: already revoked");
uint256 releasedAmount = releasedAmountFor(account);
uint256 remainderAmount = vestingGrant.grantAmount.sub(releasedAmount);
totalGrantAmount = totalGrantAmount.sub(remainderAmount);
_vestingGrants[account].isRevoked = true;
emit VestingGrantRevoked(
account,
remainderAmount,
vestingGrant.grantAmount,
releasedAmount
);
}
function _release(address account, uint256 amount) private {
require(account != address(0), "Vesting: zero account");
require(amount > 0, "Vesting: zero amount");
_released[account] = _released[account].add(amount);
totalReleasedAmount = totalReleasedAmount.add(amount);
emit TokensReleased(account, amount);
IERC20(tokenAddress).safeTransfer(account, amount);
}
}
{
"compilationTarget": {
"contracts/Vesting.sol": "Vesting"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"tokenAddress_","type":"address"},{"internalType":"uint256","name":"cliffDurationDays","type":"uint256"},{"internalType":"uint256","name":"percentReleaseAtScheduleStart","type":"uint256"},{"internalType":"uint256","name":"percentReleaseForEachInterval","type":"uint256"},{"internalType":"uint256","name":"intervalDays","type":"uint256"},{"internalType":"uint256","name":"gapDays","type":"uint256"},{"internalType":"uint256","name":"numberOfIntervals","type":"uint256"},{"internalType":"enum IVesting.ReleaseMethod","name":"releaseMethod","type":"uint8"},{"internalType":"bool","name":"allowAccumulate_","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"newScheduleStartTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldScheduleStartTimestamp","type":"uint256"}],"name":"ScheduleStartTimestampSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"grantAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isRevocable","type":"bool"}],"name":"VestingGrantAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"remainderAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"grantAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"releasedAmount","type":"uint256"}],"name":"VestingGrantRevoked","type":"event"},{"inputs":[],"name":"BATCH_MAX_NUM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERCENT_100_WEI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_DAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"grantAmount","type":"uint256"},{"internalType":"bool","name":"isRevocable","type":"bool"}],"name":"addVestingGrant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"grantAmounts","type":"uint256[]"},{"internalType":"bool[]","name":"isRevocables","type":"bool[]"}],"name":"addVestingGrantsBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allowAccumulate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVestingSchedule","outputs":[{"internalType":"uint256","name":"cliffDurationDays","type":"uint256"},{"internalType":"uint256","name":"percentReleaseAtScheduleStart","type":"uint256"},{"internalType":"uint256","name":"percentReleaseForEachInterval","type":"uint256"},{"internalType":"uint256","name":"intervalDays","type":"uint256"},{"internalType":"uint256","name":"gapDays","type":"uint256"},{"internalType":"uint256","name":"numberOfIntervals","type":"uint256"},{"internalType":"enum IVesting.ReleaseMethod","name":"releaseMethod","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"releasableAmountFor","outputs":[{"internalType":"uint256","name":"releasableAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"releasedAmountFor","outputs":[{"internalType":"uint256","name":"releasedAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"revokeVestingGrant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"revoked","outputs":[{"internalType":"bool","name":"isRevoked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scheduleStartTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"setGovernanceAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"scheduleStartTimestamp_","type":"uint256"}],"name":"setScheduleStartTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"setVestingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalGrantAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReleasedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferUnusedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unvestedAmountFor","outputs":[{"internalType":"uint256","name":"unvestedAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"vestedAmountFor","outputs":[{"internalType":"uint256","name":"vestedAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"vestingGrantFor","outputs":[{"internalType":"uint256","name":"grantAmount","type":"uint256"},{"internalType":"bool","name":"isRevocable","type":"bool"},{"internalType":"bool","name":"isRevoked","type":"bool"},{"internalType":"bool","name":"isActive","type":"bool"}],"stateMutability":"view","type":"function"}]