Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 174 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Exec Transaction | 19168665 | 785 days ago | IN | 0 ETH | 0.00214239 | ||||
| Approve Hash | 19168661 | 785 days ago | IN | 0 ETH | 0.0016215 | ||||
| Approve Hash | 19165659 | 785 days ago | IN | 0 ETH | 0.00215172 | ||||
| Exec Transaction | 19125553 | 791 days ago | IN | 0 ETH | 0.00097866 | ||||
| Approve Hash | 19125547 | 791 days ago | IN | 0 ETH | 0.00097717 | ||||
| Approve Hash | 19118722 | 792 days ago | IN | 0 ETH | 0.00174764 | ||||
| Exec Transaction | 19116179 | 792 days ago | IN | 0 ETH | 0.00106745 | ||||
| Approve Hash | 19116176 | 792 days ago | IN | 0 ETH | 0.00099448 | ||||
| Approve Hash | 19082953 | 797 days ago | IN | 0 ETH | 0.00343572 | ||||
| Exec Transaction | 19075097 | 798 days ago | IN | 0 ETH | 0.00046914 | ||||
| Approve Hash | 19075094 | 798 days ago | IN | 0 ETH | 0.0005017 | ||||
| Approve Hash | 19073277 | 798 days ago | IN | 0 ETH | 0.00083224 | ||||
| Exec Transaction | 19068139 | 799 days ago | IN | 0 ETH | 0.00059161 | ||||
| Approve Hash | 19068136 | 799 days ago | IN | 0 ETH | 0.00068926 | ||||
| Approve Hash | 19068033 | 799 days ago | IN | 0 ETH | 0.00082031 | ||||
| Exec Transaction | 19058446 | 800 days ago | IN | 0 ETH | 0.00092744 | ||||
| Approve Hash | 19058443 | 800 days ago | IN | 0 ETH | 0.00072617 | ||||
| Approve Hash | 19039936 | 803 days ago | IN | 0 ETH | 0.00165793 | ||||
| Exec Transaction | 15015593 | 1377 days ago | IN | 0 ETH | 0.00582439 | ||||
| Approve Hash | 15015592 | 1377 days ago | IN | 0 ETH | 0.0028542 | ||||
| Approve Hash | 15012254 | 1378 days ago | IN | 0 ETH | 0.00267046 | ||||
| Exec Transaction | 14999672 | 1380 days ago | IN | 0 ETH | 0.00099165 | ||||
| Approve Hash | 14999593 | 1380 days ago | IN | 0 ETH | 0.00054258 | ||||
| Approve Hash | 14999577 | 1380 days ago | IN | 0 ETH | 0.00074501 | ||||
| Approve Hash | 14972520 | 1385 days ago | IN | 0 ETH | 0.00437742 |
Latest 25 internal transactions (View All)
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TokenVestingFactory
Compiler Version
v0.8.0+commit.c7dfd78e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./MultiSig.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./BokkyPooBahsDateTimeLibrary.sol";
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address private _owner;
address private _pendingOwner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() {
_owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == _owner, "onlyOwner");
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() external view returns (address) {
return _pendingOwner;
}
/**
* @dev Allows the current owner to set the pendingOwner address.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) external onlyOwner {
_pendingOwner = newOwner;
}
/**
* @dev Allows the pendingOwner address to finalize the transfer.
*/
function claimOwnership() external {
require(msg.sender == _pendingOwner, "onlyPendingOwner");
emit OwnershipTransferred(_owner, _pendingOwner);
_owner = _pendingOwner;
_pendingOwner = address(0);
}
}
contract TokenVestingFactory is Ownable, MultiSig {
event TokenVestingCreated(address tokenVesting);
// enum VestingType { SeedInvestors, StrategicInvestors, Advisors, Team, All }
struct BeneficiaryIndex {
address tokenVesting;
uint256 vestingType;
bool isExist;
// uint256 index;
}
mapping(address => BeneficiaryIndex) private _beneficiaryIndex;
address[] private _beneficiaries;
address private _tokenAddr;
uint256 private _decimal;
constructor (address tokenAddr, uint256 decimal, address[] memory owners, uint256 threshold) {
require(tokenAddr != address(0), "TokenVestingFactory: token address must not be zero");
_tokenAddr = tokenAddr;
_decimal = decimal;
setupMultiSig(owners, threshold);
}
function create(address beneficiary, uint256 start, uint256 cliff, uint256 initialShare, uint256 periodicShare, bool revocable, uint256 vestingType) onlyOwner external {
require(!_beneficiaryIndex[beneficiary].isExist, "TokenVestingFactory: benficiery exists");
require(vestingType != 0, "TokenVestingFactory: vestingType 0 is reserved");
address tokenVesting = address(new TokenVesting(_tokenAddr, beneficiary, start, cliff, initialShare, periodicShare, _decimal, revocable));
_beneficiaries.push(beneficiary);
_beneficiaryIndex[beneficiary].tokenVesting = tokenVesting;
_beneficiaryIndex[beneficiary].vestingType = vestingType;
_beneficiaryIndex[beneficiary].isExist = true;
emit TokenVestingCreated(tokenVesting);
}
function initialize(address tokenVesting, address from, uint256 amount) external onlyOwner {
TokenVesting(tokenVesting).initialize(from, amount);
}
function update(address tokenVesting, uint256 start, uint256 cliff, uint256 initialShare, uint256 periodicShare, bool revocable) external onlyOwner {
TokenVesting(tokenVesting).update(start, cliff, initialShare, periodicShare, revocable);
}
function getBeneficiaries(uint256 vestingType) external view returns (address[] memory) {
uint256 j = 0;
address[] memory beneficiaries = new address[](_beneficiaries.length);
for (uint256 i = 0; i < _beneficiaries.length; i++) {
address beneficiary = _beneficiaries[i];
if (_beneficiaryIndex[beneficiary].vestingType == vestingType || vestingType == 0) {
beneficiaries[j] = beneficiary;
j++;
}
}
return beneficiaries;
}
function getVestingType(address beneficiary) external view returns (uint256) {
require(_beneficiaryIndex[beneficiary].isExist, "TokenVestingFactory: benficiery does not exist");
return _beneficiaryIndex[beneficiary].vestingType;
}
function getTokenVesting(address beneficiary) external view returns (address) {
require(_beneficiaryIndex[beneficiary].isExist, "TokenVestingFactory: benficiery does not exist");
return _beneficiaryIndex[beneficiary].tokenVesting;
}
function getTokenAddress() external view returns (address) {
return _tokenAddr;
}
function getDecimal() external view returns (uint256) {
return _decimal;
}
function revoke(address tokenVesting) external onlyMultiSig{
TokenVesting(tokenVesting).revoke(owner());
}
}
/**
* @title TokenVesting
* @dev A token holder contract that can release its token balance gradually like a
* typical vesting scheme, with a cliff. Optionally revocable by the
* owner.
*/
contract TokenVesting is Ownable {
using SafeERC20 for IERC20;
event TokenVestingUpdated(uint256 start, uint256 cliff, uint256 initialShare, uint256 periodicShare, bool revocable);
event TokensReleased(address beneficiary, uint256 amount);
event TokenVestingRevoked(address refundAddress, uint256 amount);
event TokenVestingInitialized(address from, uint256 amount);
enum Status {NotInitialized, Initialized, Revoked}
// beneficiary of tokens after they are released
address private _beneficiary;
uint256 private _cliff;
uint256 private _start;
address private _tokenAddr;
uint256 private _initialShare;
uint256 private _periodicShare;
uint256 private _decimal;
uint256 private _released;
bool private _revocable;
Status private _status;
/**
* @dev Creates a vesting contract that vests its balance of any ERC20 token to the
* beneficiary, gradually in a linear fashion. By then all
* of the balance will have vested.
* @param beneficiary address of the beneficiary to whom vested tokens are transferred
* @param cliff duration in seconds of the cliff in which tokens will begin to vest
* @param start the time (as Unix time) at which point vesting starts
* @param revocable whether the vesting is revocable or not
*/
constructor(
address tokenAddr,
address beneficiary,
uint256 start,
uint256 cliff,
uint256 initialShare,
uint256 periodicShare,
uint256 decimal,
bool revocable
)
{
require(beneficiary != address(0), "TokenVesting: beneficiary address must not be zero");
_tokenAddr = tokenAddr;
_beneficiary = beneficiary;
_revocable = revocable;
_cliff = start + cliff;
_start = start;
_initialShare = initialShare;
_periodicShare = periodicShare;
_decimal = decimal;
_status = Status.NotInitialized;
}
/**
* @return TokenVesting details.
*/
function getDetails() external view returns (address, uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool, uint256) {
uint256 _total = IERC20(_tokenAddr).balanceOf(address(this)) + _released;
uint256 _vested = _vestedAmount();
uint256 _releasable = _vestedAmount() - _released;
return (_beneficiary, _initialShare, _periodicShare, _start, _cliff, _total, _vested, _released, _releasable, _revocable, uint256(_status));
}
/**
* @return the initial share of the beneficiary.
*/
function getInitialShare() external view returns (uint256) {
return _initialShare;
}
/**
* @return the periodic share of the beneficiary.
*/
function getPeriodicShare() external view returns (uint256) {
return _periodicShare;
}
/**
* @return the beneficiary of the tokens.
*/
function getBeneficiary() external view returns (address) {
return _beneficiary;
}
/**
* @return the start time of the token vesting.
*/
function getStart() external view returns (uint256) {
return _start;
}
/**
* @return the cliff time of the token vesting.
*/
function getCliff() external view returns (uint256) {
return _cliff;
}
/**
* @return the total amount of the token.
*/
function getTotal() external view returns (uint256) {
return IERC20(_tokenAddr).balanceOf(address(this)) + _released;
}
/**
* @return the amount of the vested token.
*/
function getVested() external view returns (uint256) {
return _vestedAmount();
}
/**
* @return the amount of the token released.
*/
function getReleased() external view returns (uint256) {
return _released;
}
/**
* @return the amount that has already vested but hasn't been released yet.
*/
function getReleasable() public view returns (uint256) {
return _vestedAmount() - _released;
}
/**
* @return true if the vesting is revocable.
*/
function isRevocable() external view returns (bool) {
return _revocable;
}
/**
* @return true if the token is revoked.
*/
function isRevoked() external view returns (bool) {
if (_status == Status.Revoked) {
return true;
} else {
return false;
}
}
/**
* @return status.
*/
function getStatus() external view returns (uint256) {
return uint256(_status);
}
/**
* @notice change status to initialized.
*/
function initialize(address from, uint256 amount) public onlyOwner {
require(_status == Status.NotInitialized, "TokenVesting: status must be NotInitialized");
_status = Status.Initialized;
emit TokenVestingInitialized(address(from), amount);
IERC20(_tokenAddr).safeTransferFrom(from, address(this), amount);
}
/**
* @notice update token vesting contract.
*/
function update(
uint256 start,
uint256 cliff,
uint256 initialShare,
uint256 periodicShare,
bool revocable
) external onlyOwner {
require(_status == Status.NotInitialized, "TokenVesting: status must be NotInitialized");
_start = start;
_cliff = start + cliff;
_initialShare = initialShare;
_periodicShare = periodicShare;
_revocable = revocable;
emit TokenVestingUpdated(_start, _cliff, _initialShare, _periodicShare, _revocable);
}
/**
* @notice Transfers vested tokens to beneficiary.
*/
function release() external {
require(_status != Status.NotInitialized, "TokenVesting: status is NotInitialized");
uint256 unreleased = getReleasable();
require(unreleased > 0, "TokenVesting: releasable amount is zero");
_released = _released + unreleased;
emit TokensReleased(address(_beneficiary), unreleased);
IERC20(_tokenAddr).safeTransfer(_beneficiary, unreleased);
}
/**
* @notice Allows the owner to revoke the vesting. Tokens already vested
* remain in the contract, the rest are returned to the owner.
*/
function revoke(address refundAddress) external onlyOwner {
require(_revocable, "TokenVesting: contract is not revocable");
require(_status != Status.Revoked, "TokenVesting: status is Revoked");
uint256 balance = IERC20(_tokenAddr).balanceOf(address(this));
uint256 unreleased = getReleasable();
uint256 refund = balance - unreleased;
_status = Status.Revoked;
emit TokenVestingRevoked(address(refundAddress), refund);
IERC20(_tokenAddr).safeTransfer(refundAddress, refund);
}
/**
* @dev Calculates the amount that has already vested.
*/
function _vestedAmount() private view returns (uint256) {
uint256 currentBalance = IERC20(_tokenAddr).balanceOf(address(this));
uint256 totalBalance = currentBalance + _released;
uint256 initialRelease = (totalBalance * _initialShare) / ((10 ** _decimal) * 100) ;
if (block.timestamp < _start)
return 0;
if (_status == Status.Revoked)
return totalBalance;
if (block.timestamp < _cliff)
return initialRelease;
uint256 monthlyRelease = (totalBalance * _periodicShare) / ((10 ** _decimal) * 100);
uint256 _months = BokkyPooBahsDateTimeLibrary.diffMonths(_cliff, block.timestamp);
if (initialRelease + (monthlyRelease * (_months + 1)) >= totalBalance) {
return totalBalance;
} else {
return initialRelease + (monthlyRelease * (_months + 1));
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// ----------------------------------------------------------------------------
// BokkyPooBah's DateTime Library v1.01
//
// A gas-efficient Solidity date and time library
//
// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary
//
// Tested date range 1970/01/01 to 2345/12/31
//
// Conventions:
// Unit | Range | Notes
// :-------- |:-------------:|:-----
// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC
// year | 1970 ... 2345 |
// month | 1 ... 12 |
// day | 1 ... 31 |
// hour | 0 ... 23 |
// minute | 0 ... 59 |
// second | 0 ... 59 |
// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday
//
//
// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.
// ----------------------------------------------------------------------------
library BokkyPooBahsDateTimeLibrary {
uint constant SECONDS_PER_DAY = 24 * 60 * 60;
uint constant SECONDS_PER_HOUR = 60 * 60;
uint constant SECONDS_PER_MINUTE = 60;
int constant OFFSET19700101 = 2440588;
uint constant DOW_MON = 1;
uint constant DOW_TUE = 2;
uint constant DOW_WED = 3;
uint constant DOW_THU = 4;
uint constant DOW_FRI = 5;
uint constant DOW_SAT = 6;
uint constant DOW_SUN = 7;
// ------------------------------------------------------------------------
// Calculate the number of days from 1970/01/01 to year/month/day using
// the date conversion algorithm from
// http://aa.usno.navy.mil/faq/docs/JD_Formula.php
// and subtracting the offset 2440588 so that 1970/01/01 is day 0
//
// days = day
// - 32075
// + 1461 * (year + 4800 + (month - 14) / 12) / 4
// + 367 * (month - 2 - (month - 14) / 12 * 12) / 12
// - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4
// - offset
// ------------------------------------------------------------------------
function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) {
require(year >= 1970, "BP01");
int _year = int(year);
int _month = int(month);
int _day = int(day);
int __days = _day
- 32075
+ 1461 * (_year + 4800 + (_month - 14) / 12) / 4
+ 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12
- 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4
- OFFSET19700101;
_days = uint(__days);
}
// ------------------------------------------------------------------------
// Calculate year/month/day from the number of days since 1970/01/01 using
// the date conversion algorithm from
// http://aa.usno.navy.mil/faq/docs/JD_Formula.php
// and adding the offset 2440588 so that 1970/01/01 is day 0
//
// int L = days + 68569 + offset
// int N = 4 * L / 146097
// L = L - (146097 * N + 3) / 4
// year = 4000 * (L + 1) / 1461001
// L = L - 1461 * year / 4 + 31
// month = 80 * L / 2447
// dd = L - 2447 * month / 80
// L = month / 11
// month = month + 2 - 12 * L
// year = 100 * (N - 49) + year + L
// ------------------------------------------------------------------------
function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) {
int __days = int(_days);
int L = __days + 68569 + OFFSET19700101;
int N = 4 * L / 146097;
L = L - (146097 * N + 3) / 4;
int _year = 4000 * (L + 1) / 1461001;
L = L - 1461 * _year / 4 + 31;
int _month = 80 * L / 2447;
int _day = L - 2447 * _month / 80;
L = _month / 11;
_month = _month + 2 - 12 * L;
_year = 100 * (N - 49) + _year + L;
year = uint(_year);
month = uint(_month);
day = uint(_day);
}
function timestampFromDate(uint year, uint month, uint day) internal pure returns (uint timestamp) {
timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;
}
function timestampFromDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (uint timestamp) {
timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second;
}
function timestampToDate(uint timestamp) internal pure returns (uint year, uint month, uint day) {
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function timestampToDateTime(uint timestamp) internal pure returns (uint year, uint month, uint day, uint hour, uint minute, uint second) {
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
uint secs = timestamp % SECONDS_PER_DAY;
hour = secs / SECONDS_PER_HOUR;
secs = secs % SECONDS_PER_HOUR;
minute = secs / SECONDS_PER_MINUTE;
second = secs % SECONDS_PER_MINUTE;
}
function isValidDate(uint year, uint month, uint day) internal pure returns (bool valid) {
if (year >= 1970 && month > 0 && month <= 12) {
uint daysInMonth = _getDaysInMonth(year, month);
if (day > 0 && day <= daysInMonth) {
valid = true;
}
}
}
function isValidDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (bool valid) {
if (isValidDate(year, month, day)) {
if (hour < 24 && minute < 60 && second < 60) {
valid = true;
}
}
}
function isLeapYear(uint timestamp) internal pure returns (bool leapYear) {
(uint year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);
leapYear = _isLeapYear(year);
}
function _isLeapYear(uint year) internal pure returns (bool leapYear) {
leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
function isWeekDay(uint timestamp) internal pure returns (bool weekDay) {
weekDay = getDayOfWeek(timestamp) <= DOW_FRI;
}
function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) {
weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;
}
function getDaysInMonth(uint timestamp) internal pure returns (uint daysInMonth) {
(uint year, uint month,) = _daysToDate(timestamp / SECONDS_PER_DAY);
daysInMonth = _getDaysInMonth(year, month);
}
function _getDaysInMonth(uint year, uint month) internal pure returns (uint daysInMonth) {
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
daysInMonth = 31;
} else if (month != 2) {
daysInMonth = 30;
} else {
daysInMonth = _isLeapYear(year) ? 29 : 28;
}
}
// 1 = Monday, 7 = Sunday
function getDayOfWeek(uint timestamp) internal pure returns (uint dayOfWeek) {
uint _days = timestamp / SECONDS_PER_DAY;
dayOfWeek = (_days + 3) % 7 + 1;
}
function getYear(uint timestamp) internal pure returns (uint year) {
(year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function getMonth(uint timestamp) internal pure returns (uint month) {
(,month,) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function getDay(uint timestamp) internal pure returns (uint day) {
(,,day) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function getHour(uint timestamp) internal pure returns (uint hour) {
uint secs = timestamp % SECONDS_PER_DAY;
hour = secs / SECONDS_PER_HOUR;
}
function getMinute(uint timestamp) internal pure returns (uint minute) {
uint secs = timestamp % SECONDS_PER_HOUR;
minute = secs / SECONDS_PER_MINUTE;
}
function getSecond(uint timestamp) internal pure returns (uint second) {
second = timestamp % SECONDS_PER_MINUTE;
}
function addYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) {
(uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);
year += _years;
uint daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;
require(newTimestamp >= timestamp, "BP02");
}
function addMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) {
(uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);
month += _months;
year += (month - 1) / 12;
month = (month - 1) % 12 + 1;
uint daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;
require(newTimestamp >= timestamp, "BP02");
}
function addDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp + _days * SECONDS_PER_DAY;
require(newTimestamp >= timestamp, "BP02");
}
function addHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;
require(newTimestamp >= timestamp, "BP02");
}
function addMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;
require(newTimestamp >= timestamp, "BP02");
}
function addSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp + _seconds;
require(newTimestamp >= timestamp, "BP02");
}
function subYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) {
(uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);
year -= _years;
uint daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;
require(newTimestamp <= timestamp, "BP03");
}
function subMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) {
(uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);
uint yearMonth = year * 12 + (month - 1) - _months;
year = yearMonth / 12;
month = yearMonth % 12 + 1;
uint daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;
require(newTimestamp <= timestamp, "BP03");
}
function subDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp - _days * SECONDS_PER_DAY;
require(newTimestamp <= timestamp, "BP03");
}
function subHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;
require(newTimestamp <= timestamp, 'BP03');
}
function subMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;
require(newTimestamp <= timestamp, 'BP03');
}
function subSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp - _seconds;
require(newTimestamp <= timestamp, 'BP03');
}
function diffYears(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _years) {
require(fromTimestamp <= toTimestamp, 'BP03');
(uint fromYear,,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);
(uint toYear,,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
_years = toYear - fromYear;
}
function diffMonths(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _months) {
require(fromTimestamp <= toTimestamp, 'BP03');
(uint fromYear, uint fromMonth,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);
(uint toYear, uint toMonth,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
_months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;
}
function diffDays(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _days) {
require(fromTimestamp <= toTimestamp, 'BP03');
_days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;
}
function diffHours(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _hours) {
require(fromTimestamp <= toTimestamp, 'BP03');
_hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;
}
function diffMinutes(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _minutes) {
require(fromTimestamp <= toTimestamp, 'BP03');
_minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;
}
function diffSeconds(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _seconds) {
require(fromTimestamp <= toTimestamp, 'BP03');
_seconds = toTimestamp - fromTimestamp;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MultiSig {
event setupEvent(address[] signers, uint256 threshold);
event ApproveHash(bytes32 indexed approvedHash, address indexed owner);
event ExecutionFailure(bytes32 txHash);
event ExecutionSuccess(bytes32 txHash);
event signerAddEvent(address signer);
event signerRemoveEvent(address signer);
event signerChangedEvent(address oldSigner, address newSigner);
event thresholdEvent(uint256 threshold);
event eventAlreadySigned(address indexed signed);
address[] private _signers;
// Mapping to keep track of all hashes (message or transaction) that have been approved by ANY signers
mapping(address => mapping(bytes32 => uint256)) public approvedHashes;
uint256 internal _threshold;
uint256 public _nonce;
bytes32 public _currentHash;
/**
* @dev Throws if called by any account other than the this contract address.
*/
modifier onlyMultiSig() {
require(msg.sender == address(this), "Only Multisig contract can run this method");
_;
}
constructor () {
}
/**
* @dev setup the multisig contract.
* @param signers List of signers.
* @param threshold The minimum required sign for executing a transaction.
*/
function setupMultiSig(
address[] memory signers,
uint256 threshold
) internal {
require(_threshold == 0, "MS11");
require(threshold <= signers.length, "MS01");
require(threshold > 1, "MS02");
address signer;
for (uint256 i = 0; i < signers.length; i++) {
signer = signers[i];
require(!existSigner(signer), "MS03");
require(signer != address(0), "MS04");
require(signer != address(this), "MS05");
_signers.push(signer);
}
_threshold = threshold;
emit setupEvent(_signers, _threshold);
}
/**
* @dev Allows to execute a Safe transaction confirmed by required number of signers.
* @param data Data payload of transaction.
*/
function execTransaction(
bytes calldata data
) external returns (bool success) {
bytes32 txHash;
// Use scope here to limit variable lifetime and prevent `stack too deep` errors
{
bytes memory txHashData =
encodeTransactionData(
// Transaction info
data,
_nonce
);
// Increase nonce and execute transaction.
_nonce++;
_currentHash = 0x0;
txHash = keccak256(txHashData);
checkSignatures(txHash);
}
// Use scope here to limit variable lifetime and prevent `stack too deep` errors
{
success = execute(data);
if (success) emit ExecutionSuccess(txHash);
else emit ExecutionFailure(txHash);
}
}
/**
* @dev Get the current value of nonce
*/
function getNonce() external view returns (uint256){
return _nonce;
}
/**
* @dev Execute a transaction
* @param data the encoded data of the transaction
*/
function execute(
bytes memory data
) internal returns (bool success) {
address to = address (this);
// We require some gas to emit the events (at least 2500) after the execution
uint256 gasToCall = gasleft() - 2500;
assembly {
success := call(gasToCall, to, 0, add(data, 0x20), mload(data), 0, 0)
}
}
/**
* @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
* @param dataHash Hash of the data
*/
function checkSignatures(bytes32 dataHash) public view {
uint256 threshold = _threshold;
// Check that a threshold is set
require(threshold > 1, "MS02");
address[] memory alreadySigned = getSignersOfHash(dataHash);
require(alreadySigned.length >= threshold, "MS06");
}
/**
* @dev Return the list of signers for a given hash
* @param hash Hash of the data
*/
function getSignersOfHash(
bytes32 hash
) public view returns (address[] memory) {
uint256 j = 0;
address[] memory doneSignersTemp = new address[](_signers.length);
uint256 i;
address currentSigner;
for (i = 0; i < _signers.length; i++) {
currentSigner = _signers[i];
if (approvedHashes[currentSigner][hash] == 1) {
doneSignersTemp[j] = currentSigner;
j++;
}
}
address[] memory doneSigners = new address[](j);
for (i=0; i < j; i++){
doneSigners[i] = doneSignersTemp[i];
}
return doneSigners;
}
/**
* @dev Marks a hash as approved. This can be used to validate a hash that is used by a signature.
* @param data Data payload.
*/
function approveHash(
bytes calldata data
) external {
require(existSigner(msg.sender), "MS07");
bytes32 hashToApprove = getTransactionHash(data, _nonce);
bytes32 hashToCancel = getCancelTransactionHash(_nonce);
if(_currentHash == 0x0) {
require(hashToApprove != hashToCancel, "MS12");
_currentHash = hashToApprove;
}
else {
require(_currentHash == hashToApprove || hashToApprove == hashToCancel, "MS13");
}
approvedHashes[msg.sender][hashToApprove] = 1;
emit ApproveHash(hashToApprove, msg.sender);
}
/**
* @dev Returns the bytes that are hashed to be signed by owners.
* @param data Data payload.
* @param nonce Transaction nonce.
*/
function encodeTransactionData(
bytes calldata data,
uint256 nonce
) public pure returns (bytes memory) {
bytes32 safeTxHash =
keccak256(
abi.encode(
keccak256(data),
nonce
)
);
return abi.encodePacked(safeTxHash);
}
function encodeCancelTransactionData(
uint256 nonce
) public pure returns (bytes memory) {
bytes32 safeTxHash =
keccak256(
abi.encode(
keccak256(""),
nonce
)
);
return abi.encodePacked(safeTxHash);
}
/**
* @dev Returns hash to be signed by owners.
* @param data Data payload.
*/
function getTransactionHash(
bytes calldata data,
uint256 nonce
) public pure returns (bytes32) {
return keccak256(encodeTransactionData(data, nonce));
}
function getCancelTransactionHash(
uint256 nonce
) public pure returns (bytes32) {
return keccak256(encodeCancelTransactionData(nonce));
}
/**
* @dev Check if a given address is a signer or not.
* @param signer signer address.
*/
function existSigner(
address signer
) public view returns (bool) {
for (uint256 i = 0; i < _signers.length; i++) {
address signerI = _signers[i];
if (signerI == signer) {
return true;
}
}
return false;
}
/**
* @dev Get the list of all signers.
*/
function getSigners() external view returns (address[] memory ) {
address[] memory ret = new address[](_signers.length) ;
for (uint256 i = 0; i < _signers.length; i++) {
ret[i] = _signers[i];
}
return ret;
}
/**
* @dev Set a new threshold for signing.
* @param threshold the minimum required signatures for executing a transaction.
*/
function setThreshold(
uint256 threshold
) public onlyMultiSig{
require(threshold <= _signers.length, "MS01");
require(threshold > 1, "MS02");
_threshold = threshold;
emit thresholdEvent(threshold);
}
/**
* @dev Get threshold value.
*/
function getThreshold() external view returns(uint256) {
return _threshold;
}
/**
* @dev Add a new signer and new threshold.
* @param signer new signer address.
* @param threshold new threshold
*/
function addSigner(
address signer,
uint256 threshold
) external onlyMultiSig{
require(!existSigner(signer), "MS03");
require(signer != address(0), "MS04");
require(signer != address(this), "MS05");
_signers.push(signer);
emit signerAddEvent(signer);
setThreshold(threshold);
}
/**
* @dev Remove an old signer
* @param signer an old signer.
* @param threshold new threshold
*/
function removeSigner(
address signer,
uint256 threshold
) external onlyMultiSig{
require(existSigner(signer), "MS07");
require(_signers.length - 1 > 1, "MS09");
require(_signers.length - 1 >= threshold, "MS10");
require(signer != address(0), "MS04");
for (uint256 i = 0; i < _signers.length - 1; i++) {
if (_signers[i] == signer) {
_signers[i] = _signers[_signers.length - 1];
break;
}
}
_signers.pop();
emit signerRemoveEvent(signer);
setThreshold(threshold);
}
/**
* @dev Replace an old signer with a new one
* @param oldSigner old signer.
* @param newSigner new signer
*/
function changeSigner(
address oldSigner,
address newSigner
) external onlyMultiSig{
require(existSigner(oldSigner), "MS07");
require(!existSigner(newSigner), "MS03");
require(newSigner != address(0), "MS04");
require(newSigner != address(this), "MS05");
for (uint256 i = 0; i < _signers.length; i++) {
if (_signers[i] == oldSigner) {
_signers[i] = newSigner;
break;
}
}
emit signerChangedEvent(oldSigner, newSigner);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
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));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
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) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
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");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
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");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(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 {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "istanbul",
"libraries": {},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"tokenAddr","type":"address"},{"internalType":"uint256","name":"decimal","type":"uint256"},{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256","name":"threshold","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"approvedHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"ApproveHash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"ExecutionFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"ExecutionSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenVesting","type":"address"}],"name":"TokenVestingCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"signed","type":"address"}],"name":"eventAlreadySigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"setupEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"signerAddEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":false,"internalType":"address","name":"newSigner","type":"address"}],"name":"signerChangedEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"signerRemoveEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"thresholdEvent","type":"event"},{"inputs":[],"name":"_currentHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"addSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"approveHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"approvedHashes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"oldSigner","type":"address"},{"internalType":"address","name":"newSigner","type":"address"}],"name":"changeSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dataHash","type":"bytes32"}],"name":"checkSignatures","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"cliff","type":"uint256"},{"internalType":"uint256","name":"initialShare","type":"uint256"},{"internalType":"uint256","name":"periodicShare","type":"uint256"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"uint256","name":"vestingType","type":"uint256"}],"name":"create","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"encodeCancelTransactionData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"encodeTransactionData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"execTransaction","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"existSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vestingType","type":"uint256"}],"name":"getBeneficiaries","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"getCancelTransactionHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDecimal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSigners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"getSignersOfHash","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"}],"name":"getTokenVesting","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"getTransactionHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"}],"name":"getVestingType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenVesting","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"removeSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenVesting","type":"address"}],"name":"revoke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"setThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenVesting","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"cliff","type":"uint256"},{"internalType":"uint256","name":"initialShare","type":"uint256"},{"internalType":"uint256","name":"periodicShare","type":"uint256"},{"internalType":"bool","name":"revocable","type":"bool"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b50604051620040943803806200409483398101604081905262000034916200031a565b600080546001600160a01b031916331790556001600160a01b038416620000785760405162461bcd60e51b81526004016200006f906200051a565b60405180910390fd5b600980546001600160a01b0319166001600160a01b038616179055600a839055620000a48282620000ae565b50505050620005b5565b60045415620000d15760405162461bcd60e51b81526004016200006f9062000466565b8151811115620000f55760405162461bcd60e51b81526004016200006f90620004de565b60018111620001185760405162461bcd60e51b81526004016200006f90620004c0565b6000805b835181101562000237578381815181106200014757634e487b7160e01b600052603260045260246000fd5b6020026020010151915062000162826200027f60201b60201c565b15620001825760405162461bcd60e51b81526004016200006f90620004a2565b6001600160a01b038216620001ab5760405162461bcd60e51b81526004016200006f90620004fc565b6001600160a01b038216301415620001d75760405162461bcd60e51b81526004016200006f9062000484565b600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b038416179055806200022e8162000577565b9150506200011c565b5060048290556040517fd95bf29a5cf0fd9865d5be8ce4eb4b05f699471ffd88d15530a0ad63aabe5b1490620002729060029085906200040e565b60405180910390a1505050565b6000805b600254811015620002f757600060028281548110620002b257634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0390811691508416811415620002e157600192505050620002fd565b5080620002ee8162000577565b91505062000283565b50600090505b919050565b80516001600160a01b0381168114620002fd57600080fd5b6000806000806080858703121562000330578384fd5b6200033b8562000302565b60208681015160408801519296509450906001600160401b038082111562000361578485fd5b818801915088601f83011262000375578485fd5b8151818111156200038a576200038a6200059f565b83810260405185828201018181108582111715620003ac57620003ac6200059f565b604052828152858101935084860182860187018d1015620003cb578889fd5b8895505b83861015620003f857620003e38162000302565b855260019590950194938601938601620003cf565b5060609a909a0151989b979a5050505050505050565b6000604082016040835280855480835260608501915086845260209250828420845b82811015620004575781546001600160a01b03168452928401926001918201910162000430565b50505092019290925292915050565b6020808252600490820152634d53313160e01b604082015260600190565b6020808252600490820152634d53303560e01b604082015260600190565b6020808252600490820152634d53303360e01b604082015260600190565b60208082526004908201526326a9981960e11b604082015260600190565b6020808252600490820152634d53303160e01b604082015260600190565b6020808252600490820152631354cc0d60e21b604082015260600190565b60208082526033908201527f546f6b656e56657374696e67466163746f72793a20746f6b656e20616464726560408201527f7373206d757374206e6f74206265207a65726f00000000000000000000000000606082015260800190565b60006000198214156200059857634e487b7160e01b81526011600452602481fd5b5060010190565b634e487b7160e01b600052604160045260246000fd5b613acf80620005c56000396000f3fe60806040523480156200001157600080fd5b50600436106200021f5760003560e01c80637d8329741162000129578063d4f77ab111620000b1578063ee85f5fe116200007b578063ee85f5fe1462000489578063ee93c42b14620004a0578063f2fde38b14620004aa578063fd516a0214620004c1576200021f565b8063d4f77ab11462000447578063d7728b21146200045e578063e30c39781462000475578063e75235b8146200047f576200021f565b8063960bfe0411620000f3578063960bfe0414620003f8578063b7b2c0d7146200040f578063c7da349d1462000426578063d087d288146200043d576200021f565b80637d83297414620003b65780638da5cb5b14620003cd578063926b4edf14620003d757806394cf795e14620003ee576200021f565b80633b05093611620001ad57806365af1bed116200017757806365af1bed146200035a57806374a8f103146200037157806376edaf001462000388578063783804d9146200039f576200021f565b80633b05093614620003185780633bad5426146200032f5780634e71e0c814620003465780635d1222aa1462000350576200021f565b80631794bb3c11620001ef5780631794bb3c14620002ab578063325c714414620002c257806334ce10c414620002d957806335cabd3014620002f2576200021f565b8062742176146200022457806310fe9ae8146200025357806312740b56146200026c57806315e6b0221462000292575b600080fd5b6200023b6200023536600462001b1b565b620004d8565b6040516200024a919062001ca0565b60405180910390f35b6200025d620005e9565b6040516200024a919062001bc6565b620002836200027d36600462001b5f565b620005f8565b6040516200024a919062001cb9565b620002a9620002a33660046200199c565b6200066b565b005b620002a9620002bc366004620019d3565b62000842565b620002a9620002d336600462001b02565b620008d8565b620002e362000936565b6040516200024a919062001bad565b620003096200030336600462001b02565b6200093c565b6040516200024a919062001c51565b620002836200032936600462001b02565b62000b4b565b620002a96200034036600462001a13565b62000bc6565b620002a962000e47565b620002e362000ed8565b620002a96200036b36600462001a13565b62000ede565b620002a96200038236600462001978565b62000ffd565b620002e36200039936600462001b5f565b6200108d565b62000309620003b036600462001b02565b620010ac565b620002e3620003c736600462001a13565b620011e2565b6200025d620011ff565b620002a9620003e836600462001a9b565b6200120e565b62000309620013bc565b620002a96200040936600462001b02565b620014bb565b6200025d6200042036600462001978565b62001567565b6200023b6200043736600462001978565b620015c4565b620002e362001645565b620002a96200045836600462001a3f565b6200164b565b620002e36200046f36600462001b02565b620016ea565b6200025d62001705565b620002e362001714565b620002e36200049a36600462001978565b6200171a565b620002e362001777565b620002a9620004bb36600462001978565b6200177d565b620002a9620004d236600462001b1b565b620017cc565b6000806000620004ec8585600554620005f8565b600580549192506000620005008362002011565b909155505060006006558051602082012091506200051e82620008d8565b506200056084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620018cb92505050565b91508115620005a8577fdc29884a71d2bb98d3c53dc09718be05c7bfd142b7773a5c5cf2517629290ac0816040516200059a919062001bad565b60405180910390a1620005e2565b7fdbe42d02a4e07d7eeff2874efe172540c93b297d206f6d691c9782a257323e3281604051620005d9919062001bad565b60405180910390a15b5092915050565b6009546001600160a01b031690565b6060600084846040516200060e92919062001bb6565b6040519081900381206200062791859060200162001cab565b6040516020818303038152906040528051906020012090508060405160200162000652919062001bad565b6040516020818303038152906040529150509392505050565b333014620006965760405162461bcd60e51b81526004016200068d9062001ee3565b60405180910390fd5b620006a182620015c4565b620006c05760405162461bcd60e51b81526004016200068d9062001d69565b620006cb81620015c4565b15620006eb5760405162461bcd60e51b81526004016200068d9062001da5565b6001600160a01b038116620007145760405162461bcd60e51b81526004016200068d9062001f91565b6001600160a01b038116301415620007405760405162461bcd60e51b81526004016200068d9062001d87565b60005b6002548110156200080257826001600160a01b0316600282815481106200077a57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b03161415620007ed578160028281548110620007b957634e487b7160e01b600052603260045260246000fd5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555062000802565b80620007f98162002011565b91505062000743565b507f7e8e25ddc635cb5bf8351e6459039cf927dca393363ab35edb92f6f16c20853882826040516200083692919062001bda565b60405180910390a15050565b6000546001600160a01b031633146200086f5760405162461bcd60e51b81526004016200068d9062001faf565b60405163cd6dc68760e01b81526001600160a01b0384169063cd6dc687906200089f908590859060040162001c38565b600060405180830381600087803b158015620008ba57600080fd5b505af1158015620008cf573d6000803e3d6000fd5b50505050505050565b60045460018111620008fe5760405162461bcd60e51b81526004016200068d9062001ec5565b60006200090b836200093c565b90508181511015620009315760405162461bcd60e51b81526004016200068d9062001ea7565b505050565b600a5490565b606060008060028054905067ffffffffffffffff8111156200096e57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562000998578160200160208202803683370190505b5090506000805b60025482101562000a635760028281548110620009cc57634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b03168083526003825260408084208a85529092529120549091506001141562000a4e578083858151811062000a2657634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528362000a4a8162002011565b9450505b8162000a5a8162002011565b9250506200099f565b60008467ffffffffffffffff81111562000a8d57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562000ab7578160200160208202803683370190505b509050600092505b8483101562000b3f5783838151811062000ae957634e487b7160e01b600052603260045260246000fd5b602002602001015181848151811062000b1257634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528262000b368162002011565b93505062000abf565b9450505050505b919050565b606060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708360405160200162000b8492919062001cab565b6040516020818303038152906040528051906020012090508060405160200162000baf919062001bad565b604051602081830303815290604052915050919050565b33301462000be85760405162461bcd60e51b81526004016200068d9062001ee3565b62000bf382620015c4565b62000c125760405162461bcd60e51b81526004016200068d9062001d69565b60025460019062000c2590829062001ff7565b1162000c455760405162461bcd60e51b81526004016200068d9062001d0f565b600254819062000c589060019062001ff7565b101562000c795760405162461bcd60e51b81526004016200068d9062001d2d565b6001600160a01b03821662000ca25760405162461bcd60e51b81526004016200068d9062001f91565b60005b60025462000cb69060019062001ff7565b81101562000dbb57826001600160a01b03166002828154811062000cea57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316141562000da6576002805462000d189060019062001ff7565b8154811062000d3757634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600280546001600160a01b03909216918390811062000d7257634e487b7160e01b600052603260045260246000fd5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555062000dbb565b8062000db28162002011565b91505062000ca5565b50600280548062000ddc57634e487b7160e01b600052603160045260246000fd5b600082815260209020810160001990810180546001600160a01b03191690550190556040517f2a26a55a8080e2e746000a8f5cbd1ef67983c5d0bbf17077c34ad78927d020d19062000e3090849062001bc6565b60405180910390a162000e4381620014bb565b5050565b6001546001600160a01b0316331462000e745760405162461bcd60e51b81526004016200068d9062001e7d565b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60055481565b33301462000f005760405162461bcd60e51b81526004016200068d9062001ee3565b62000f0b82620015c4565b1562000f2b5760405162461bcd60e51b81526004016200068d9062001da5565b6001600160a01b03821662000f545760405162461bcd60e51b81526004016200068d9062001f91565b6001600160a01b03821630141562000f805760405162461bcd60e51b81526004016200068d9062001d87565b600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b0384161790556040517fdae259046cd53db960bf96e7d68edf396dbbae145d2f361d945a48d45a3b48a59062000e3090849062001bc6565b3330146200101f5760405162461bcd60e51b81526004016200068d9062001ee3565b806001600160a01b03166374a8f10362001038620011ff565b6040518263ffffffff1660e01b815260040162001056919062001bc6565b600060405180830381600087803b1580156200107157600080fd5b505af115801562001086573d6000803e3d6000fd5b5050505050565b60006200109c848484620005f8565b8051906020012090509392505050565b606060008060088054905067ffffffffffffffff811115620010de57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562001108578160200160208202803683370190505b50905060005b600854811015620011da576000600882815481106200113d57634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b0316808352600790915260409091206001015490915086148062001174575085155b15620011c457808385815181106200119c57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015283620011c08162002011565b9450505b5080620011d18162002011565b9150506200110e565b509392505050565b600360209081526000928352604080842090915290825290205481565b6000546001600160a01b031690565b6000546001600160a01b031633146200123b5760405162461bcd60e51b81526004016200068d9062001faf565b6001600160a01b03871660009081526007602052604090206002015460ff16156200127a5760405162461bcd60e51b81526004016200068d9062001f4b565b806200129a5760405162461bcd60e51b81526004016200068d9062001e2f565b6000600960009054906101000a90046001600160a01b03168888888888600a5489604051620012c990620018f7565b620012dc98979695949392919062001bf4565b604051809103906000f080158015620012f9573d6000803e3d6000fd5b506008805460018181019092557ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b03808d166001600160a01b0319928316811790935560009283526007602052604092839020805491861691909216178155808301869055600201805460ff1916909217909155519091507fd8e638d9ae6f6e4f3267bd58084c383fcc9044b5a1867e9e449098343ae63e1690620013aa90839062001bc6565b60405180910390a15050505050505050565b60025460609060009067ffffffffffffffff811115620013ec57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562001416578160200160208202803683370190505b50905060005b600254811015620014b557600281815481106200144957634e487b7160e01b600052603260045260246000fd5b9060005260206000200160009054906101000a90046001600160a01b03168282815181106200148857634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280620014ac8162002011565b9150506200141c565b50905090565b333014620014dd5760405162461bcd60e51b81526004016200068d9062001ee3565b600254811115620015025760405162461bcd60e51b81526004016200068d9062001f2d565b60018111620015255760405162461bcd60e51b81526004016200068d9062001ec5565b60048190556040517ffe44fa8929b5cdc79f5f66efa51b2f7b70f55504ab5c87dc86680b68a775dcf6906200155c90839062001bad565b60405180910390a150565b6001600160a01b03811660009081526007602052604081206002015460ff16620015a55760405162461bcd60e51b81526004016200068d9062001de1565b506001600160a01b039081166000908152600760205260409020541690565b6000805b6002548110156200163c57600060028281548110620015f757634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0390811691508416811415620016265760019250505062000b46565b5080620016338162002011565b915050620015c8565b50600092915050565b60055490565b6000546001600160a01b03163314620016785760405162461bcd60e51b81526004016200068d9062001faf565b604051630156d01360e71b81526001600160a01b0387169063ab68098090620016ae908890889088908890889060040162001fd2565b600060405180830381600087803b158015620016c957600080fd5b505af1158015620016de573d6000803e3d6000fd5b50505050505050505050565b6000620016f78262000b4b565b805190602001209050919050565b6001546001600160a01b031690565b60045490565b6001600160a01b03811660009081526007602052604081206002015460ff16620017585760405162461bcd60e51b81526004016200068d9062001de1565b506001600160a01b031660009081526007602052604090206001015490565b60065481565b6000546001600160a01b03163314620017aa5760405162461bcd60e51b81526004016200068d9062001faf565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b620017d733620015c4565b620017f65760405162461bcd60e51b81526004016200068d9062001d69565b60006200180783836005546200108d565b9050600062001818600554620016ea565b600654909150620018515780821415620018465760405162461bcd60e51b81526004016200068d9062001dc3565b600682905562001880565b8160065414806200186157508082145b620018805760405162461bcd60e51b81526004016200068d9062001d4b565b336000818152600360209081526040808320868452909152808220600190555184917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350505050565b600030816109c45a620018df919062001ff7565b905060008085516020870160008686f1949350505050565b611a54806200204683390190565b80356001600160a01b038116811462000b4657600080fd5b8035801515811462000b4657600080fd5b60008083601f84011262001940578182fd5b50813567ffffffffffffffff81111562001958578182fd5b6020830191508360208285010111156200197157600080fd5b9250929050565b6000602082840312156200198a578081fd5b620019958262001905565b9392505050565b60008060408385031215620019af578081fd5b620019ba8362001905565b9150620019ca6020840162001905565b90509250929050565b600080600060608486031215620019e8578081fd5b620019f38462001905565b925062001a036020850162001905565b9150604084013590509250925092565b6000806040838503121562001a26578182fd5b62001a318362001905565b946020939093013593505050565b60008060008060008060c0878903121562001a58578182fd5b62001a638762001905565b95506020870135945060408701359350606087013592506080870135915062001a8f60a088016200191d565b90509295509295509295565b600080600080600080600060e0888a03121562001ab6578081fd5b62001ac18862001905565b96506020880135955060408801359450606088013593506080880135925062001aed60a089016200191d565b915060c0880135905092959891949750929550565b60006020828403121562001b14578081fd5b5035919050565b6000806020838503121562001b2e578182fd5b823567ffffffffffffffff81111562001b45578283fd5b62001b53858286016200192e565b90969095509350505050565b60008060006040848603121562001b74578283fd5b833567ffffffffffffffff81111562001b8b578384fd5b62001b99868287016200192e565b909790965060209590950135949350505050565b90815260200190565b6000828483379101908152919050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03988916815296909716602087015260408601949094526060850192909252608084015260a083015260c082015290151560e08201526101000190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b8181101562001c945783516001600160a01b03168352928401929184019160010162001c6d565b50909695505050505050565b901515815260200190565b918252602082015260400190565b6000602080835283518082850152825b8181101562001ce75785810183015185820160400152820162001cc9565b8181111562001cf95783604083870101525b50601f01601f1916929092016040019392505050565b6020808252600490820152634d53303960e01b604082015260600190565b60208082526004908201526304d5331360e41b604082015260600190565b6020808252600490820152634d53313360e01b604082015260600190565b6020808252600490820152634d53303760e01b604082015260600190565b6020808252600490820152634d53303560e01b604082015260600190565b6020808252600490820152634d53303360e01b604082015260600190565b60208082526004908201526326a9989960e11b604082015260600190565b6020808252602e908201527f546f6b656e56657374696e67466163746f72793a2062656e666963696572792060408201526d191bd95cc81b9bdd08195e1a5cdd60921b606082015260800190565b6020808252602e908201527f546f6b656e56657374696e67466163746f72793a2076657374696e675479706560408201526d080c081a5cc81c995cd95c9d995960921b606082015260800190565b60208082526010908201526f37b7363ca832b73234b733a7bbb732b960811b604082015260600190565b60208082526004908201526326a9981b60e11b604082015260600190565b60208082526004908201526326a9981960e11b604082015260600190565b6020808252602a908201527f4f6e6c79204d756c746973696720636f6e74726163742063616e2072756e20746040820152691a1a5cc81b595d1a1bd960b21b606082015260800190565b6020808252600490820152634d53303160e01b604082015260600190565b60208082526026908201527f546f6b656e56657374696e67466163746f72793a2062656e666963696572792060408201526565786973747360d01b606082015260800190565b6020808252600490820152631354cc0d60e21b604082015260600190565b60208082526009908201526837b7363ca7bbb732b960b91b604082015260600190565b9485526020850193909352604084019190915260608301521515608082015260a00190565b6000828210156200200c576200200c6200202f565b500390565b60006000198214156200202857620020286200202f565b5060010190565b634e487b7160e01b600052601160045260246000fdfe60806040523480156200001157600080fd5b5060405162001a5438038062001a5483398101604081905262000034916200010b565b600080546001600160a01b031916331790556001600160a01b038716620000785760405162461bcd60e51b81526004016200006f906200018c565b60405180910390fd5b600580546001600160a01b03808b166001600160a01b03199283161790925560028054928a1692909116919091179055600a805482151560ff19909116179055620000c48587620001de565b60035550600494909455600691909155600755506008555050600a805461ff001916905562000203565b80516001600160a01b03811681146200010657600080fd5b919050565b600080600080600080600080610100898b03121562000128578384fd5b6200013389620000ee565b97506200014360208a01620000ee565b965060408901519550606089015194506080890151935060a0890151925060c0890151915060e089015180151581146200017b578182fd5b809150509295985092959890939650565b60208082526032908201527f546f6b656e56657374696e673a2062656e65666963696172792061646472657360408201527173206d757374206e6f74206265207a65726f60701b606082015260800190565b60008219821115620001fe57634e487b7160e01b81526011600452602481fd5b500190565b61184180620002136000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c8063775a25e3116100b8578063c5292c671161007c578063c5292c67146101fc578063cd6dc68714610204578063e30c397814610217578063f2fde38b1461021f578063f47a6e8414610232578063fbbf93a01461023a57610137565b8063775a25e3146101c95780637a140b8b146101d157806386d1a69f146101d95780638da5cb5b146101e1578063ab680980146101e957610137565b80634e71e0c8116100ff5780634e71e0c814610187578063565a2e2c146101915780635ffd1bad146101a657806363260e36146101ae57806374a8f103146101b657610137565b80630bfdc5191461013c5780630d60e5531461015a57806321617565146101625780632bc9ed021461016a5780634e69d5601461017f575b600080fd5b610144610259565b60405161015191906114d0565b60405180910390f35b610144610260565b61014461026f565b610172610286565b604051610151919061120a565b6101446102ca565b61018f6102f7565b005b61019961038e565b604051610151919061115e565b61017261039d565b6101446103a6565b61018f6101c436600461107f565b6103ac565b610144610546565b6101446105d5565b61018f6105db565b6101996106c9565b61018f6101f73660046110f6565b6106d8565b6101446107c5565b61018f610212366004611099565b6107cb565b6101996108a3565b61018f61022d36600461107f565b6108b2565b6101446108fe565b610242610904565b6040516101519b9a999897969594939291906111af565b6006545b90565b600061026a610a68565b905090565b600060095461027c610a68565b61026a919061178e565b60006002600a54610100900460ff1660028111156102b457634e487b7160e01b600052602160045260246000fd5b14156102c25750600161025d565b50600061025d565b600a54600090610100900460ff16600281111561026a57634e487b7160e01b600052602160045260246000fd5b6001546001600160a01b0316331461032a5760405162461bcd60e51b8152600401610321906113bb565b60405180910390fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6002546001600160a01b031690565b600a5460ff1690565b60035490565b6000546001600160a01b031633146103d65760405162461bcd60e51b8152600401610321906114ad565b600a5460ff166103f85760405162461bcd60e51b81526004016103219061128e565b6002600a54610100900460ff16600281111561042457634e487b7160e01b600052602160045260246000fd5b14156104425760405162461bcd60e51b8152600401610321906112d5565b6005546040516370a0823160e01b81526000916001600160a01b0316906370a082319061047390309060040161115e565b60206040518083038186803b15801561048b57600080fd5b505afa15801561049f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c391906110de565b905060006104cf61026f565b905060006104dd828461178e565b600a805461ff0019166102001790556040519091507f8c82cd5dc1ce07aad22dcf75d3642f20cad51b7d13b907e638e5444bdad41d9d906105219086908490611196565b60405180910390a1600554610540906001600160a01b03168583610c3e565b50505050565b6009546005546040516370a0823160e01b8152600092916001600160a01b0316906370a082319061057b90309060040161115e565b60206040518083038186803b15801561059357600080fd5b505afa1580156105a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cb91906110de565b61026a919061153f565b60075490565b6000600a54610100900460ff16600281111561060757634e487b7160e01b600052602160045260246000fd5b14156106255760405162461bcd60e51b815260040161032190611248565b600061062f61026f565b9050600081116106515760405162461bcd60e51b8152600401610321906113e5565b8060095461065f919061153f565b6009556002546040517fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179916106a1916001600160a01b03909116908490611196565b60405180910390a16002546005546106c6916001600160a01b03918216911683610c3e565b50565b6000546001600160a01b031690565b6000546001600160a01b031633146107025760405162461bcd60e51b8152600401610321906114ad565b6000600a54610100900460ff16600281111561072e57634e487b7160e01b600052602160045260246000fd5b1461074b5760405162461bcd60e51b815260040161032190611370565b600485905561075a848661153f565b600381905560068490556007839055600a805460ff191683151517908190556004546040517f9b226cd59889be3c7db1994851c65da63e7508a07f4a475b702ed8cb42f926af936107b69390918891889160ff909116906114d9565b60405180910390a15050505050565b60045490565b6000546001600160a01b031633146107f55760405162461bcd60e51b8152600401610321906114ad565b6000600a54610100900460ff16600281111561082157634e487b7160e01b600052602160045260246000fd5b1461083e5760405162461bcd60e51b815260040161032190611370565b600a805461ff0019166101001790556040517f3b9c044a0268e30cb1d82d3baf306abfeee1d6e5cf84911b9b78af45da3384ae9061087f9084908490611196565b60405180910390a160055461089f906001600160a01b0316833084610c99565b5050565b6001546001600160a01b031690565b6000546001600160a01b031633146108dc5760405162461bcd60e51b8152600401610321906114ad565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60095490565b600080600080600080600080600080600080600954600560009054906101000a90046001600160a01b03166001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161095a919061115e565b60206040518083038186803b15801561097257600080fd5b505afa158015610986573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109aa91906110de565b6109b4919061153f565b905060006109c0610a68565b905060006009546109cf610a68565b6109d9919061178e565b9050600260009054906101000a90046001600160a01b0316600654600754600454600354878760095488600a60009054906101000a900460ff16600a60019054906101000a900460ff166002811115610a4257634e487b7160e01b600052602160045260246000fd5b9d509d509d509d509d509d509d509d509d509d509d50505050909192939495969798999a565b6005546040516370a0823160e01b815260009182916001600160a01b03909116906370a0823190610a9d90309060040161115e565b60206040518083038186803b158015610ab557600080fd5b505afa158015610ac9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aed91906110de565b9050600060095482610aff919061153f565b90506000600854600a610b1291906115df565b610b1d906064611730565b600654610b2a9084611730565b610b349190611585565b9050600454421015610b4c576000935050505061025d565b6002600a54610100900460ff166002811115610b7857634e487b7160e01b600052602160045260246000fd5b1415610b885750915061025d9050565b600354421015610b9c57925061025d915050565b6000600854600a610bad91906115df565b610bb8906064611730565b600754610bc59085611730565b610bcf9190611585565b90506000610bdf60035442610cba565b905083610bed82600161153f565b610bf79084611730565b610c01908561153f565b10610c1357839550505050505061025d565b610c1e81600161153f565b610c289083611730565b610c32908461153f565b9550505050505061025d565b610c948363a9059cbb60e01b8484604051602401610c5d929190611196565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610d54565b505050565b610540846323b872dd60e01b858585604051602401610c5d93929190611172565b600081831115610cdc5760405162461bcd60e51b81526004016103219061130c565b600080610cf4610cef6201518087611585565b610de3565b509092509050600080610d0d610cef6201518088611585565b50909250905082610d1f85600c611730565b82610d2b85600c611730565b610d35919061153f565b610d3f919061178e565b610d49919061178e565b979650505050505050565b6000610da9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610f579092919063ffffffff16565b805190915015610c945780806020019051810190610dc791906110c2565b610c945760405162461bcd60e51b815260040161032190611463565b60008080838162253d8c610dfa8362010bd96114fe565b610e0491906114fe565b9050600062023ab1610e178360046116ad565b610e219190611557565b90506004610e328262023ab16116ad565b610e3d9060036114fe565b610e479190611557565b610e51908361174f565b9150600062164b09610e648460016114fe565b610e7090610fa06116ad565b610e7a9190611557565b90506004610e8a826105b56116ad565b610e949190611557565b610e9e908461174f565b610ea990601f6114fe565b9250600061098f610ebb8560506116ad565b610ec59190611557565b905060006050610ed78361098f6116ad565b610ee19190611557565b610eeb908661174f565b9050610ef8600b83611557565b9450610f0585600c6116ad565b610f108360026114fe565b610f1a919061174f565b91508483610f2960318761174f565b610f349060646116ad565b610f3e91906114fe565b610f4891906114fe565b9a919950975095505050505050565b6060610f668484600085610f70565b90505b9392505050565b606082471015610f925760405162461bcd60e51b81526004016103219061132a565b610f9b85611025565b610fb75760405162461bcd60e51b81526004016103219061142c565b600080866001600160a01b03168587604051610fd39190611142565b60006040518083038185875af1925050503d8060008114611010576040519150601f19603f3d011682016040523d82523d6000602084013e611015565b606091505b5091509150610d4982828661102f565b803b15155b919050565b6060831561103e575081610f69565b82511561104e5782518084602001fd5b8160405162461bcd60e51b81526004016103219190611215565b80356001600160a01b038116811461102a57600080fd5b600060208284031215611090578081fd5b610f6982611068565b600080604083850312156110ab578081fd5b6110b483611068565b946020939093013593505050565b6000602082840312156110d3578081fd5b8151610f69816117fd565b6000602082840312156110ef578081fd5b5051919050565b600080600080600060a0868803121561110d578081fd5b853594506020860135935060408601359250606086013591506080860135611134816117fd565b809150509295509295909350565b600082516111548184602087016117a5565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039b909b168b5260208b019990995260408a01979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015215156101208301526101408201526101600190565b901515815260200190565b60006020825282518060208401526112348160408501602087016117a5565b601f01601f19169190910160400192915050565b60208082526026908201527f546f6b656e56657374696e673a20737461747573206973204e6f74496e697469604082015265185b1a5e995960d21b606082015260800190565b60208082526027908201527f546f6b656e56657374696e673a20636f6e7472616374206973206e6f74207265604082015266766f6361626c6560c81b606082015260800190565b6020808252601f908201527f546f6b656e56657374696e673a20737461747573206973205265766f6b656400604082015260600190565b6020808252600490820152634250303360e01b604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252602b908201527f546f6b656e56657374696e673a20737461747573206d757374206265204e6f7460408201526a125b9a5d1a585b1a5e995960aa1b606082015260800190565b60208082526010908201526f37b7363ca832b73234b733a7bbb732b960811b604082015260600190565b60208082526027908201527f546f6b656e56657374696e673a2072656c65617361626c6520616d6f756e74206040820152666973207a65726f60c81b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526009908201526837b7363ca7bbb732b960b91b604082015260600190565b90815260200190565b9485526020850193909352604084019190915260608301521515608082015260a00190565b600080821280156001600160ff1b0384900385131615611520576115206117d1565b600160ff1b8390038412811615611539576115396117d1565b50500190565b60008219821115611552576115526117d1565b500190565b600082611566576115666117e7565b600160ff1b821460001984141615611580576115806117d1565b500590565b600082611594576115946117e7565b500490565b80825b60018086116115ab57506115d6565b8187048211156115bd576115bd6117d1565b808616156115ca57918102915b9490941c93800261159c565b94509492505050565b6000610f6960001984846000826115f857506001610f69565b8161160557506000610f69565b816001811461161b576002811461162557611652565b6001915050610f69565b60ff841115611636576116366117d1565b6001841b91508482111561164c5761164c6117d1565b50610f69565b5060208310610133831016604e8410600b8410161715611685575081810a83811115611680576116806117d1565b610f69565b6116928484846001611599565b8086048211156116a4576116a46117d1565b02949350505050565b60006001600160ff1b03818413828413808216868404861116156116d3576116d36117d1565b600160ff1b848712828116878305891216156116f1576116f16117d1565b85871292508782058712848416161561170c5761170c6117d1565b87850587128184161615611722576117226117d1565b505050929093029392505050565b600081600019048311821515161561174a5761174a6117d1565b500290565b60008083128015600160ff1b85018412161561176d5761176d6117d1565b6001600160ff1b0384018313811615611788576117886117d1565b50500390565b6000828210156117a0576117a06117d1565b500390565b60005b838110156117c05781810151838201526020016117a8565b838111156105405750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b80151581146106c657600080fdfea2646970667358221220186ed9064fbc477e481b5f21e08d5310386ea3b168d162cc8ef06f22a28bf90d64736f6c63430008000033a264697066735822122051a279132717742012ccfe760a3621938d06f1be2891506ea64bf0e6c955734164736f6c6343000800003300000000000000000000000065a8fba02f641a13bb7b01d5e1129b0521004f520000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000fa55a42f22a25cc76f736d20d10443ede65003950000000000000000000000008a052e2a04f64775dd80da9ae82c512cf5baf62b000000000000000000000000d29a43775d35d0fb65047d5255930636661a0e72
Deployed Bytecode
0x60806040523480156200001157600080fd5b50600436106200021f5760003560e01c80637d8329741162000129578063d4f77ab111620000b1578063ee85f5fe116200007b578063ee85f5fe1462000489578063ee93c42b14620004a0578063f2fde38b14620004aa578063fd516a0214620004c1576200021f565b8063d4f77ab11462000447578063d7728b21146200045e578063e30c39781462000475578063e75235b8146200047f576200021f565b8063960bfe0411620000f3578063960bfe0414620003f8578063b7b2c0d7146200040f578063c7da349d1462000426578063d087d288146200043d576200021f565b80637d83297414620003b65780638da5cb5b14620003cd578063926b4edf14620003d757806394cf795e14620003ee576200021f565b80633b05093611620001ad57806365af1bed116200017757806365af1bed146200035a57806374a8f103146200037157806376edaf001462000388578063783804d9146200039f576200021f565b80633b05093614620003185780633bad5426146200032f5780634e71e0c814620003465780635d1222aa1462000350576200021f565b80631794bb3c11620001ef5780631794bb3c14620002ab578063325c714414620002c257806334ce10c414620002d957806335cabd3014620002f2576200021f565b8062742176146200022457806310fe9ae8146200025357806312740b56146200026c57806315e6b0221462000292575b600080fd5b6200023b6200023536600462001b1b565b620004d8565b6040516200024a919062001ca0565b60405180910390f35b6200025d620005e9565b6040516200024a919062001bc6565b620002836200027d36600462001b5f565b620005f8565b6040516200024a919062001cb9565b620002a9620002a33660046200199c565b6200066b565b005b620002a9620002bc366004620019d3565b62000842565b620002a9620002d336600462001b02565b620008d8565b620002e362000936565b6040516200024a919062001bad565b620003096200030336600462001b02565b6200093c565b6040516200024a919062001c51565b620002836200032936600462001b02565b62000b4b565b620002a96200034036600462001a13565b62000bc6565b620002a962000e47565b620002e362000ed8565b620002a96200036b36600462001a13565b62000ede565b620002a96200038236600462001978565b62000ffd565b620002e36200039936600462001b5f565b6200108d565b62000309620003b036600462001b02565b620010ac565b620002e3620003c736600462001a13565b620011e2565b6200025d620011ff565b620002a9620003e836600462001a9b565b6200120e565b62000309620013bc565b620002a96200040936600462001b02565b620014bb565b6200025d6200042036600462001978565b62001567565b6200023b6200043736600462001978565b620015c4565b620002e362001645565b620002a96200045836600462001a3f565b6200164b565b620002e36200046f36600462001b02565b620016ea565b6200025d62001705565b620002e362001714565b620002e36200049a36600462001978565b6200171a565b620002e362001777565b620002a9620004bb36600462001978565b6200177d565b620002a9620004d236600462001b1b565b620017cc565b6000806000620004ec8585600554620005f8565b600580549192506000620005008362002011565b909155505060006006558051602082012091506200051e82620008d8565b506200056084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620018cb92505050565b91508115620005a8577fdc29884a71d2bb98d3c53dc09718be05c7bfd142b7773a5c5cf2517629290ac0816040516200059a919062001bad565b60405180910390a1620005e2565b7fdbe42d02a4e07d7eeff2874efe172540c93b297d206f6d691c9782a257323e3281604051620005d9919062001bad565b60405180910390a15b5092915050565b6009546001600160a01b031690565b6060600084846040516200060e92919062001bb6565b6040519081900381206200062791859060200162001cab565b6040516020818303038152906040528051906020012090508060405160200162000652919062001bad565b6040516020818303038152906040529150509392505050565b333014620006965760405162461bcd60e51b81526004016200068d9062001ee3565b60405180910390fd5b620006a182620015c4565b620006c05760405162461bcd60e51b81526004016200068d9062001d69565b620006cb81620015c4565b15620006eb5760405162461bcd60e51b81526004016200068d9062001da5565b6001600160a01b038116620007145760405162461bcd60e51b81526004016200068d9062001f91565b6001600160a01b038116301415620007405760405162461bcd60e51b81526004016200068d9062001d87565b60005b6002548110156200080257826001600160a01b0316600282815481106200077a57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b03161415620007ed578160028281548110620007b957634e487b7160e01b600052603260045260246000fd5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555062000802565b80620007f98162002011565b91505062000743565b507f7e8e25ddc635cb5bf8351e6459039cf927dca393363ab35edb92f6f16c20853882826040516200083692919062001bda565b60405180910390a15050565b6000546001600160a01b031633146200086f5760405162461bcd60e51b81526004016200068d9062001faf565b60405163cd6dc68760e01b81526001600160a01b0384169063cd6dc687906200089f908590859060040162001c38565b600060405180830381600087803b158015620008ba57600080fd5b505af1158015620008cf573d6000803e3d6000fd5b50505050505050565b60045460018111620008fe5760405162461bcd60e51b81526004016200068d9062001ec5565b60006200090b836200093c565b90508181511015620009315760405162461bcd60e51b81526004016200068d9062001ea7565b505050565b600a5490565b606060008060028054905067ffffffffffffffff8111156200096e57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562000998578160200160208202803683370190505b5090506000805b60025482101562000a635760028281548110620009cc57634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b03168083526003825260408084208a85529092529120549091506001141562000a4e578083858151811062000a2657634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528362000a4a8162002011565b9450505b8162000a5a8162002011565b9250506200099f565b60008467ffffffffffffffff81111562000a8d57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562000ab7578160200160208202803683370190505b509050600092505b8483101562000b3f5783838151811062000ae957634e487b7160e01b600052603260045260246000fd5b602002602001015181848151811062000b1257634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528262000b368162002011565b93505062000abf565b9450505050505b919050565b606060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708360405160200162000b8492919062001cab565b6040516020818303038152906040528051906020012090508060405160200162000baf919062001bad565b604051602081830303815290604052915050919050565b33301462000be85760405162461bcd60e51b81526004016200068d9062001ee3565b62000bf382620015c4565b62000c125760405162461bcd60e51b81526004016200068d9062001d69565b60025460019062000c2590829062001ff7565b1162000c455760405162461bcd60e51b81526004016200068d9062001d0f565b600254819062000c589060019062001ff7565b101562000c795760405162461bcd60e51b81526004016200068d9062001d2d565b6001600160a01b03821662000ca25760405162461bcd60e51b81526004016200068d9062001f91565b60005b60025462000cb69060019062001ff7565b81101562000dbb57826001600160a01b03166002828154811062000cea57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316141562000da6576002805462000d189060019062001ff7565b8154811062000d3757634e487b7160e01b600052603260045260246000fd5b600091825260209091200154600280546001600160a01b03909216918390811062000d7257634e487b7160e01b600052603260045260246000fd5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555062000dbb565b8062000db28162002011565b91505062000ca5565b50600280548062000ddc57634e487b7160e01b600052603160045260246000fd5b600082815260209020810160001990810180546001600160a01b03191690550190556040517f2a26a55a8080e2e746000a8f5cbd1ef67983c5d0bbf17077c34ad78927d020d19062000e3090849062001bc6565b60405180910390a162000e4381620014bb565b5050565b6001546001600160a01b0316331462000e745760405162461bcd60e51b81526004016200068d9062001e7d565b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60055481565b33301462000f005760405162461bcd60e51b81526004016200068d9062001ee3565b62000f0b82620015c4565b1562000f2b5760405162461bcd60e51b81526004016200068d9062001da5565b6001600160a01b03821662000f545760405162461bcd60e51b81526004016200068d9062001f91565b6001600160a01b03821630141562000f805760405162461bcd60e51b81526004016200068d9062001d87565b600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b0384161790556040517fdae259046cd53db960bf96e7d68edf396dbbae145d2f361d945a48d45a3b48a59062000e3090849062001bc6565b3330146200101f5760405162461bcd60e51b81526004016200068d9062001ee3565b806001600160a01b03166374a8f10362001038620011ff565b6040518263ffffffff1660e01b815260040162001056919062001bc6565b600060405180830381600087803b1580156200107157600080fd5b505af115801562001086573d6000803e3d6000fd5b5050505050565b60006200109c848484620005f8565b8051906020012090509392505050565b606060008060088054905067ffffffffffffffff811115620010de57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562001108578160200160208202803683370190505b50905060005b600854811015620011da576000600882815481106200113d57634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b0316808352600790915260409091206001015490915086148062001174575085155b15620011c457808385815181106200119c57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015283620011c08162002011565b9450505b5080620011d18162002011565b9150506200110e565b509392505050565b600360209081526000928352604080842090915290825290205481565b6000546001600160a01b031690565b6000546001600160a01b031633146200123b5760405162461bcd60e51b81526004016200068d9062001faf565b6001600160a01b03871660009081526007602052604090206002015460ff16156200127a5760405162461bcd60e51b81526004016200068d9062001f4b565b806200129a5760405162461bcd60e51b81526004016200068d9062001e2f565b6000600960009054906101000a90046001600160a01b03168888888888600a5489604051620012c990620018f7565b620012dc98979695949392919062001bf4565b604051809103906000f080158015620012f9573d6000803e3d6000fd5b506008805460018181019092557ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b03808d166001600160a01b0319928316811790935560009283526007602052604092839020805491861691909216178155808301869055600201805460ff1916909217909155519091507fd8e638d9ae6f6e4f3267bd58084c383fcc9044b5a1867e9e449098343ae63e1690620013aa90839062001bc6565b60405180910390a15050505050505050565b60025460609060009067ffffffffffffffff811115620013ec57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562001416578160200160208202803683370190505b50905060005b600254811015620014b557600281815481106200144957634e487b7160e01b600052603260045260246000fd5b9060005260206000200160009054906101000a90046001600160a01b03168282815181106200148857634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280620014ac8162002011565b9150506200141c565b50905090565b333014620014dd5760405162461bcd60e51b81526004016200068d9062001ee3565b600254811115620015025760405162461bcd60e51b81526004016200068d9062001f2d565b60018111620015255760405162461bcd60e51b81526004016200068d9062001ec5565b60048190556040517ffe44fa8929b5cdc79f5f66efa51b2f7b70f55504ab5c87dc86680b68a775dcf6906200155c90839062001bad565b60405180910390a150565b6001600160a01b03811660009081526007602052604081206002015460ff16620015a55760405162461bcd60e51b81526004016200068d9062001de1565b506001600160a01b039081166000908152600760205260409020541690565b6000805b6002548110156200163c57600060028281548110620015f757634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0390811691508416811415620016265760019250505062000b46565b5080620016338162002011565b915050620015c8565b50600092915050565b60055490565b6000546001600160a01b03163314620016785760405162461bcd60e51b81526004016200068d9062001faf565b604051630156d01360e71b81526001600160a01b0387169063ab68098090620016ae908890889088908890889060040162001fd2565b600060405180830381600087803b158015620016c957600080fd5b505af1158015620016de573d6000803e3d6000fd5b50505050505050505050565b6000620016f78262000b4b565b805190602001209050919050565b6001546001600160a01b031690565b60045490565b6001600160a01b03811660009081526007602052604081206002015460ff16620017585760405162461bcd60e51b81526004016200068d9062001de1565b506001600160a01b031660009081526007602052604090206001015490565b60065481565b6000546001600160a01b03163314620017aa5760405162461bcd60e51b81526004016200068d9062001faf565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b620017d733620015c4565b620017f65760405162461bcd60e51b81526004016200068d9062001d69565b60006200180783836005546200108d565b9050600062001818600554620016ea565b600654909150620018515780821415620018465760405162461bcd60e51b81526004016200068d9062001dc3565b600682905562001880565b8160065414806200186157508082145b620018805760405162461bcd60e51b81526004016200068d9062001d4b565b336000818152600360209081526040808320868452909152808220600190555184917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350505050565b600030816109c45a620018df919062001ff7565b905060008085516020870160008686f1949350505050565b611a54806200204683390190565b80356001600160a01b038116811462000b4657600080fd5b8035801515811462000b4657600080fd5b60008083601f84011262001940578182fd5b50813567ffffffffffffffff81111562001958578182fd5b6020830191508360208285010111156200197157600080fd5b9250929050565b6000602082840312156200198a578081fd5b620019958262001905565b9392505050565b60008060408385031215620019af578081fd5b620019ba8362001905565b9150620019ca6020840162001905565b90509250929050565b600080600060608486031215620019e8578081fd5b620019f38462001905565b925062001a036020850162001905565b9150604084013590509250925092565b6000806040838503121562001a26578182fd5b62001a318362001905565b946020939093013593505050565b60008060008060008060c0878903121562001a58578182fd5b62001a638762001905565b95506020870135945060408701359350606087013592506080870135915062001a8f60a088016200191d565b90509295509295509295565b600080600080600080600060e0888a03121562001ab6578081fd5b62001ac18862001905565b96506020880135955060408801359450606088013593506080880135925062001aed60a089016200191d565b915060c0880135905092959891949750929550565b60006020828403121562001b14578081fd5b5035919050565b6000806020838503121562001b2e578182fd5b823567ffffffffffffffff81111562001b45578283fd5b62001b53858286016200192e565b90969095509350505050565b60008060006040848603121562001b74578283fd5b833567ffffffffffffffff81111562001b8b578384fd5b62001b99868287016200192e565b909790965060209590950135949350505050565b90815260200190565b6000828483379101908152919050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03988916815296909716602087015260408601949094526060850192909252608084015260a083015260c082015290151560e08201526101000190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b8181101562001c945783516001600160a01b03168352928401929184019160010162001c6d565b50909695505050505050565b901515815260200190565b918252602082015260400190565b6000602080835283518082850152825b8181101562001ce75785810183015185820160400152820162001cc9565b8181111562001cf95783604083870101525b50601f01601f1916929092016040019392505050565b6020808252600490820152634d53303960e01b604082015260600190565b60208082526004908201526304d5331360e41b604082015260600190565b6020808252600490820152634d53313360e01b604082015260600190565b6020808252600490820152634d53303760e01b604082015260600190565b6020808252600490820152634d53303560e01b604082015260600190565b6020808252600490820152634d53303360e01b604082015260600190565b60208082526004908201526326a9989960e11b604082015260600190565b6020808252602e908201527f546f6b656e56657374696e67466163746f72793a2062656e666963696572792060408201526d191bd95cc81b9bdd08195e1a5cdd60921b606082015260800190565b6020808252602e908201527f546f6b656e56657374696e67466163746f72793a2076657374696e675479706560408201526d080c081a5cc81c995cd95c9d995960921b606082015260800190565b60208082526010908201526f37b7363ca832b73234b733a7bbb732b960811b604082015260600190565b60208082526004908201526326a9981b60e11b604082015260600190565b60208082526004908201526326a9981960e11b604082015260600190565b6020808252602a908201527f4f6e6c79204d756c746973696720636f6e74726163742063616e2072756e20746040820152691a1a5cc81b595d1a1bd960b21b606082015260800190565b6020808252600490820152634d53303160e01b604082015260600190565b60208082526026908201527f546f6b656e56657374696e67466163746f72793a2062656e666963696572792060408201526565786973747360d01b606082015260800190565b6020808252600490820152631354cc0d60e21b604082015260600190565b60208082526009908201526837b7363ca7bbb732b960b91b604082015260600190565b9485526020850193909352604084019190915260608301521515608082015260a00190565b6000828210156200200c576200200c6200202f565b500390565b60006000198214156200202857620020286200202f565b5060010190565b634e487b7160e01b600052601160045260246000fdfe60806040523480156200001157600080fd5b5060405162001a5438038062001a5483398101604081905262000034916200010b565b600080546001600160a01b031916331790556001600160a01b038716620000785760405162461bcd60e51b81526004016200006f906200018c565b60405180910390fd5b600580546001600160a01b03808b166001600160a01b03199283161790925560028054928a1692909116919091179055600a805482151560ff19909116179055620000c48587620001de565b60035550600494909455600691909155600755506008555050600a805461ff001916905562000203565b80516001600160a01b03811681146200010657600080fd5b919050565b600080600080600080600080610100898b03121562000128578384fd5b6200013389620000ee565b97506200014360208a01620000ee565b965060408901519550606089015194506080890151935060a0890151925060c0890151915060e089015180151581146200017b578182fd5b809150509295985092959890939650565b60208082526032908201527f546f6b656e56657374696e673a2062656e65666963696172792061646472657360408201527173206d757374206e6f74206265207a65726f60701b606082015260800190565b60008219821115620001fe57634e487b7160e01b81526011600452602481fd5b500190565b61184180620002136000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c8063775a25e3116100b8578063c5292c671161007c578063c5292c67146101fc578063cd6dc68714610204578063e30c397814610217578063f2fde38b1461021f578063f47a6e8414610232578063fbbf93a01461023a57610137565b8063775a25e3146101c95780637a140b8b146101d157806386d1a69f146101d95780638da5cb5b146101e1578063ab680980146101e957610137565b80634e71e0c8116100ff5780634e71e0c814610187578063565a2e2c146101915780635ffd1bad146101a657806363260e36146101ae57806374a8f103146101b657610137565b80630bfdc5191461013c5780630d60e5531461015a57806321617565146101625780632bc9ed021461016a5780634e69d5601461017f575b600080fd5b610144610259565b60405161015191906114d0565b60405180910390f35b610144610260565b61014461026f565b610172610286565b604051610151919061120a565b6101446102ca565b61018f6102f7565b005b61019961038e565b604051610151919061115e565b61017261039d565b6101446103a6565b61018f6101c436600461107f565b6103ac565b610144610546565b6101446105d5565b61018f6105db565b6101996106c9565b61018f6101f73660046110f6565b6106d8565b6101446107c5565b61018f610212366004611099565b6107cb565b6101996108a3565b61018f61022d36600461107f565b6108b2565b6101446108fe565b610242610904565b6040516101519b9a999897969594939291906111af565b6006545b90565b600061026a610a68565b905090565b600060095461027c610a68565b61026a919061178e565b60006002600a54610100900460ff1660028111156102b457634e487b7160e01b600052602160045260246000fd5b14156102c25750600161025d565b50600061025d565b600a54600090610100900460ff16600281111561026a57634e487b7160e01b600052602160045260246000fd5b6001546001600160a01b0316331461032a5760405162461bcd60e51b8152600401610321906113bb565b60405180910390fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6002546001600160a01b031690565b600a5460ff1690565b60035490565b6000546001600160a01b031633146103d65760405162461bcd60e51b8152600401610321906114ad565b600a5460ff166103f85760405162461bcd60e51b81526004016103219061128e565b6002600a54610100900460ff16600281111561042457634e487b7160e01b600052602160045260246000fd5b14156104425760405162461bcd60e51b8152600401610321906112d5565b6005546040516370a0823160e01b81526000916001600160a01b0316906370a082319061047390309060040161115e565b60206040518083038186803b15801561048b57600080fd5b505afa15801561049f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c391906110de565b905060006104cf61026f565b905060006104dd828461178e565b600a805461ff0019166102001790556040519091507f8c82cd5dc1ce07aad22dcf75d3642f20cad51b7d13b907e638e5444bdad41d9d906105219086908490611196565b60405180910390a1600554610540906001600160a01b03168583610c3e565b50505050565b6009546005546040516370a0823160e01b8152600092916001600160a01b0316906370a082319061057b90309060040161115e565b60206040518083038186803b15801561059357600080fd5b505afa1580156105a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cb91906110de565b61026a919061153f565b60075490565b6000600a54610100900460ff16600281111561060757634e487b7160e01b600052602160045260246000fd5b14156106255760405162461bcd60e51b815260040161032190611248565b600061062f61026f565b9050600081116106515760405162461bcd60e51b8152600401610321906113e5565b8060095461065f919061153f565b6009556002546040517fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179916106a1916001600160a01b03909116908490611196565b60405180910390a16002546005546106c6916001600160a01b03918216911683610c3e565b50565b6000546001600160a01b031690565b6000546001600160a01b031633146107025760405162461bcd60e51b8152600401610321906114ad565b6000600a54610100900460ff16600281111561072e57634e487b7160e01b600052602160045260246000fd5b1461074b5760405162461bcd60e51b815260040161032190611370565b600485905561075a848661153f565b600381905560068490556007839055600a805460ff191683151517908190556004546040517f9b226cd59889be3c7db1994851c65da63e7508a07f4a475b702ed8cb42f926af936107b69390918891889160ff909116906114d9565b60405180910390a15050505050565b60045490565b6000546001600160a01b031633146107f55760405162461bcd60e51b8152600401610321906114ad565b6000600a54610100900460ff16600281111561082157634e487b7160e01b600052602160045260246000fd5b1461083e5760405162461bcd60e51b815260040161032190611370565b600a805461ff0019166101001790556040517f3b9c044a0268e30cb1d82d3baf306abfeee1d6e5cf84911b9b78af45da3384ae9061087f9084908490611196565b60405180910390a160055461089f906001600160a01b0316833084610c99565b5050565b6001546001600160a01b031690565b6000546001600160a01b031633146108dc5760405162461bcd60e51b8152600401610321906114ad565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60095490565b600080600080600080600080600080600080600954600560009054906101000a90046001600160a01b03166001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161095a919061115e565b60206040518083038186803b15801561097257600080fd5b505afa158015610986573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109aa91906110de565b6109b4919061153f565b905060006109c0610a68565b905060006009546109cf610a68565b6109d9919061178e565b9050600260009054906101000a90046001600160a01b0316600654600754600454600354878760095488600a60009054906101000a900460ff16600a60019054906101000a900460ff166002811115610a4257634e487b7160e01b600052602160045260246000fd5b9d509d509d509d509d509d509d509d509d509d509d50505050909192939495969798999a565b6005546040516370a0823160e01b815260009182916001600160a01b03909116906370a0823190610a9d90309060040161115e565b60206040518083038186803b158015610ab557600080fd5b505afa158015610ac9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aed91906110de565b9050600060095482610aff919061153f565b90506000600854600a610b1291906115df565b610b1d906064611730565b600654610b2a9084611730565b610b349190611585565b9050600454421015610b4c576000935050505061025d565b6002600a54610100900460ff166002811115610b7857634e487b7160e01b600052602160045260246000fd5b1415610b885750915061025d9050565b600354421015610b9c57925061025d915050565b6000600854600a610bad91906115df565b610bb8906064611730565b600754610bc59085611730565b610bcf9190611585565b90506000610bdf60035442610cba565b905083610bed82600161153f565b610bf79084611730565b610c01908561153f565b10610c1357839550505050505061025d565b610c1e81600161153f565b610c289083611730565b610c32908461153f565b9550505050505061025d565b610c948363a9059cbb60e01b8484604051602401610c5d929190611196565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610d54565b505050565b610540846323b872dd60e01b858585604051602401610c5d93929190611172565b600081831115610cdc5760405162461bcd60e51b81526004016103219061130c565b600080610cf4610cef6201518087611585565b610de3565b509092509050600080610d0d610cef6201518088611585565b50909250905082610d1f85600c611730565b82610d2b85600c611730565b610d35919061153f565b610d3f919061178e565b610d49919061178e565b979650505050505050565b6000610da9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610f579092919063ffffffff16565b805190915015610c945780806020019051810190610dc791906110c2565b610c945760405162461bcd60e51b815260040161032190611463565b60008080838162253d8c610dfa8362010bd96114fe565b610e0491906114fe565b9050600062023ab1610e178360046116ad565b610e219190611557565b90506004610e328262023ab16116ad565b610e3d9060036114fe565b610e479190611557565b610e51908361174f565b9150600062164b09610e648460016114fe565b610e7090610fa06116ad565b610e7a9190611557565b90506004610e8a826105b56116ad565b610e949190611557565b610e9e908461174f565b610ea990601f6114fe565b9250600061098f610ebb8560506116ad565b610ec59190611557565b905060006050610ed78361098f6116ad565b610ee19190611557565b610eeb908661174f565b9050610ef8600b83611557565b9450610f0585600c6116ad565b610f108360026114fe565b610f1a919061174f565b91508483610f2960318761174f565b610f349060646116ad565b610f3e91906114fe565b610f4891906114fe565b9a919950975095505050505050565b6060610f668484600085610f70565b90505b9392505050565b606082471015610f925760405162461bcd60e51b81526004016103219061132a565b610f9b85611025565b610fb75760405162461bcd60e51b81526004016103219061142c565b600080866001600160a01b03168587604051610fd39190611142565b60006040518083038185875af1925050503d8060008114611010576040519150601f19603f3d011682016040523d82523d6000602084013e611015565b606091505b5091509150610d4982828661102f565b803b15155b919050565b6060831561103e575081610f69565b82511561104e5782518084602001fd5b8160405162461bcd60e51b81526004016103219190611215565b80356001600160a01b038116811461102a57600080fd5b600060208284031215611090578081fd5b610f6982611068565b600080604083850312156110ab578081fd5b6110b483611068565b946020939093013593505050565b6000602082840312156110d3578081fd5b8151610f69816117fd565b6000602082840312156110ef578081fd5b5051919050565b600080600080600060a0868803121561110d578081fd5b853594506020860135935060408601359250606086013591506080860135611134816117fd565b809150509295509295909350565b600082516111548184602087016117a5565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039b909b168b5260208b019990995260408a01979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015215156101208301526101408201526101600190565b901515815260200190565b60006020825282518060208401526112348160408501602087016117a5565b601f01601f19169190910160400192915050565b60208082526026908201527f546f6b656e56657374696e673a20737461747573206973204e6f74496e697469604082015265185b1a5e995960d21b606082015260800190565b60208082526027908201527f546f6b656e56657374696e673a20636f6e7472616374206973206e6f74207265604082015266766f6361626c6560c81b606082015260800190565b6020808252601f908201527f546f6b656e56657374696e673a20737461747573206973205265766f6b656400604082015260600190565b6020808252600490820152634250303360e01b604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252602b908201527f546f6b656e56657374696e673a20737461747573206d757374206265204e6f7460408201526a125b9a5d1a585b1a5e995960aa1b606082015260800190565b60208082526010908201526f37b7363ca832b73234b733a7bbb732b960811b604082015260600190565b60208082526027908201527f546f6b656e56657374696e673a2072656c65617361626c6520616d6f756e74206040820152666973207a65726f60c81b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b60208082526009908201526837b7363ca7bbb732b960b91b604082015260600190565b90815260200190565b9485526020850193909352604084019190915260608301521515608082015260a00190565b600080821280156001600160ff1b0384900385131615611520576115206117d1565b600160ff1b8390038412811615611539576115396117d1565b50500190565b60008219821115611552576115526117d1565b500190565b600082611566576115666117e7565b600160ff1b821460001984141615611580576115806117d1565b500590565b600082611594576115946117e7565b500490565b80825b60018086116115ab57506115d6565b8187048211156115bd576115bd6117d1565b808616156115ca57918102915b9490941c93800261159c565b94509492505050565b6000610f6960001984846000826115f857506001610f69565b8161160557506000610f69565b816001811461161b576002811461162557611652565b6001915050610f69565b60ff841115611636576116366117d1565b6001841b91508482111561164c5761164c6117d1565b50610f69565b5060208310610133831016604e8410600b8410161715611685575081810a83811115611680576116806117d1565b610f69565b6116928484846001611599565b8086048211156116a4576116a46117d1565b02949350505050565b60006001600160ff1b03818413828413808216868404861116156116d3576116d36117d1565b600160ff1b848712828116878305891216156116f1576116f16117d1565b85871292508782058712848416161561170c5761170c6117d1565b87850587128184161615611722576117226117d1565b505050929093029392505050565b600081600019048311821515161561174a5761174a6117d1565b500290565b60008083128015600160ff1b85018412161561176d5761176d6117d1565b6001600160ff1b0384018313811615611788576117886117d1565b50500390565b6000828210156117a0576117a06117d1565b500390565b60005b838110156117c05781810151838201526020016117a8565b838111156105405750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b80151581146106c657600080fdfea2646970667358221220186ed9064fbc477e481b5f21e08d5310386ea3b168d162cc8ef06f22a28bf90d64736f6c63430008000033a264697066735822122051a279132717742012ccfe760a3621938d06f1be2891506ea64bf0e6c955734164736f6c63430008000033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000065a8fba02f641a13bb7b01d5e1129b0521004f520000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000fa55a42f22a25cc76f736d20d10443ede65003950000000000000000000000008a052e2a04f64775dd80da9ae82c512cf5baf62b000000000000000000000000d29a43775d35d0fb65047d5255930636661a0e72
-----Decoded View---------------
Arg [0] : tokenAddr (address): 0x65a8fbA02F641a13Bb7B01d5E1129b0521004f52
Arg [1] : decimal (uint256): 18
Arg [2] : owners (address[]): 0xfA55A42F22a25cc76F736D20D10443edE6500395,0x8A052E2A04f64775Dd80dA9ae82C512CF5baf62B,0xd29a43775D35d0fB65047D5255930636661a0E72
Arg [3] : threshold (uint256): 2
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 00000000000000000000000065a8fba02f641a13bb7b01d5e1129b0521004f52
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [5] : 000000000000000000000000fa55a42f22a25cc76f736d20d10443ede6500395
Arg [6] : 0000000000000000000000008a052e2a04f64775dd80da9ae82c512cf5baf62b
Arg [7] : 000000000000000000000000d29a43775d35d0fb65047d5255930636661a0e72
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.