Address Details
contract

0x09aAB5cE8e2F5f7De524FC000971c57f9E5E2B55

SnafuVestingVault Last Balance Update: Block #18290126
Created by 0x805a71–fa331f at 0xa3ecfa–655dba

Balance

0 xDAI

(@ /xDAI)

Fetching tokens...

Contract name:
SnafuVestingVault




Optimization enabled
true
Compiler version
v0.6.12+commit.27d51765




Optimization runs
200
EVM Version
istanbul




Verified at
2021-05-15 17:34:38.232811Z

Constructor Arguments

00000000000000000000000027b9c2bd4baea18abdf49169054c1c1c12af9862

Arg [0] (address) : 0x27b9c2bd4baea18abdf49169054c1c1c12af9862

              

Contract source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.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);
}
//
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
//
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
//
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
//
/*
Original contract taken from https://github.com/tapmydata/tap-protocol/blob/main/contracts/VestingVault.sol
Removed the possibility to revoke token grants and added some views for better analytics.
*/
contract SnafuVestingVault is Ownable {
using SafeMath for uint256;
using SafeMath for uint16;
struct Grant {
uint256 startTime;
uint256 amount;
uint16 vestingDuration;
uint16 daysClaimed;
uint256 totalClaimed;
address recipient;
}
event GrantAdded(address indexed recipient, uint256 amount, uint16 vestingDurationInDays, uint16 vestingCliffInDays);
event GrantTokensClaimed(address indexed recipient, uint256 amountClaimed);
IERC20 public token;
mapping (address => Grant) private tokenGrants;
constructor(IERC20 _token) public {
require(address(_token) != address(0));
token = _token;
}
function addTokenGrant(
address _recipient,
uint256 _amount,
uint16 _vestingDurationInDays,
uint16 _vestingCliffInDays
)
external
onlyOwner
{
require(tokenGrants[_recipient].amount == 0, "Grant already exists, must revoke first.");
require(_vestingCliffInDays <= 10*365, "Cliff greater than 10 years");
require(_vestingDurationInDays <= 25*365, "Duration greater than 25 years");
uint256 amountVestedPerDay = _amount.div(_vestingDurationInDays);
require(amountVestedPerDay > 0, "amountVestedPerDay > 0");
// Transfer the grant tokens under the control of the vesting contract
require(token.transferFrom(owner(), address(this), _amount));
Grant memory grant = Grant({
startTime: currentTime() + _vestingCliffInDays * 1 days,
amount: _amount,
vestingDuration: _vestingDurationInDays,
daysClaimed: 0,
totalClaimed: 0,
recipient: _recipient
});
tokenGrants[_recipient] = grant;
emit GrantAdded(_recipient, _amount, _vestingDurationInDays, _vestingCliffInDays);
}
/// @notice Allows a grant recipient to claim their vested tokens. Errors if no tokens have vested
function claimVestedTokens() external {
uint16 daysVested;
uint256 amountVested;
(daysVested, amountVested) = calculateGrantClaim(msg.sender);
require(amountVested > 0, "Vested is 0");
Grant storage tokenGrant = tokenGrants[msg.sender];
tokenGrant.daysClaimed = uint16(tokenGrant.daysClaimed.add(daysVested));
tokenGrant.totalClaimed = uint256(tokenGrant.totalClaimed.add(amountVested));
require(token.transfer(tokenGrant.recipient, amountVested), "no tokens");
emit GrantTokensClaimed(tokenGrant.recipient, amountVested);
}
function getGrantStartTime(address _recipient) public view returns(uint256) {
Grant storage tokenGrant = tokenGrants[_recipient];
return tokenGrant.startTime;
}
function getGrantEndTime(address _recipient) public view returns(uint256) {
Grant storage tokenGrant = tokenGrants[_recipient];
return tokenGrant.startTime + (tokenGrant.vestingDuration * 1 days);
}
function getGrantAmount(address _recipient) public view returns(uint256) {
Grant storage tokenGrant = tokenGrants[_recipient];
return tokenGrant.amount;
}
function getGrantAmountLeft(address _recipient) public view returns(uint256) {
Grant storage tokenGrant = tokenGrants[_recipient];
uint256 remainingGrant = tokenGrant.amount.sub(tokenGrant.totalClaimed);
return remainingGrant;
}
function getVestingSummary(address[] memory vestedAccounts) public view returns(uint256, uint256){
uint256 remainingAmount;
uint256 totalAmount;
for(uint256 i = 0; i < vestedAccounts.length; i++){
totalAmount = totalAmount.add(getGrantAmount(vestedAccounts[i]));
remainingAmount = remainingAmount.add(getGrantAmountLeft(vestedAccounts[i]));
}
return (remainingAmount, totalAmount);
}
/// @notice Calculate the vested and unclaimed months and tokens available for `_grantId` to claim
/// Due to rounding errors once grant duration is reached, returns the entire left grant amount
/// Returns (0, 0) if cliff has not been reached
function calculateGrantClaim(address _recipient) public view returns (uint16, uint256) {
Grant storage tokenGrant = tokenGrants[_recipient];
require(tokenGrant.totalClaimed < tokenGrant.amount, "Grant fully claimed");
// For grants created with a future start date, that hasn't been reached, return 0, 0
if (currentTime() < tokenGrant.startTime) {
return (0, 0);
}
// Check cliff was reached
uint elapsedDays = currentTime().sub(tokenGrant.startTime - 1 days).div(1 days);
// If over vesting duration, all tokens vested
if (elapsedDays >= tokenGrant.vestingDuration) {
uint256 remainingGrant = tokenGrant.amount.sub(tokenGrant.totalClaimed);
return (tokenGrant.vestingDuration, remainingGrant);
} else {
uint16 daysVested = uint16(elapsedDays.sub(tokenGrant.daysClaimed));
uint256 amountVestedPerDay = tokenGrant.amount.div(uint256(tokenGrant.vestingDuration));
uint256 amountVested = uint256(daysVested.mul(amountVestedPerDay));
return (daysVested, amountVested);
}
}
function currentTime() private view returns(uint256) {
return block.timestamp;
}
}

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_token","internalType":"contract IERC20"}]},{"type":"event","name":"GrantAdded","inputs":[{"type":"address","name":"recipient","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint16","name":"vestingDurationInDays","internalType":"uint16","indexed":false},{"type":"uint16","name":"vestingCliffInDays","internalType":"uint16","indexed":false}],"anonymous":false},{"type":"event","name":"GrantTokensClaimed","inputs":[{"type":"address","name":"recipient","internalType":"address","indexed":true},{"type":"uint256","name":"amountClaimed","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addTokenGrant","inputs":[{"type":"address","name":"_recipient","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"uint16","name":"_vestingDurationInDays","internalType":"uint16"},{"type":"uint16","name":"_vestingCliffInDays","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"calculateGrantClaim","inputs":[{"type":"address","name":"_recipient","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimVestedTokens","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getGrantAmount","inputs":[{"type":"address","name":"_recipient","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getGrantAmountLeft","inputs":[{"type":"address","name":"_recipient","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getGrantEndTime","inputs":[{"type":"address","name":"_recipient","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getGrantStartTime","inputs":[{"type":"address","name":"_recipient","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getVestingSummary","inputs":[{"type":"address[]","name":"vestedAccounts","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"token","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
            

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100b45760003560e01c8063b0a4af0b11610071578063b0a4af0b146101a9578063e34e61db14610265578063e74f3fbb1461028b578063f2fde38b14610293578063fc0c546a146102b9578063fd75b8d4146102c1576100b4565b80630a0f5dbb146100b957806358013251146100f15780636d72c24e14610117578063715018a61461013d57806384a198dc146101475780638da5cb5b14610185575b600080fd5b6100df600480360360208110156100cf57600080fd5b50356001600160a01b0316610305565b60408051918252519081900360200190f35b6100df6004803603602081101561010757600080fd5b50356001600160a01b0316610320565b6100df6004803603602081101561012d57600080fd5b50356001600160a01b0316610356565b610145610374565b005b6101456004803603608081101561015d57600080fd5b506001600160a01b038135169060208101359061ffff60408201358116916060013516610428565b61018d610822565b604080516001600160a01b039092168252519081900360200190f35b61024c600480360360208110156101bf57600080fd5b8101906020810181356401000000008111156101da57600080fd5b8201836020820111156101ec57600080fd5b8035906020019184602083028401116401000000008311171561020e57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610831945050505050565b6040805192835260208301919091528051918290030190f35b6100df6004803603602081101561027b57600080fd5b50356001600160a01b03166108a7565b6101456108db565b610145600480360360208110156102a957600080fd5b50356001600160a01b0316610a9d565b61018d610ba7565b6102e7600480360360208110156102d757600080fd5b50356001600160a01b0316610bb6565b6040805161ffff909316835260208301919091528051918290030190f35b6001600160a01b031660009081526002602052604090205490565b6001600160a01b038116600090815260026020526040812060038101546001820154839161034e9190610d0c565b949350505050565b6001600160a01b031660009081526002602052604090206001015490565b61037c610d57565b6000546001600160a01b039081169116146103de576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b610430610d57565b6000546001600160a01b03908116911614610492576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038416600090815260026020526040902060010154156104ea5760405162461bcd60e51b8152600401808060200182810382526028815260200180610fbe6028913960400191505060405180910390fd5b610e428161ffff161115610545576040805162461bcd60e51b815260206004820152601b60248201527f436c6966662067726561746572207468616e2031302079656172730000000000604482015290519081900360640190fd5b6123a58261ffff1611156105a0576040805162461bcd60e51b815260206004820152601e60248201527f4475726174696f6e2067726561746572207468616e2032352079656172730000604482015290519081900360640190fd5b60006105b08461ffff8516610d5b565b905060008111610600576040805162461bcd60e51b81526020600482015260166024820152750616d6f756e74566573746564506572446179203e20360541b604482015290519081900360640190fd5b6001546001600160a01b03166323b872dd610619610822565b30876040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b15801561067157600080fd5b505af1158015610685573d6000803e3d6000fd5b505050506040513d602081101561069b57600080fd5b50516106a657600080fd5b6106ae610f50565b6040518060c001604052808461ffff16620151800262ffffff166106d0610d9d565b0181526020018681526020018561ffff168152602001600061ffff16815260200160008152602001876001600160a01b031681525090508060026000886001600160a01b03166001600160a01b03168152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548161ffff021916908361ffff16021790555060608201518160020160026101000a81548161ffff021916908361ffff1602179055506080820151816003015560a08201518160040160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550905050856001600160a01b03167f3a85fbf4409bf528727ff71970c3407dc22c206cb648d2ecff75e2f6bbba8ac7868686604051808481526020018361ffff1681526020018261ffff168152602001935050505060405180910390a2505050505050565b6000546001600160a01b031690565b60008060008060005b855181101561089b5761086961086287838151811061085557fe5b6020026020010151610356565b8390610da1565b915061089161088a87838151811061087d57fe5b6020026020010151610320565b8490610da1565b925060010161083a565b5090925090505b915091565b6001600160a01b0316600090815260026020819052604090912090810154905461ffff909116620151800262ffffff160190565b6000806108e733610bb6565b90925090508061092c576040805162461bcd60e51b815260206004820152600b60248201526a056657374656420697320360ac1b604482015290519081900360640190fd5b3360009081526002602081905260409091209081015461095a9062010000900461ffff908116908516610da1565b60028201805461ffff92909216620100000263ffff000019909216919091179055600381015461098a9083610da1565b60038201556001546004808301546040805163a9059cbb60e01b81526001600160a01b0392831693810193909352602483018690525192169163a9059cbb916044808201926020929091908290030181600087803b1580156109eb57600080fd5b505af11580156109ff573d6000803e3d6000fd5b505050506040513d6020811015610a1557600080fd5b5051610a54576040805162461bcd60e51b81526020600482015260096024820152686e6f20746f6b656e7360b81b604482015290519081900360640190fd5b60048101546040805184815290516001600160a01b03909216917fc6cbb4aa8681b18644bf64921eea8f2b9f44cbd58d64fc07a110bfccc20382969181900360200190a2505050565b610aa5610d57565b6000546001600160a01b03908116911614610b07576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116610b4c5760405162461bcd60e51b8152600401808060200182810382526026815260200180610f986026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b6001600160a01b03811660009081526002602052604081206001810154600382015483929111610c23576040805162461bcd60e51b815260206004820152601360248201527211dc985b9d08199d5b1b1e4818db185a5b5959606a1b604482015290519081900360640190fd5b8054610c2d610d9d565b1015610c405760008092509250506108a2565b6000610c6a62015180610c6462015180856000015403610c5e610d9d565b90610d0c565b90610d5b565b600283015490915061ffff168110610cb0576000610c9983600301548460010154610d0c90919063ffffffff16565b60029093015461ffff1694509192506108a2915050565b6002820154600090610ccd90839062010000900461ffff16610d0c565b60028401546001850154919250600091610cea9161ffff16610d5b565b90506000610cfc61ffff841683610dfb565b9296509194506108a29350505050565b6000610d4e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610e54565b90505b92915050565b3390565b6000610d4e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250610eeb565b4290565b600082820183811015610d4e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082610e0a57506000610d51565b82820282848281610e1757fe5b0414610d4e5760405162461bcd60e51b8152600401808060200182810382526021815260200180610fe66021913960400191505060405180910390fd5b60008184841115610ee35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610ea8578181015183820152602001610e90565b50505050905090810190601f168015610ed55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008183610f3a5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610ea8578181015183820152602001610e90565b506000838581610f4657fe5b0495945050505050565b6040518060c001604052806000815260200160008152602001600061ffff168152602001600061ffff1681526020016000815260200160006001600160a01b03168152509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734772616e7420616c7265616479206578697374732c206d757374207265766f6b652066697273742e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220949e6132d5aae9bd3760cf0867647853c4a1b0aa786c8b5e0786d17b6874f75664736f6c634300060c0033