文件 1 的 7:IERC20.sol
pragma solidity 0.7.5;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
文件 2 的 7:IIntegralTimeRelease.sol
pragma solidity 0.7.5;
interface IIntegralTimeRelease {
event OwnerSet(address owner);
event Claim(address claimer, address receiver, uint256 option1Amount, uint256 option2Amount);
event Skim(address to, uint256 amount);
event Option1StopBlockSet(uint256 option1StopBlock);
event Option2StopBlockSet(uint256 option2StopBlock);
}
文件 3 的 7:IntegralTimeRelease.sol
pragma solidity 0.7.5;
import 'Math.sol';
import 'SafeMath.sol';
import 'TransferHelper.sol';
import 'IERC20.sol';
import 'IIntegralTimeRelease.sol';
import 'Votes.sol';
contract IntegralTimeRelease is IIntegralTimeRelease, Votes {
using SafeMath for uint256;
using SafeMath for uint96;
address public immutable token;
address public owner;
uint96 public option1TotalAllocations;
uint96 public option2TotalAllocations;
uint96 public option1TotalClaimed;
uint96 public option2TotalClaimed;
struct Option {
uint96 allocation;
uint96 claimed;
uint32 initBlock;
}
mapping(address => Option) public option1;
mapping(address => Option) public option2;
uint256 public option1StartBlock;
uint256 public option1EndBlock;
uint256 public option1StopBlock;
uint256 public option2StartBlock;
uint256 public option2EndBlock;
uint256 public option2StopBlock;
uint256 public option1StopSetBlock;
uint256 public option2StopSetBlock;
constructor(
address _token,
uint256 _option1StartBlock,
uint256 _option1EndBlock,
uint256 _option2StartBlock,
uint256 _option2EndBlock
) {
owner = msg.sender;
emit OwnerSet(owner);
token = _token;
_setOption1Timeframe(_option1StartBlock, _option1EndBlock);
_setOption2Timeframe(_option2StartBlock, _option2EndBlock);
}
function setOwner(address _owner) external {
require(msg.sender == owner, 'TR_FORBIDDEN');
owner = _owner;
emit OwnerSet(owner);
}
function _setOption1Timeframe(uint256 _option1StartBlock, uint256 _option1EndBlock) internal {
require(_option1EndBlock > _option1StartBlock, 'INVALID_OPTION1_TIME_FRAME');
option1StartBlock = _option1StartBlock;
option1EndBlock = _option1EndBlock;
option1StopBlock = _option1EndBlock;
option1StopSetBlock = _option1EndBlock;
}
function _setOption2Timeframe(uint256 _option2StartBlock, uint256 _option2EndBlock) internal {
require(_option2EndBlock > _option2StartBlock, 'INVALID_OPTION2_TIME_FRAME');
option2StartBlock = _option2StartBlock;
option2EndBlock = _option2EndBlock;
option2StopBlock = _option2EndBlock;
option2StopSetBlock = _option2EndBlock;
}
function initOption1Allocations(address[] calldata wallets, uint96[] calldata amounts) external {
require(msg.sender == owner, 'TR_FORBIDDEN');
require(option1StopSetBlock == option1EndBlock, 'TR_STOP_ALREADY_SET');
require(wallets.length == amounts.length, 'TR_INVALID_LENGTHS');
uint32 initBlock = safe32(block.number);
uint96 total = 0;
for (uint256 i = 0; i < wallets.length; i++) {
address wallet = wallets[i];
require(option1[wallet].allocation == 0, 'TR_ALLOCATION_ALREADY_SET');
uint96 amount = amounts[i];
require(amount > 0, 'TR_ALLOCATION_ZERO');
option1[wallet].allocation = amount;
option1[wallet].initBlock = initBlock;
total = total.add96(amount);
}
option1TotalAllocations = option1TotalAllocations.add96(total);
require(IERC20(token).balanceOf(address(this)) >= getTokensLeft(), 'TR_INSUFFICIENT_BALANCE');
}
function initOption2Allocations(address[] calldata wallets, uint96[] calldata amounts) external {
require(msg.sender == owner, 'TR_FORBIDDEN');
require(option2StopSetBlock == option2EndBlock, 'TR_STOP_ALREADY_SET');
require(wallets.length == amounts.length, 'TR_INVALID_LENGTHS');
uint32 initBlock = safe32(block.number);
uint96 total = 0;
for (uint256 i = 0; i < wallets.length; i++) {
address wallet = wallets[i];
require(option2[wallet].allocation == 0, 'TR_ALLOCATION_ALREADY_SET');
uint96 amount = amounts[i];
require(amount > 0, 'TR_ALLOCATION_ZERO');
option2[wallet].allocation = amount;
option2[wallet].initBlock = initBlock;
total = total.add96(amount);
}
option2TotalAllocations = option2TotalAllocations.add96(total);
require(IERC20(token).balanceOf(address(this)) >= getTokensLeft(), 'TR_INSUFFICIENT_BALANCE');
}
function updateOption1Allocations(address[] calldata wallets, uint96[] calldata amounts) external {
require(msg.sender == owner, 'TR_FORBIDDEN');
require(option1StopSetBlock == option1EndBlock, 'TR_STOP_ALREADY_SET');
require(wallets.length == amounts.length, 'TR_INVALID_LENGTHS');
for (uint256 i = 0; i < wallets.length; i++) {
address wallet = wallets[i];
uint96 amount = amounts[i];
uint96 oldAmount = option1[wallet].allocation;
require(oldAmount > 0, 'TR_ALLOCATION_NOT_SET');
require(getReleasedOption1(wallet) <= amount, 'TR_ALLOCATION_TOO_SMALL');
option1TotalAllocations = option1TotalAllocations.sub96(oldAmount).add96(amount);
option1[wallet].allocation = amount;
uint96 claimed = option1[wallet].claimed;
if (checkpointsLength[wallet] != 0) {
_updateVotes(wallet, address(0), oldAmount.sub96(claimed));
}
_updateVotes(address(0), wallet, amount.sub96(claimed));
}
require(IERC20(token).balanceOf(address(this)) >= getTokensLeft(), 'TR_INSUFFICIENT_BALANCE');
}
function updateOption2Allocations(address[] calldata wallets, uint96[] calldata amounts) external {
require(msg.sender == owner, 'TR_FORBIDDEN');
require(option2StopSetBlock == option2EndBlock, 'TR_STOP_ALREADY_SET');
require(wallets.length == amounts.length, 'TR_INVALID_LENGTHS');
for (uint256 i = 0; i < wallets.length; i++) {
address wallet = wallets[i];
uint96 amount = amounts[i];
uint96 oldAmount = option2[wallet].allocation;
require(oldAmount > 0, 'TR_ALLOCATION_NOT_SET');
require(getReleasedOption2(wallet) <= amount, 'TR_ALLOCATION_TOO_SMALL');
option2TotalAllocations = option2TotalAllocations.sub96(oldAmount).add96(amount);
option2[wallet].allocation = amount;
uint96 claimed = option2[wallet].claimed;
if (checkpointsLength[wallet] != 0) {
_updateVotes(wallet, address(0), oldAmount.sub96(claimed));
}
_updateVotes(address(0), wallet, amount.sub96(claimed));
}
require(IERC20(token).balanceOf(address(this)) >= getTokensLeft(), 'TR_INSUFFICIENT_BALANCE');
}
function getTokensLeft() public view returns (uint96) {
uint256 allocationTime1 = option1EndBlock.sub(option1StartBlock);
uint256 claimableTime1 = option1StopBlock.sub(option1StartBlock);
uint96 allocation1 = safe96(uint256(option1TotalAllocations).mul(claimableTime1).div(allocationTime1));
uint256 allocationTime2 = option2EndBlock.sub(option2StartBlock);
uint256 claimableTime2 = option2StopBlock.sub(option2StartBlock);
uint96 allocation2 = safe96(uint256(option2TotalAllocations).mul(claimableTime2).div(allocationTime2));
return allocation1.add96(allocation2).sub96(option1TotalClaimed).sub96(option2TotalClaimed);
}
function setOption1StopBlock(uint256 _option1StopBlock) external {
require(msg.sender == owner, 'TR_FORBIDDEN');
require(option1StopSetBlock == option1EndBlock, 'TR_STOP_ALREADY_SET');
require(_option1StopBlock >= block.number && _option1StopBlock < option1EndBlock, 'TR_INVALID_BLOCK_NUMBER');
option1StopBlock = _option1StopBlock;
option1StopSetBlock = block.number;
emit Option1StopBlockSet(_option1StopBlock);
}
function setOption2StopBlock(uint256 _option2StopBlock) external {
require(msg.sender == owner, 'TR_FORBIDDEN');
require(option2StopSetBlock == option2EndBlock, 'TR_STOP_ALREADY_SET');
require(_option2StopBlock >= block.number && _option2StopBlock < option2EndBlock, 'TR_INVALID_BLOCK_NUMBER');
option2StopBlock = _option2StopBlock;
option2StopSetBlock = block.number;
emit Option2StopBlockSet(_option2StopBlock);
}
function skim(address to) external {
require(msg.sender == owner, 'TR_FORBIDDEN');
require(to != address(0), 'TR_ADDRESS_ZERO');
uint256 amount = getExcessTokens();
TransferHelper.safeTransfer(token, to, amount);
emit Skim(to, amount);
}
function getExcessTokens() public view returns (uint256) {
return IERC20(token).balanceOf(address(this)).sub(getTokensLeft());
}
function getReleasedOption1(address wallet) public view returns (uint96) {
return _getReleasedOption1ForBlock(wallet, block.number);
}
function _getReleasedOption1ForBlock(address wallet, uint256 blockNumber) internal view returns (uint96) {
if (blockNumber <= option1StartBlock) {
return 0;
}
uint256 elapsed = Math.min(blockNumber, option1StopBlock).sub(option1StartBlock);
uint256 allocationTime = option1EndBlock.sub(option1StartBlock);
return safe96(uint256(option1[wallet].allocation).mul(elapsed).div(allocationTime));
}
function getReleasedOption2(address wallet) public view returns (uint96) {
return _getReleasedOption2ForBlock(wallet, block.number);
}
function _getReleasedOption2ForBlock(address wallet, uint256 blockNumber) internal view returns (uint96) {
if (blockNumber <= option2StartBlock) {
return 0;
}
uint256 elapsed = Math.min(blockNumber, option2StopBlock).sub(option2StartBlock);
uint256 allocationTime = option2EndBlock.sub(option2StartBlock);
return safe96(uint256(option2[wallet].allocation).mul(elapsed).div(allocationTime));
}
function getClaimableOption1(address wallet) external view returns (uint256) {
return getReleasedOption1(wallet).sub(option1[wallet].claimed);
}
function getClaimableOption2(address wallet) external view returns (uint256) {
return getReleasedOption2(wallet).sub(option2[wallet].claimed);
}
function getOption1Allocation(address wallet) external view returns (uint256) {
return option1[wallet].allocation;
}
function getOption1Claimed(address wallet) external view returns (uint256) {
return option1[wallet].claimed;
}
function getOption2Allocation(address wallet) external view returns (uint256) {
return option2[wallet].allocation;
}
function getOption2Claimed(address wallet) external view returns (uint256) {
return option2[wallet].claimed;
}
function claim(address to) external {
address sender = msg.sender;
Option memory _option1 = option1[sender];
Option memory _option2 = option2[sender];
uint96 _option1Claimed = _option1.claimed;
uint96 _option2Claimed = _option2.claimed;
uint96 option1Amount = getReleasedOption1(sender).sub96(_option1Claimed);
uint96 option2Amount = getReleasedOption2(sender).sub96(_option2Claimed);
option1[sender].claimed = _option1Claimed.add96(option1Amount);
option2[sender].claimed = _option2Claimed.add96(option2Amount);
option1TotalClaimed = option1TotalClaimed.add96(option1Amount);
option2TotalClaimed = option2TotalClaimed.add96(option2Amount);
uint96 totalClaimed = option1Amount.add96(option2Amount);
if (checkpointsLength[sender] == 0) {
_updateVotes(address(0), sender, _option1.allocation.add96(_option2.allocation));
}
_updateVotes(sender, address(0), totalClaimed);
TransferHelper.safeTransfer(token, to, totalClaimed);
emit Claim(sender, to, option1Amount, option2Amount);
}
function safe96(uint256 n) internal pure returns (uint96) {
require(n < 2**96, 'IT_EXCEEDS_96_BITS');
return uint96(n);
}
function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96) {
uint96 option1TotalAllocation = option1[account].allocation;
uint96 option2TotalAllocation = option2[account].allocation;
uint96 votes = 0;
if (checkpointsLength[account] == 0 || checkpoints[account][0].fromBlock > blockNumber) {
if (option1[account].initBlock <= blockNumber) {
votes = votes.add96(option1TotalAllocation);
}
if (option2[account].initBlock <= blockNumber) {
votes = votes.add96(option2TotalAllocation);
}
} else {
votes = _getPriorVotes(account, blockNumber);
}
if (option1StopBlock == option1EndBlock && option2StopBlock == option2EndBlock) {
return votes;
}
if (option1StopSetBlock > blockNumber && option2StopSetBlock > blockNumber) {
return votes;
}
uint96 lockedAllocation1;
uint96 lockedAllocation2;
if (blockNumber >= option1StopSetBlock) {
uint256 allocationTime = option1EndBlock.sub(option1StartBlock);
uint256 haltedTime = option1EndBlock.sub(option1StopBlock);
lockedAllocation1 = safe96(uint256(option1TotalAllocation).mul(haltedTime).div(allocationTime));
}
if (blockNumber >= option2StopSetBlock) {
uint256 allocationTime = option2EndBlock.sub(option2StartBlock);
uint256 haltedTime = option2EndBlock.sub(option2StopBlock);
lockedAllocation2 = safe96(uint256(option2TotalAllocation).mul(haltedTime).div(allocationTime));
}
return votes.sub96(lockedAllocation1).sub96(lockedAllocation2);
}
}
文件 4 的 7:Math.sol
pragma solidity 0.7.5;
library Math {
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x < y ? x : y;
}
function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x > y ? x : y;
}
function min32(uint32 x, uint32 y) internal pure returns (uint32 z) {
z = x < y ? x : y;
}
function max32(uint32 x, uint32 y) internal pure returns (uint32 z) {
z = x > y ? x : y;
}
function sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
文件 5 的 7:SafeMath.sol
pragma solidity 0.7.5;
library SafeMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, 'SM_ADD_OVERFLOW');
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = sub(x, y, 'SM_SUB_UNDERFLOW');
}
function sub(
uint256 x,
uint256 y,
string memory message
) internal pure returns (uint256 z) {
require((z = x - y) <= x, message);
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x, 'SM_MUL_OVERFLOW');
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, 'SM_DIV_BY_ZERO');
uint256 c = a / b;
return c;
}
function ceil_div(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = div(a, b);
if (c == mul(a, b)) {
return c;
} else {
return add(c, 1);
}
}
function safe32(uint256 n) internal pure returns (uint32) {
require(n < 2**32, 'IS_EXCEEDS_32_BITS');
return uint32(n);
}
function add96(uint96 a, uint96 b) internal pure returns (uint96 c) {
c = a + b;
require(c >= a, 'SM_ADD_OVERFLOW');
}
function sub96(uint96 a, uint96 b) internal pure returns (uint96) {
require(b <= a, 'SM_SUB_UNDERFLOW');
return a - b;
}
function mul96(uint96 x, uint96 y) internal pure returns (uint96 z) {
require(y == 0 || (z = x * y) / y == x, 'SM_MUL_OVERFLOW');
}
function div96(uint96 a, uint96 b) internal pure returns (uint96) {
require(b > 0, 'SM_DIV_BY_ZERO');
uint96 c = a / b;
return c;
}
function add32(uint32 a, uint32 b) internal pure returns (uint32 c) {
c = a + b;
require(c >= a, 'SM_ADD_OVERFLOW');
}
function sub32(uint32 a, uint32 b) internal pure returns (uint32) {
require(b <= a, 'SM_SUB_UNDERFLOW');
return a - b;
}
function mul32(uint32 x, uint32 y) internal pure returns (uint32 z) {
require(y == 0 || (z = x * y) / y == x, 'SM_MUL_OVERFLOW');
}
function div32(uint32 a, uint32 b) internal pure returns (uint32) {
require(b > 0, 'SM_DIV_BY_ZERO');
uint32 c = a / b;
return c;
}
}
文件 6 的 7:TransferHelper.sol
pragma solidity 0.7.5;
library TransferHelper {
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TH_APPROVE_FAILED');
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TH_TRANSFER_FAILED');
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TH_TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{ value: value }(new bytes(0));
require(success, 'TH_ETH_TRANSFER_FAILED');
}
}
文件 7 的 7:Votes.sol
pragma solidity 0.7.5;
import 'SafeMath.sol';
contract Votes {
using SafeMath for uint96;
struct Checkpoint {
uint32 fromBlock;
uint96 votes;
}
mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;
mapping(address => uint32) public checkpointsLength;
event DelegateVotesChanged(address indexed account, uint96 oldVotes, uint96 newVotes);
function getCurrentVotes(address account) external view returns (uint96) {
return checkpoints[account][checkpointsLength[account] - 1].votes;
}
function _getPriorVotes(address account, uint256 blockNumber) internal view returns (uint96) {
require(blockNumber < block.number, 'VO_NOT_YET_DETERMINED');
uint32 n = checkpointsLength[account];
if (n == 0) {
return 0;
}
if (checkpoints[account][n - 1].fromBlock <= blockNumber) {
return checkpoints[account][n - 1].votes;
}
if (checkpoints[account][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = n - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2;
Checkpoint memory checkpoint = checkpoints[account][center];
if (checkpoint.fromBlock == blockNumber) {
return checkpoint.votes;
} else if (checkpoint.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoints[account][lower].votes;
}
function _updateVotes(
address giver,
address receiver,
uint96 votes
) internal {
if (giver == receiver || votes == 0) {
return;
}
if (giver != address(0)) {
uint32 n = checkpointsLength[giver];
require(n > 0, 'VO_INSUFFICIENT_VOTES');
uint96 oldVotes = checkpoints[giver][n - 1].votes;
uint96 newVotes = oldVotes.sub96(votes);
_writeCheckpoint(giver, n, newVotes);
}
if (receiver != address(0)) {
uint32 n = checkpointsLength[receiver];
uint96 oldVotes = checkpoints[receiver][n - 1].votes;
uint96 newVotes = oldVotes.add96(votes);
_writeCheckpoint(receiver, n, newVotes);
}
}
function _writeCheckpoint(
address account,
uint32 n,
uint96 votes
) internal {
uint32 blockNumber = safe32(block.number);
uint96 oldVotes = checkpoints[account][n - 1].votes;
if (n > 0 && checkpoints[account][n - 1].fromBlock == blockNumber) {
checkpoints[account][n - 1].votes = votes;
} else {
checkpoints[account][n] = Checkpoint(blockNumber, votes);
checkpointsLength[account] = n + 1;
}
emit DelegateVotesChanged(account, oldVotes, votes);
}
function safe32(uint256 n) internal pure returns (uint32) {
require(n < 2**32, 'VO_EXCEEDS_32_BITS');
return uint32(n);
}
}
{
"compilationTarget": {
"IntegralTimeRelease.sol": "IntegralTimeRelease"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_option1StartBlock","type":"uint256"},{"internalType":"uint256","name":"_option1EndBlock","type":"uint256"},{"internalType":"uint256","name":"_option2StartBlock","type":"uint256"},{"internalType":"uint256","name":"_option2EndBlock","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"claimer","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"option1Amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"option2Amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint96","name":"oldVotes","type":"uint96"},{"indexed":false,"internalType":"uint96","name":"newVotes","type":"uint96"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"option1StopBlock","type":"uint256"}],"name":"Option1StopBlockSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"option2StopBlock","type":"uint256"}],"name":"Option2StopBlockSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"OwnerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Skim","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"checkpoints","outputs":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint96","name":"votes","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"checkpointsLength","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getClaimableOption1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getClaimableOption2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getCurrentVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExcessTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getOption1Allocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getOption1Claimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getOption2Allocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getOption2Claimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPriorVotes","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getReleasedOption1","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"getReleasedOption2","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokensLeft","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"},{"internalType":"uint96[]","name":"amounts","type":"uint96[]"}],"name":"initOption1Allocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"},{"internalType":"uint96[]","name":"amounts","type":"uint96[]"}],"name":"initOption2Allocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"option1","outputs":[{"internalType":"uint96","name":"allocation","type":"uint96"},{"internalType":"uint96","name":"claimed","type":"uint96"},{"internalType":"uint32","name":"initBlock","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option1EndBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option1StartBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option1StopBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option1StopSetBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option1TotalAllocations","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option1TotalClaimed","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"option2","outputs":[{"internalType":"uint96","name":"allocation","type":"uint96"},{"internalType":"uint96","name":"claimed","type":"uint96"},{"internalType":"uint32","name":"initBlock","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option2EndBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option2StartBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option2StopBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option2StopSetBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option2TotalAllocations","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"option2TotalClaimed","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_option1StopBlock","type":"uint256"}],"name":"setOption1StopBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_option2StopBlock","type":"uint256"}],"name":"setOption2StopBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"},{"internalType":"uint96[]","name":"amounts","type":"uint96[]"}],"name":"updateOption1Allocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"wallets","type":"address[]"},{"internalType":"uint96[]","name":"amounts","type":"uint96[]"}],"name":"updateOption2Allocations","outputs":[],"stateMutability":"nonpayable","type":"function"}]