Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
- Contract name:
- MultiSigVesting
- Optimization enabled
- true
- Compiler version
- v0.8.7+commit.e28d00a7
- Optimization runs
- 200
- Verified at
- 2022-12-01T07:19:30.104746Z
Contract source code
// Sources flattened with hardhat v2.9.3 https://hardhat.org
// File @openzeppelin/contracts/token/ERC20/[email protected]
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from,
address to,
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);
}
// File @openzeppelin/contracts/utils/[email protected]
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 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");
(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");
(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");
(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");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal 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
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// File @openzeppelin/contracts/token/ERC20/utils/[email protected]
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
/**
* @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'
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
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
// File contracts/VestingWallet.sol
pragma solidity 0.8.7;
/**
* @title VestingWallet
* @dev This contract handles the vesting of Eth and ERC20 tokens for a given beneficiary. Custody of multiple tokens
* can be given to this contract, which will release the token to the beneficiary following a given vesting schedule.
* The vesting schedule is customizable through the {vestedAmount} function.
*
* Any token transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
* Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly)
* be immediately releasable.
*/
contract VestingWallet {
event EtherReleased(uint256 amount);
event ERC20Released(address indexed token, uint256 amount);
address private _beneficiary;
uint64 private _start;
uint64 private _duration;
/**
* @dev Set the beneficiary, start timestamp and vesting duration of the vesting wallet.
*/
function VestingWallet_initialize(
address beneficiaryAddress,
uint64 startTimestamp,
uint64 durationSeconds
) internal {
require(beneficiaryAddress != address(0), "VestingWallet: beneficiary is zero address");
_beneficiary = beneficiaryAddress;
_start = startTimestamp;
_duration = durationSeconds;
}
/**
* @dev Getter for the beneficiary address.
*/
function beneficiary() public view virtual returns (address) {
return _beneficiary;
}
/**
* @dev Getter for the start timestamp.
*/
function start() public view virtual returns (uint256) {
return _start;
}
/**
* @dev Getter for the vesting duration.
*/
function duration() public view virtual returns (uint256) {
return _duration;
}
/**
* @dev Calculates the amount of ether that has already vested. Default implementation is a linear vesting curve.
*/
function vestedAmount(uint64 timestamp) public view virtual returns (uint256) {
return _vestingSchedule(address(this).balance, timestamp);
}
/**
* @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve.
*/
function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) {
return _vestingSchedule(IERC20(token).balanceOf(address(this)), timestamp);
}
/**
* @dev Virtual implementation of the vesting formula. This returns the amout vested, as a function of time, for
* an asset given its total historical allocation.
*/
function _vestingSchedule(uint256 totalAllocation, uint64 timestamp) internal view virtual returns (uint256) {
if (timestamp >= start() + duration()) {
return totalAllocation;
}else{
return 0;
}
}
}
// File contracts/MultiSigWallet.sol
pragma solidity 0.8.7;
contract MultiSigWallet {
/*
* Events
*/
event Confirmation(address indexed sender, uint indexed transactionId);
event Revocation(address indexed sender, uint indexed transactionId);
event Submission(uint indexed transactionId);
event Execution(uint indexed transactionId);
event ExecutionFailure(uint indexed transactionId);
event Deposit(address indexed sender, uint value);
event OwnerAddition(address indexed owner);
event OwnerRemoval(address indexed owner);
event RequirementChange(uint required);
/*
* Constants
*/
uint constant public MAX_OWNER_COUNT = 50;
/*
* Storage
*/
mapping (uint => Transaction) public transactions;
mapping (uint => mapping (address => bool)) public confirmations;
mapping (address => bool) public isOwner;
address[] public owners;
uint public required;
uint public transactionCount;
struct Transaction {
address destination;
uint value;
bytes data;
bool executed;
}
/*
* Modifiers
*/
modifier onlyWallet() {
require(msg.sender == address(this));
_;
}
modifier ownerDoesNotExist(address owner) {
require(!isOwner[owner]);
_;
}
modifier ownerExists(address owner) {
require(isOwner[owner]);
_;
}
modifier transactionExists(uint transactionId) {
require(transactions[transactionId].destination != address(0));
_;
}
modifier confirmed(uint transactionId, address owner) {
require(confirmations[transactionId][owner]);
_;
}
modifier notConfirmed(uint transactionId, address owner) {
require(!confirmations[transactionId][owner]);
_;
}
modifier notExecuted(uint transactionId) {
require(!transactions[transactionId].executed);
_;
}
modifier notNull(address _address) {
require(_address != address(0));
_;
}
modifier validRequirement(uint ownerCount, uint _required) {
require(ownerCount <= MAX_OWNER_COUNT
&& _required <= ownerCount
&& _required != 0
&& ownerCount != 0);
_;
}
/// @dev Fallback function allows to deposit ether.
fallback()
external
payable
{
if (msg.value > 0)
emit Deposit(msg.sender, msg.value);
}
receive()
external
payable
{
if (msg.value > 0)
emit Deposit(msg.sender, msg.value);
}
/*
* Public functions
*/
/// @dev Contract constructor sets initial owners and required number of confirmations.
/// @param _owners List of initial owners.
/// @param _required Number of required confirmations.
function MultiSigWallet_initialize(address[] memory _owners, uint _required)
validRequirement(_owners.length, _required) internal
{
for (uint i=0; i<_owners.length; i++) {
require(!isOwner[_owners[i]] && _owners[i] != address(0));
isOwner[_owners[i]] = true;
}
owners = _owners;
required = _required;
}
/// @dev Allows to add a new owner. Transaction has to be sent by wallet.
/// @param owner Address of new owner.
function addOwner(address owner)
public
onlyWallet
ownerDoesNotExist(owner)
notNull(owner)
validRequirement(owners.length + 1, required)
{
isOwner[owner] = true;
owners.push(owner);
emit OwnerAddition(owner);
}
/// @dev Allows to remove an owner. Transaction has to be sent by wallet.
/// @param owner Address of owner.
function removeOwner(address owner)
public
onlyWallet
ownerExists(owner)
{
isOwner[owner] = false;
for (uint i=0; i<owners.length - 1; i++)
if (owners[i] == owner) {
owners[i] = owners[owners.length - 1];
break;
}
owners.pop();
if (required > owners.length)
changeRequirement(owners.length);
emit OwnerRemoval(owner);
}
/// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet.
/// @param owner Address of owner to be replaced.
/// @param newOwner Address of new owner.
function replaceOwner(address owner, address newOwner)
public
onlyWallet
ownerExists(owner)
ownerDoesNotExist(newOwner)
{
for (uint i=0; i<owners.length; i++)
if (owners[i] == owner) {
owners[i] = newOwner;
break;
}
isOwner[owner] = false;
isOwner[newOwner] = true;
emit OwnerRemoval(owner);
emit OwnerAddition(newOwner);
}
/// @dev Allows to change the number of required confirmations. Transaction has to be sent by wallet.
/// @param _required Number of required confirmations.
function changeRequirement(uint _required)
public
onlyWallet
validRequirement(owners.length, _required)
{
required = _required;
emit RequirementChange(_required);
}
/// @dev Allows an owner to submit and confirm a transaction.
/// @param destination Transaction target address.
/// @param value Transaction ether value.
/// @param data Transaction data payload.
/// @return transactionId Returns transaction ID.
function submitTransaction(address destination, uint value, bytes memory data)
public
returns (uint transactionId)
{
transactionId = addTransaction(destination, value, data);
confirmTransaction(transactionId);
}
/// @dev Allows an owner to confirm a transaction.
/// @param transactionId Transaction ID.
function confirmTransaction(uint transactionId)
public
virtual
ownerExists(msg.sender)
transactionExists(transactionId)
notConfirmed(transactionId, msg.sender)
{
confirmations[transactionId][msg.sender] = true;
emit Confirmation(msg.sender, transactionId);
executeTransaction(transactionId);
}
/// @dev Allows an owner to revoke a confirmation for a transaction.
/// @param transactionId Transaction ID.
function revokeConfirmation(uint transactionId)
public
ownerExists(msg.sender)
confirmed(transactionId, msg.sender)
notExecuted(transactionId)
{
confirmations[transactionId][msg.sender] = false;
emit Revocation(msg.sender, transactionId);
}
/// @dev Allows anyone to execute a confirmed transaction.
/// @param transactionId Transaction ID.
function executeTransaction(uint transactionId)
public
virtual
ownerExists(msg.sender)
confirmed(transactionId, msg.sender)
notExecuted(transactionId)
{
if (isConfirmed(transactionId)) {
Transaction storage txn = transactions[transactionId];
txn.executed = true;
if (external_call(txn.destination, txn.value, txn.data.length, txn.data))
emit Execution(transactionId);
else {
emit ExecutionFailure(transactionId);
txn.executed = false;
}
}
}
// call has been separated into its own function in order to take advantage
// of the Solidity's code generator to produce a loop that copies tx.data into memory.
function external_call(address destination, uint value, uint dataLength, bytes memory data) internal returns (bool) {
bool result;
assembly {
let x := mload(0x40) // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention)
let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that
result := call(
sub(gas(), 34710), // 34710 is the value that solidity is currently emitting
// It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +
// callNewAccountGas (25000, in case the destination address does not exist and needs creating)
destination,
value,
d,
dataLength, // Size of the input (in bytes) - this is what fixes the padding problem
x,
0 // Output is ignored, therefore the output size is zero
)
}
return result;
}
/// @dev Returns the confirmation status of a transaction.
/// @param transactionId Transaction ID.
/// @return Confirmation status.
function isConfirmed(uint transactionId)
public
view
returns (bool)
{
uint count = 0;
for (uint i=0; i<owners.length; i++) {
if (confirmations[transactionId][owners[i]])
count += 1;
if (count == required)
return true;
}
return false;
}
/*
* Internal functions
*/
/// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet.
/// @param destination Transaction target address.
/// @param value Transaction ether value.
/// @param data Transaction data payload.
/// @return transactionId Returns transaction ID.
function addTransaction(address destination, uint value, bytes memory data)
internal
notNull(destination)
returns (uint transactionId)
{
transactionId = transactionCount;
transactions[transactionId] = Transaction({
destination: destination,
value: value,
data: data,
executed: false
});
transactionCount += 1;
emit Submission(transactionId);
}
/*
* Web3 call functions
*/
/// @dev Returns number of confirmations of a transaction.
/// @param transactionId Transaction ID.
/// @return count Number of confirmations.
function getConfirmationCount(uint transactionId)
public
view
returns (uint count)
{
for (uint i=0; i<owners.length; i++)
if (confirmations[transactionId][owners[i]])
count += 1;
}
/// @dev Returns total number of transactions after filers are applied.
/// @param pending Include pending transactions.
/// @param executed Include executed transactions.
/// @return count Total number of transactions after filters are applied.
function getTransactionCount(bool pending, bool executed)
public
view
returns (uint count)
{
for (uint i=0; i<transactionCount; i++)
if ( pending && !transactions[i].executed
|| executed && transactions[i].executed)
count += 1;
}
/// @dev Returns list of owners.
/// @return List of owner addresses.
function getOwners()
public
view
returns (address[] memory)
{
return owners;
}
/// @dev Returns array with owner addresses, which confirmed transaction.
/// @param transactionId Transaction ID.
/// @return _confirmations Returns array of owner addresses.
function getConfirmations(uint transactionId)
public
view
returns (address[] memory _confirmations)
{
address[] memory confirmationsTemp = new address[](owners.length);
uint count = 0;
uint i;
for (i=0; i<owners.length; i++)
if (confirmations[transactionId][owners[i]]) {
confirmationsTemp[count] = owners[i];
count += 1;
}
_confirmations = new address[](count);
for (i=0; i<count; i++)
_confirmations[i] = confirmationsTemp[i];
}
/// @dev Returns list of transaction IDs in defined range.
/// @param from Index start position of transaction array.
/// @param to Index end position of transaction array.
/// @param pending Include pending transactions.
/// @param executed Include executed transactions.
/// @return _transactionIds Returns array of transaction IDs.
function getTransactionIds(uint from, uint to, bool pending, bool executed)
public
view
returns (uint[] memory _transactionIds)
{
uint[] memory transactionIdsTemp = new uint[](transactionCount);
uint count = 0;
uint i;
for (i=0; i<transactionCount; i++)
if ( pending && !transactions[i].executed
|| executed && transactions[i].executed)
{
transactionIdsTemp[count] = i;
count += 1;
}
_transactionIds = new uint[](to - from);
for (i=from; i<to; i++)
_transactionIds[i - from] = transactionIdsTemp[i];
}
}
// File contracts/MultiSigVesting.sol
pragma solidity 0.8.7;
contract MultiSigVesting is MultiSigWallet,VestingWallet{
address public _tokenLp;
address public _token;
address private _wrei;
// address private _pool;
address private immutable _idopool;
constructor() {
_idopool = msg.sender;
}
function initialize(
address[] memory _owners,
uint256 _required,
uint64 _durationSeconds,
address _benefit,
uint64 _time,
address token,
address _lpAddr,
address wrei
) external {
require(msg.sender == _idopool,"only pool");
MultiSigWallet_initialize(_owners, _required);
VestingWallet_initialize(_benefit,_time,_durationSeconds);
_token = token;
_wrei = wrei;
_tokenLp = _lpAddr;
}
function releaseLp() public onlyWallet {
uint256 releasable = vestedAmount(_tokenLp, uint64(block.timestamp));
emit ERC20Released(_tokenLp, releasable);
SafeERC20.safeTransfer(IERC20(_tokenLp), beneficiary(), releasable);
}
function release(uint256 _amount) public onlyWallet {
uint256 value;
require(start() < block.timestamp,"end!");
if(_token == _wrei) {
value = address(this).balance;
require(_amount <= value,"amount lt balanceOf");
payable(beneficiary()).transfer(_amount);
}else{
value = IERC20(_token).balanceOf(address(this));
require(_amount <= value,"amount lt balanceOf");
IERC20(_token).transfer(beneficiary(), _amount);
}
emit EtherReleased(_amount);
}
}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Confirmation","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ERC20Released","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"EtherReleased","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Execution","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ExecutionFailure","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"OwnerAddition","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnerRemoval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RequirementChange","inputs":[{"type":"uint256","name":"required","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Revocation","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"Submission","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_OWNER_COUNT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_token","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"_tokenLp","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"beneficiary","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeRequirement","inputs":[{"type":"uint256","name":"_required","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"confirmTransaction","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"confirmations","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"duration","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeTransaction","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"count","internalType":"uint256"}],"name":"getConfirmationCount","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"_confirmations","internalType":"address[]"}],"name":"getConfirmations","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getOwners","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"count","internalType":"uint256"}],"name":"getTransactionCount","inputs":[{"type":"bool","name":"pending","internalType":"bool"},{"type":"bool","name":"executed","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"_transactionIds","internalType":"uint256[]"}],"name":"getTransactionIds","inputs":[{"type":"uint256","name":"from","internalType":"uint256"},{"type":"uint256","name":"to","internalType":"uint256"},{"type":"bool","name":"pending","internalType":"bool"},{"type":"bool","name":"executed","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address[]","name":"_owners","internalType":"address[]"},{"type":"uint256","name":"_required","internalType":"uint256"},{"type":"uint64","name":"_durationSeconds","internalType":"uint64"},{"type":"address","name":"_benefit","internalType":"address"},{"type":"uint64","name":"_time","internalType":"uint64"},{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"_lpAddr","internalType":"address"},{"type":"address","name":"wrei","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isConfirmed","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owners","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"release","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"releaseLp","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"replaceOwner","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"required","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeConfirmation","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"start","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}],"name":"submitTransaction","inputs":[{"type":"address","name":"destination","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"transactionCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"destination","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"bool","name":"executed","internalType":"bool"}],"name":"transactions","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"vestedAmount","inputs":[{"type":"uint64","name":"timestamp","internalType":"uint64"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"vestedAmount","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint64","name":"timestamp","internalType":"uint64"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x60a060405234801561001057600080fd5b5033606081901b6080526126fe61003260003960006115ce01526126fe6000f3fe6080604052600436106101dc5760003560e01c80639ace38c211610102578063c642747411610095578063dc8452cd11610064578063dc8452cd14610625578063e20056e61461063b578063ecd0c0c31461065b578063ee22610b1461067b57610220565b8063c6427474146105a9578063cf5bf23f146105c9578063d6c3179d146105e9578063d74f8edd1461061057610220565b8063b77bf600116100d1578063b77bf6001461052e578063ba51a6df14610544578063be9a655514610564578063c01a8c841461058957610220565b80639ace38c21461048f578063a0e67e2b146104bf578063a8abe69a146104e1578063b5dc40c31461050e57610220565b806337bdc99b1161017a5780637065cb48116101495780637065cb481461040f578063784547a71461042f578063810ec23b1461044f5780638b51d13f1461046f57610220565b806337bdc99b1461039c57806338af3eed146103bc57806343ad92d5146103da57806354741525146103ef57610220565b8063173825d9116101b6578063173825d9146102e157806320ea8d86146103015780632f54bf6e146103215780633411c81c1461036157610220565b8063025e7c27146102585780630a17b06b146102955780630fb5a6b4146102c357610220565b3661022057341561021e5760405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c906020015b60405180910390a25b005b341561021e5760405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c90602001610215565b34801561026457600080fd5b506102786102733660046123af565b61069b565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102a157600080fd5b506102b56102b036600461244e565b6106c5565b60405190815260200161028c565b3480156102cf57600080fd5b506007546001600160401b03166102b5565b3480156102ed57600080fd5b5061021e6102fc36600461210e565b6106d7565b34801561030d57600080fd5b5061021e61031c3660046123af565b61088e565b34801561032d57600080fd5b5061035161033c36600461210e565b60026020526000908152604090205460ff1681565b604051901515815260200161028c565b34801561036d57600080fd5b5061035161037c3660046123e1565b600160209081526000928352604080842090915290825290205460ff1681565b3480156103a857600080fd5b5061021e6103b73660046123af565b610944565b3480156103c857600080fd5b506006546001600160a01b0316610278565b3480156103e657600080fd5b5061021e610bec565b3480156103fb57600080fd5b506102b561040a366004612376565b610c95565b34801561041b57600080fd5b5061021e61042a36600461210e565b610d12565b34801561043b57600080fd5b5061035161044a3660046123af565b610e2b565b34801561045b57600080fd5b506102b561046a36600461220a565b610eca565b34801561047b57600080fd5b506102b561048a3660046123af565b610f55565b34801561049b57600080fd5b506104af6104aa3660046123af565b610fdb565b60405161028c94939291906124b1565b3480156104cb57600080fd5b506104d4611099565b60405161028c91906124eb565b3480156104ed57600080fd5b506105016104fc366004612404565b6110fb565b60405161028c9190612538565b34801561051a57600080fd5b506104d46105293660046123af565b611291565b34801561053a57600080fd5b506102b560055481565b34801561055057600080fd5b5061021e61055f3660046123af565b611467565b34801561057057600080fd5b50600654600160a01b90046001600160401b03166102b5565b34801561059557600080fd5b5061021e6105a43660046123af565b6114e4565b3480156105b557600080fd5b506102b56105c436600461215c565b6115ab565b3480156105d557600080fd5b5061021e6105e4366004612234565b6115c3565b3480156105f557600080fd5b5060075461027890600160401b90046001600160a01b031681565b34801561061c57600080fd5b506102b5603281565b34801561063157600080fd5b506102b560045481565b34801561064757600080fd5b5061021e610656366004612129565b611698565b34801561066757600080fd5b50600854610278906001600160a01b031681565b34801561068757600080fd5b5061021e6106963660046123af565b61182b565b600381815481106106ab57600080fd5b6000918252602090912001546001600160a01b0316905081565b60006106d147836119ee565b92915050565b3330146106e357600080fd5b6001600160a01b038116600090815260026020526040902054819060ff1661070a57600080fd5b6001600160a01b0382166000908152600260205260408120805460ff191690555b60035461073a906001906125cb565b81101561080a57826001600160a01b03166003828154811061075e5761075e61268e565b6000918252602090912001546001600160a01b031614156107f85760038054610789906001906125cb565b815481106107995761079961268e565b600091825260209091200154600380546001600160a01b0390921691839081106107c5576107c561268e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555061080a565b8061080281612647565b91505061072b565b50600380548061081c5761081c612678565b600082815260209020810160001990810180546001600160a01b031916905501905560035460045411156108565760035461085690611467565b6040516001600160a01b038316907f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9090600090a25050565b3360008181526002602052604090205460ff166108aa57600080fd5b60008281526001602090815260408083203380855292529091205483919060ff166108d457600080fd5b600084815260208190526040902060030154849060ff16156108f557600080fd5b6000858152600160209081526040808320338085529252808320805460ff191690555187927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a35050505050565b33301461095057600080fd5b60004261096d6006546001600160401b03600160a01b9091041690565b106109ac5760405162461bcd60e51b81526004016109a390602080825260049082015263656e642160e01b604082015260600190565b60405180910390fd5b6009546008546001600160a01b0390811691161415610a4d57504780821115610a0d5760405162461bcd60e51b815260206004820152601360248201527230b6b7bab73a10363a103130b630b731b2a7b360691b60448201526064016109a3565b6006546040516001600160a01b039091169083156108fc029084906000818181858888f19350505050158015610a47573d6000803e3d6000fd5b50610bb5565b6008546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610a9057600080fd5b505afa158015610aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac891906123c8565b905080821115610b105760405162461bcd60e51b815260206004820152601360248201527230b6b7bab73a10363a103130b630b731b2a7b360691b60448201526064016109a3565b6008546001600160a01b031663a9059cbb610b336006546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381600087803b158015610b7b57600080fd5b505af1158015610b8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb39190612359565b505b6040518281527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a15050565b333014610bf857600080fd5b600754600090610c1890600160401b90046001600160a01b031642610eca565b600754604051828152919250600160401b90046001600160a01b0316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a2600754610c92906001600160a01b03600160401b90910416610c8c6006546001600160a01b031690565b83611a3d565b50565b6000805b600554811015610d0b57838015610cc2575060008181526020819052604090206003015460ff16155b80610ce65750828015610ce6575060008181526020819052604090206003015460ff165b15610cf957610cf66001836125b3565b91505b80610d0381612647565b915050610c99565b5092915050565b333014610d1e57600080fd5b6001600160a01b038116600090815260026020526040902054819060ff1615610d4657600080fd5b816001600160a01b038116610d5a57600080fd5b600354610d689060016125b3565b60045460328211158015610d7c5750818111155b8015610d8757508015155b8015610d9257508115155b610d9b57600080fd5b6001600160a01b038516600081815260026020526040808220805460ff1916600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b03191684179055517ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d9190a25050505050565b600080805b600354811015610ec05760008481526001602052604081206003805491929184908110610e5f57610e5f61268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1615610e9a57610e976001836125b3565b91505b600454821415610eae575060019392505050565b80610eb881612647565b915050610e30565b5060009392505050565b6040516370a0823160e01b8152306004820152600090610f4e906001600160a01b038516906370a082319060240160206040518083038186803b158015610f1057600080fd5b505afa158015610f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4891906123c8565b836119ee565b9392505050565b6000805b600354811015610fd55760008381526001602052604081206003805491929184908110610f8857610f8861268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1615610fc357610fc06001836125b3565b91505b80610fcd81612647565b915050610f59565b50919050565b6000602081905290815260409020805460018201546002830180546001600160a01b0390931693919261100d90612612565b80601f016020809104026020016040519081016040528092919081815260200182805461103990612612565b80156110865780601f1061105b57610100808354040283529160200191611086565b820191906000526020600020905b81548152906001019060200180831161106957829003601f168201915b5050506003909301549192505060ff1684565b606060038054806020026020016040519081016040528092919081815260200182805480156110f157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116110d3575b5050505050905090565b606060006005546001600160401b03811115611119576111196126a4565b604051908082528060200260200182016040528015611142578160200160208202803683370190505b5090506000805b6005548110156111d957858015611172575060008181526020819052604090206003015460ff16155b806111965750848015611196575060008181526020819052604090206003015460ff165b156111c757808383815181106111ae576111ae61268e565b60209081029190910101526111c46001836125b3565b91505b806111d181612647565b915050611149565b6111e388886125cb565b6001600160401b038111156111fa576111fa6126a4565b604051908082528060200260200182016040528015611223578160200160208202803683370190505b5093508790505b86811015611286578281815181106112445761124461268e565b602002602001015184898361125991906125cb565b815181106112695761126961268e565b60209081029190910101528061127e81612647565b91505061122a565b505050949350505050565b6003546060906000906001600160401b038111156112b1576112b16126a4565b6040519080825280602002602001820160405280156112da578160200160208202803683370190505b5090506000805b6003548110156113b857600085815260016020526040812060038054919291849081106113105761131061268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff16156113a657600381815481106113505761135061268e565b9060005260206000200160009054906101000a90046001600160a01b03168383815181106113805761138061268e565b6001600160a01b03909216602092830291909101909101526113a36001836125b3565b91505b806113b081612647565b9150506112e1565b816001600160401b038111156113d0576113d06126a4565b6040519080825280602002602001820160405280156113f9578160200160208202803683370190505b509350600090505b8181101561145f5782818151811061141b5761141b61268e565b60200260200101518482815181106114355761143561268e565b6001600160a01b03909216602092830291909101909101528061145781612647565b915050611401565b505050919050565b33301461147357600080fd5b60035481603282118015906114885750818111155b801561149357508015155b801561149e57508115155b6114a757600080fd5b60048390556040518381527fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a9060200160405180910390a1505050565b3360008181526002602052604090205460ff1661150057600080fd5b60008281526020819052604090205482906001600160a01b031661152357600080fd5b60008381526001602090815260408083203380855292529091205484919060ff161561154e57600080fd5b6000858152600160208181526040808420338086529252808420805460ff1916909317909255905187927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a36115a48561182b565b5050505050565b60006115b8848484611a94565b9050610f4e816114e4565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146116275760405162461bcd60e51b81526020600482015260096024820152681bdb9b1e481c1bdbdb60ba1b60448201526064016109a3565b6116318888611b87565b61163c858588611cbe565b600880546001600160a01b039485166001600160a01b03199182161790915560098054928516929091169190911790556007805491909216600160401b0268010000000000000000600160e01b03199091161790555050505050565b3330146116a457600080fd5b6001600160a01b038216600090815260026020526040902054829060ff166116cb57600080fd5b6001600160a01b038216600090815260026020526040902054829060ff16156116f357600080fd5b60005b60035481101561179157846001600160a01b03166003828154811061171d5761171d61268e565b6000918252602090912001546001600160a01b0316141561177f57836003828154811061174c5761174c61268e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550611791565b8061178981612647565b9150506116f6565b506001600160a01b03808516600081815260026020526040808220805460ff1990811690915593871682528082208054909416600117909355915190917f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9091a26040516001600160a01b038416907ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d90600090a250505050565b3360008181526002602052604090205460ff1661184757600080fd5b60008281526001602090815260408083203380855292529091205483919060ff1661187157600080fd5b600084815260208190526040902060030154849060ff161561189257600080fd5b61189b85610e2b565b156115a457600085815260208190526040902060038101805460ff19166001908117909155815490820154600283018054611979936001600160a01b03169291906118e590612612565b90508460020180546118f690612612565b80601f016020809104026020016040519081016040528092919081815260200182805461192290612612565b801561196f5780601f106119445761010080835404028352916020019161196f565b820191906000526020600020905b81548152906001019060200180831161195257829003601f168201915b5050505050611d77565b156119ae5760405186907f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7590600090a26119e6565b60405186907f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923690600090a260038101805460ff191690555b505050505050565b6000611a026007546001600160401b031690565b600654600160a01b90046001600160401b0316611a1f91906125b3565b826001600160401b031610611a355750816106d1565b5060006106d1565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611a8f908490611d9a565b505050565b6000836001600160a01b038116611aaa57600080fd5b600554604080516080810182526001600160a01b038881168252602080830189815283850189815260006060860181905287815280845295909520845181546001600160a01b03191694169390931783555160018301559251805194965091939092611b1d926002850192910190611fed565b50606091909101516003909101805460ff19169115159190911790556005805460019190600090611b4f9084906125b3565b909155505060405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b81518160328211158015611b9b5750818111155b8015611ba657508015155b8015611bb157508115155b611bba57600080fd5b60005b8451811015611ca15760026000868381518110611bdc57611bdc61268e565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff16158015611c3c575060006001600160a01b0316858281518110611c2857611c2861268e565b60200260200101516001600160a01b031614155b611c4557600080fd5b600160026000878481518110611c5d57611c5d61268e565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580611c9981612647565b915050611bbd565b508351611cb5906003906020870190612071565b50505060045550565b6001600160a01b038316611d275760405162461bcd60e51b815260206004820152602a60248201527f56657374696e6757616c6c65743a2062656e6566696369617279206973207a65604482015269726f206164647265737360b01b60648201526084016109a3565b600680546001600160a01b03949094166001600160e01b031990941693909317600160a01b6001600160401b0393841602179092556007805467ffffffffffffffff191692909116919091179055565b6000806040516020840160008287838a8c6187965a03f198975050505050505050565b6000611def826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e6c9092919063ffffffff16565b805190915015611a8f5780806020019051810190611e0d9190612359565b611a8f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109a3565b6060611e7b8484600085611e83565b949350505050565b606082471015611ee45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109a3565b6001600160a01b0385163b611f3b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109a3565b600080866001600160a01b03168587604051611f579190612495565b60006040518083038185875af1925050503d8060008114611f94576040519150601f19603f3d011682016040523d82523d6000602084013e611f99565b606091505b5091509150611fa9828286611fb4565b979650505050505050565b60608315611fc3575081610f4e565b825115611fd35782518084602001fd5b8160405162461bcd60e51b81526004016109a39190612570565b828054611ff990612612565b90600052602060002090601f01602090048101928261201b5760008555612061565b82601f1061203457805160ff1916838001178555612061565b82800160010185558215612061579182015b82811115612061578251825591602001919060010190612046565b5061206d9291506120c6565b5090565b828054828255906000526020600020908101928215612061579160200282015b8281111561206157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612091565b5b8082111561206d57600081556001016120c7565b80356001600160a01b03811681146120f257600080fd5b919050565b80356001600160401b03811681146120f257600080fd5b60006020828403121561212057600080fd5b610f4e826120db565b6000806040838503121561213c57600080fd5b612145836120db565b9150612153602084016120db565b90509250929050565b60008060006060848603121561217157600080fd5b61217a846120db565b9250602080850135925060408501356001600160401b038082111561219e57600080fd5b818701915087601f8301126121b257600080fd5b8135818111156121c4576121c46126a4565b6121d6601f8201601f19168501612583565b915080825288848285010111156121ec57600080fd5b80848401858401376000848284010152508093505050509250925092565b6000806040838503121561221d57600080fd5b612226836120db565b9150612153602084016120f7565b600080600080600080600080610100898b03121561225157600080fd5b6001600160401b03808a35111561226757600080fd5b89358a018b601f82011261227a57600080fd5b80358281111561228c5761228c6126a4565b8060051b925061229e60208401612583565b80828252602082019150602084018f60208787010111156122be57600080fd5b600095505b838610156122e9576122d4816120db565b835260019590950194602092830192016122c3565b509b5050505060208a01359750612304905060408a016120f7565b955061231260608a016120db565b945061232060808a016120f7565b935061232e60a08a016120db565b925061233c60c08a016120db565b915061234a60e08a016120db565b90509295985092959890939650565b60006020828403121561236b57600080fd5b8151610f4e816126ba565b6000806040838503121561238957600080fd5b8235612394816126ba565b915060208301356123a4816126ba565b809150509250929050565b6000602082840312156123c157600080fd5b5035919050565b6000602082840312156123da57600080fd5b5051919050565b600080604083850312156123f457600080fd5b82359150612153602084016120db565b6000806000806080858703121561241a57600080fd5b84359350602085013592506040850135612433816126ba565b91506060850135612443816126ba565b939692955090935050565b60006020828403121561246057600080fd5b610f4e826120f7565b600081518084526124818160208601602086016125e2565b601f01601f19169290920160200192915050565b600082516124a78184602087016125e2565b9190910192915050565b60018060a01b03851681528360208201526080604082015260006124d86080830185612469565b9050821515606083015295945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561252c5783516001600160a01b031683529284019291840191600101612507565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561252c57835183529284019291840191600101612554565b602081526000610f4e6020830184612469565b604051601f8201601f191681016001600160401b03811182821017156125ab576125ab6126a4565b604052919050565b600082198211156125c6576125c6612662565b500190565b6000828210156125dd576125dd612662565b500390565b60005b838110156125fd5781810151838201526020016125e5565b8381111561260c576000848401525b50505050565b600181811c9082168061262657607f821691505b60208210811415610fd557634e487b7160e01b600052602260045260246000fd5b600060001982141561265b5761265b612662565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8015158114610c9257600080fdfea2646970667358221220ad5f1b47d2adf92bad4533ffe2cbf7d6d45660df712721af9b5b08a8d8a1354664736f6c63430008070033
Deployed ByteCode
0x6080604052600436106101dc5760003560e01c80639ace38c211610102578063c642747411610095578063dc8452cd11610064578063dc8452cd14610625578063e20056e61461063b578063ecd0c0c31461065b578063ee22610b1461067b57610220565b8063c6427474146105a9578063cf5bf23f146105c9578063d6c3179d146105e9578063d74f8edd1461061057610220565b8063b77bf600116100d1578063b77bf6001461052e578063ba51a6df14610544578063be9a655514610564578063c01a8c841461058957610220565b80639ace38c21461048f578063a0e67e2b146104bf578063a8abe69a146104e1578063b5dc40c31461050e57610220565b806337bdc99b1161017a5780637065cb48116101495780637065cb481461040f578063784547a71461042f578063810ec23b1461044f5780638b51d13f1461046f57610220565b806337bdc99b1461039c57806338af3eed146103bc57806343ad92d5146103da57806354741525146103ef57610220565b8063173825d9116101b6578063173825d9146102e157806320ea8d86146103015780632f54bf6e146103215780633411c81c1461036157610220565b8063025e7c27146102585780630a17b06b146102955780630fb5a6b4146102c357610220565b3661022057341561021e5760405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c906020015b60405180910390a25b005b341561021e5760405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c90602001610215565b34801561026457600080fd5b506102786102733660046123af565b61069b565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102a157600080fd5b506102b56102b036600461244e565b6106c5565b60405190815260200161028c565b3480156102cf57600080fd5b506007546001600160401b03166102b5565b3480156102ed57600080fd5b5061021e6102fc36600461210e565b6106d7565b34801561030d57600080fd5b5061021e61031c3660046123af565b61088e565b34801561032d57600080fd5b5061035161033c36600461210e565b60026020526000908152604090205460ff1681565b604051901515815260200161028c565b34801561036d57600080fd5b5061035161037c3660046123e1565b600160209081526000928352604080842090915290825290205460ff1681565b3480156103a857600080fd5b5061021e6103b73660046123af565b610944565b3480156103c857600080fd5b506006546001600160a01b0316610278565b3480156103e657600080fd5b5061021e610bec565b3480156103fb57600080fd5b506102b561040a366004612376565b610c95565b34801561041b57600080fd5b5061021e61042a36600461210e565b610d12565b34801561043b57600080fd5b5061035161044a3660046123af565b610e2b565b34801561045b57600080fd5b506102b561046a36600461220a565b610eca565b34801561047b57600080fd5b506102b561048a3660046123af565b610f55565b34801561049b57600080fd5b506104af6104aa3660046123af565b610fdb565b60405161028c94939291906124b1565b3480156104cb57600080fd5b506104d4611099565b60405161028c91906124eb565b3480156104ed57600080fd5b506105016104fc366004612404565b6110fb565b60405161028c9190612538565b34801561051a57600080fd5b506104d46105293660046123af565b611291565b34801561053a57600080fd5b506102b560055481565b34801561055057600080fd5b5061021e61055f3660046123af565b611467565b34801561057057600080fd5b50600654600160a01b90046001600160401b03166102b5565b34801561059557600080fd5b5061021e6105a43660046123af565b6114e4565b3480156105b557600080fd5b506102b56105c436600461215c565b6115ab565b3480156105d557600080fd5b5061021e6105e4366004612234565b6115c3565b3480156105f557600080fd5b5060075461027890600160401b90046001600160a01b031681565b34801561061c57600080fd5b506102b5603281565b34801561063157600080fd5b506102b560045481565b34801561064757600080fd5b5061021e610656366004612129565b611698565b34801561066757600080fd5b50600854610278906001600160a01b031681565b34801561068757600080fd5b5061021e6106963660046123af565b61182b565b600381815481106106ab57600080fd5b6000918252602090912001546001600160a01b0316905081565b60006106d147836119ee565b92915050565b3330146106e357600080fd5b6001600160a01b038116600090815260026020526040902054819060ff1661070a57600080fd5b6001600160a01b0382166000908152600260205260408120805460ff191690555b60035461073a906001906125cb565b81101561080a57826001600160a01b03166003828154811061075e5761075e61268e565b6000918252602090912001546001600160a01b031614156107f85760038054610789906001906125cb565b815481106107995761079961268e565b600091825260209091200154600380546001600160a01b0390921691839081106107c5576107c561268e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555061080a565b8061080281612647565b91505061072b565b50600380548061081c5761081c612678565b600082815260209020810160001990810180546001600160a01b031916905501905560035460045411156108565760035461085690611467565b6040516001600160a01b038316907f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9090600090a25050565b3360008181526002602052604090205460ff166108aa57600080fd5b60008281526001602090815260408083203380855292529091205483919060ff166108d457600080fd5b600084815260208190526040902060030154849060ff16156108f557600080fd5b6000858152600160209081526040808320338085529252808320805460ff191690555187927ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e991a35050505050565b33301461095057600080fd5b60004261096d6006546001600160401b03600160a01b9091041690565b106109ac5760405162461bcd60e51b81526004016109a390602080825260049082015263656e642160e01b604082015260600190565b60405180910390fd5b6009546008546001600160a01b0390811691161415610a4d57504780821115610a0d5760405162461bcd60e51b815260206004820152601360248201527230b6b7bab73a10363a103130b630b731b2a7b360691b60448201526064016109a3565b6006546040516001600160a01b039091169083156108fc029084906000818181858888f19350505050158015610a47573d6000803e3d6000fd5b50610bb5565b6008546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610a9057600080fd5b505afa158015610aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac891906123c8565b905080821115610b105760405162461bcd60e51b815260206004820152601360248201527230b6b7bab73a10363a103130b630b731b2a7b360691b60448201526064016109a3565b6008546001600160a01b031663a9059cbb610b336006546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381600087803b158015610b7b57600080fd5b505af1158015610b8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb39190612359565b505b6040518281527fda9d4e5f101b8b9b1c5b76d0c5a9f7923571acfc02376aa076b75a8c080c956b9060200160405180910390a15050565b333014610bf857600080fd5b600754600090610c1890600160401b90046001600160a01b031642610eca565b600754604051828152919250600160401b90046001600160a01b0316907fc0e523490dd523c33b1878c9eb14ff46991e3f5b2cd33710918618f2a39cba1b9060200160405180910390a2600754610c92906001600160a01b03600160401b90910416610c8c6006546001600160a01b031690565b83611a3d565b50565b6000805b600554811015610d0b57838015610cc2575060008181526020819052604090206003015460ff16155b80610ce65750828015610ce6575060008181526020819052604090206003015460ff165b15610cf957610cf66001836125b3565b91505b80610d0381612647565b915050610c99565b5092915050565b333014610d1e57600080fd5b6001600160a01b038116600090815260026020526040902054819060ff1615610d4657600080fd5b816001600160a01b038116610d5a57600080fd5b600354610d689060016125b3565b60045460328211158015610d7c5750818111155b8015610d8757508015155b8015610d9257508115155b610d9b57600080fd5b6001600160a01b038516600081815260026020526040808220805460ff1916600190811790915560038054918201815583527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b03191684179055517ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d9190a25050505050565b600080805b600354811015610ec05760008481526001602052604081206003805491929184908110610e5f57610e5f61268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1615610e9a57610e976001836125b3565b91505b600454821415610eae575060019392505050565b80610eb881612647565b915050610e30565b5060009392505050565b6040516370a0823160e01b8152306004820152600090610f4e906001600160a01b038516906370a082319060240160206040518083038186803b158015610f1057600080fd5b505afa158015610f24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4891906123c8565b836119ee565b9392505050565b6000805b600354811015610fd55760008381526001602052604081206003805491929184908110610f8857610f8861268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1615610fc357610fc06001836125b3565b91505b80610fcd81612647565b915050610f59565b50919050565b6000602081905290815260409020805460018201546002830180546001600160a01b0390931693919261100d90612612565b80601f016020809104026020016040519081016040528092919081815260200182805461103990612612565b80156110865780601f1061105b57610100808354040283529160200191611086565b820191906000526020600020905b81548152906001019060200180831161106957829003601f168201915b5050506003909301549192505060ff1684565b606060038054806020026020016040519081016040528092919081815260200182805480156110f157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116110d3575b5050505050905090565b606060006005546001600160401b03811115611119576111196126a4565b604051908082528060200260200182016040528015611142578160200160208202803683370190505b5090506000805b6005548110156111d957858015611172575060008181526020819052604090206003015460ff16155b806111965750848015611196575060008181526020819052604090206003015460ff165b156111c757808383815181106111ae576111ae61268e565b60209081029190910101526111c46001836125b3565b91505b806111d181612647565b915050611149565b6111e388886125cb565b6001600160401b038111156111fa576111fa6126a4565b604051908082528060200260200182016040528015611223578160200160208202803683370190505b5093508790505b86811015611286578281815181106112445761124461268e565b602002602001015184898361125991906125cb565b815181106112695761126961268e565b60209081029190910101528061127e81612647565b91505061122a565b505050949350505050565b6003546060906000906001600160401b038111156112b1576112b16126a4565b6040519080825280602002602001820160405280156112da578160200160208202803683370190505b5090506000805b6003548110156113b857600085815260016020526040812060038054919291849081106113105761131061268e565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff16156113a657600381815481106113505761135061268e565b9060005260206000200160009054906101000a90046001600160a01b03168383815181106113805761138061268e565b6001600160a01b03909216602092830291909101909101526113a36001836125b3565b91505b806113b081612647565b9150506112e1565b816001600160401b038111156113d0576113d06126a4565b6040519080825280602002602001820160405280156113f9578160200160208202803683370190505b509350600090505b8181101561145f5782818151811061141b5761141b61268e565b60200260200101518482815181106114355761143561268e565b6001600160a01b03909216602092830291909101909101528061145781612647565b915050611401565b505050919050565b33301461147357600080fd5b60035481603282118015906114885750818111155b801561149357508015155b801561149e57508115155b6114a757600080fd5b60048390556040518381527fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a9060200160405180910390a1505050565b3360008181526002602052604090205460ff1661150057600080fd5b60008281526020819052604090205482906001600160a01b031661152357600080fd5b60008381526001602090815260408083203380855292529091205484919060ff161561154e57600080fd5b6000858152600160208181526040808420338086529252808420805460ff1916909317909255905187927f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef91a36115a48561182b565b5050505050565b60006115b8848484611a94565b9050610f4e816114e4565b336001600160a01b037f00000000000000000000000090c9ea90db9e924b5e4f705b5edd04d0ad1d787d16146116275760405162461bcd60e51b81526020600482015260096024820152681bdb9b1e481c1bdbdb60ba1b60448201526064016109a3565b6116318888611b87565b61163c858588611cbe565b600880546001600160a01b039485166001600160a01b03199182161790915560098054928516929091169190911790556007805491909216600160401b0268010000000000000000600160e01b03199091161790555050505050565b3330146116a457600080fd5b6001600160a01b038216600090815260026020526040902054829060ff166116cb57600080fd5b6001600160a01b038216600090815260026020526040902054829060ff16156116f357600080fd5b60005b60035481101561179157846001600160a01b03166003828154811061171d5761171d61268e565b6000918252602090912001546001600160a01b0316141561177f57836003828154811061174c5761174c61268e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550611791565b8061178981612647565b9150506116f6565b506001600160a01b03808516600081815260026020526040808220805460ff1990811690915593871682528082208054909416600117909355915190917f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9091a26040516001600160a01b038416907ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d90600090a250505050565b3360008181526002602052604090205460ff1661184757600080fd5b60008281526001602090815260408083203380855292529091205483919060ff1661187157600080fd5b600084815260208190526040902060030154849060ff161561189257600080fd5b61189b85610e2b565b156115a457600085815260208190526040902060038101805460ff19166001908117909155815490820154600283018054611979936001600160a01b03169291906118e590612612565b90508460020180546118f690612612565b80601f016020809104026020016040519081016040528092919081815260200182805461192290612612565b801561196f5780601f106119445761010080835404028352916020019161196f565b820191906000526020600020905b81548152906001019060200180831161195257829003601f168201915b5050505050611d77565b156119ae5760405186907f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7590600090a26119e6565b60405186907f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923690600090a260038101805460ff191690555b505050505050565b6000611a026007546001600160401b031690565b600654600160a01b90046001600160401b0316611a1f91906125b3565b826001600160401b031610611a355750816106d1565b5060006106d1565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611a8f908490611d9a565b505050565b6000836001600160a01b038116611aaa57600080fd5b600554604080516080810182526001600160a01b038881168252602080830189815283850189815260006060860181905287815280845295909520845181546001600160a01b03191694169390931783555160018301559251805194965091939092611b1d926002850192910190611fed565b50606091909101516003909101805460ff19169115159190911790556005805460019190600090611b4f9084906125b3565b909155505060405182907fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5190600090a2509392505050565b81518160328211158015611b9b5750818111155b8015611ba657508015155b8015611bb157508115155b611bba57600080fd5b60005b8451811015611ca15760026000868381518110611bdc57611bdc61268e565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff16158015611c3c575060006001600160a01b0316858281518110611c2857611c2861268e565b60200260200101516001600160a01b031614155b611c4557600080fd5b600160026000878481518110611c5d57611c5d61268e565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580611c9981612647565b915050611bbd565b508351611cb5906003906020870190612071565b50505060045550565b6001600160a01b038316611d275760405162461bcd60e51b815260206004820152602a60248201527f56657374696e6757616c6c65743a2062656e6566696369617279206973207a65604482015269726f206164647265737360b01b60648201526084016109a3565b600680546001600160a01b03949094166001600160e01b031990941693909317600160a01b6001600160401b0393841602179092556007805467ffffffffffffffff191692909116919091179055565b6000806040516020840160008287838a8c6187965a03f198975050505050505050565b6000611def826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e6c9092919063ffffffff16565b805190915015611a8f5780806020019051810190611e0d9190612359565b611a8f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109a3565b6060611e7b8484600085611e83565b949350505050565b606082471015611ee45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109a3565b6001600160a01b0385163b611f3b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109a3565b600080866001600160a01b03168587604051611f579190612495565b60006040518083038185875af1925050503d8060008114611f94576040519150601f19603f3d011682016040523d82523d6000602084013e611f99565b606091505b5091509150611fa9828286611fb4565b979650505050505050565b60608315611fc3575081610f4e565b825115611fd35782518084602001fd5b8160405162461bcd60e51b81526004016109a39190612570565b828054611ff990612612565b90600052602060002090601f01602090048101928261201b5760008555612061565b82601f1061203457805160ff1916838001178555612061565b82800160010185558215612061579182015b82811115612061578251825591602001919060010190612046565b5061206d9291506120c6565b5090565b828054828255906000526020600020908101928215612061579160200282015b8281111561206157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190612091565b5b8082111561206d57600081556001016120c7565b80356001600160a01b03811681146120f257600080fd5b919050565b80356001600160401b03811681146120f257600080fd5b60006020828403121561212057600080fd5b610f4e826120db565b6000806040838503121561213c57600080fd5b612145836120db565b9150612153602084016120db565b90509250929050565b60008060006060848603121561217157600080fd5b61217a846120db565b9250602080850135925060408501356001600160401b038082111561219e57600080fd5b818701915087601f8301126121b257600080fd5b8135818111156121c4576121c46126a4565b6121d6601f8201601f19168501612583565b915080825288848285010111156121ec57600080fd5b80848401858401376000848284010152508093505050509250925092565b6000806040838503121561221d57600080fd5b612226836120db565b9150612153602084016120f7565b600080600080600080600080610100898b03121561225157600080fd5b6001600160401b03808a35111561226757600080fd5b89358a018b601f82011261227a57600080fd5b80358281111561228c5761228c6126a4565b8060051b925061229e60208401612583565b80828252602082019150602084018f60208787010111156122be57600080fd5b600095505b838610156122e9576122d4816120db565b835260019590950194602092830192016122c3565b509b5050505060208a01359750612304905060408a016120f7565b955061231260608a016120db565b945061232060808a016120f7565b935061232e60a08a016120db565b925061233c60c08a016120db565b915061234a60e08a016120db565b90509295985092959890939650565b60006020828403121561236b57600080fd5b8151610f4e816126ba565b6000806040838503121561238957600080fd5b8235612394816126ba565b915060208301356123a4816126ba565b809150509250929050565b6000602082840312156123c157600080fd5b5035919050565b6000602082840312156123da57600080fd5b5051919050565b600080604083850312156123f457600080fd5b82359150612153602084016120db565b6000806000806080858703121561241a57600080fd5b84359350602085013592506040850135612433816126ba565b91506060850135612443816126ba565b939692955090935050565b60006020828403121561246057600080fd5b610f4e826120f7565b600081518084526124818160208601602086016125e2565b601f01601f19169290920160200192915050565b600082516124a78184602087016125e2565b9190910192915050565b60018060a01b03851681528360208201526080604082015260006124d86080830185612469565b9050821515606083015295945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561252c5783516001600160a01b031683529284019291840191600101612507565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561252c57835183529284019291840191600101612554565b602081526000610f4e6020830184612469565b604051601f8201601f191681016001600160401b03811182821017156125ab576125ab6126a4565b604052919050565b600082198211156125c6576125c6612662565b500190565b6000828210156125dd576125dd612662565b500390565b60005b838110156125fd5781810151838201526020016125e5565b8381111561260c576000848401525b50505050565b600181811c9082168061262657607f821691505b60208210811415610fd557634e487b7160e01b600052602260045260246000fd5b600060001982141561265b5761265b612662565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8015158114610c9257600080fdfea2646970667358221220ad5f1b47d2adf92bad4533ffe2cbf7d6d45660df712721af9b5b08a8d8a1354664736f6c63430008070033