Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been partially verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- EthealNormalSale
- Optimization enabled
- true
- Compiler version
- v0.4.19+commit.c4cbbb05
- Optimization runs
- 200
- Verified at
- 2026-02-04T10:15:01.893708Z
Constructor Arguments
000000000000000000000000b565726e2e44e4ae9e3ce750fc4ba8fa65e701e0000000000000000000000000000000000000000000000000000000005b108c80000000000000000000000000000000000000000000000000000000005b381980000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000028a857425466f800000000000000000000000000000000000000000000000000000000000000028de8000000000000000000000000000000000000000000000054b40b1f852bda00000000000000000000000000000fc5c6c8015962e7035f3bdc5fe7ec94bedc77833
Arg [0] (address) : 0xb565726e2e44e4ae9e3ce750fc4ba8fa65e701e0
Arg [1] (uint256) : 1527811200
Arg [2] (uint256) : 1530403200
Arg [3] (uint256) : 100000000000000000
Arg [4] (uint256) : 700
Arg [5] (uint256) : 12000000000000000000000
Arg [6] (uint256) : 2678400
Arg [7] (uint256) : 25000000000000000000000
Arg [8] (address) : 0xfc5c6c8015962e7035f3bdc5fe7ec94bedc77833
EthealNormalSale.sol
pragma solidity ^0.4.17;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner public {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
/**
* @title ERC20
* @dev ERC20 interface
*/
contract ERC20 {
function balanceOf(address who) public constant returns (uint256);
function transfer(address to, uint256 value) public returns (bool);
function allowance(address owner, address spender) public constant returns (uint256);
function transferFrom(address from, address to, uint256 value) public returns (bool);
function approve(address spender, uint256 value) public returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract Controlled {
/// @notice The address of the controller is the only address that can call
/// a function with this modifier
modifier onlyController { require(msg.sender == controller); _; }
address public controller;
function Controlled() public { controller = msg.sender;}
/// @notice Changes the controller of the contract
/// @param _newController The new controller of the contract
function changeController(address _newController) public onlyController {
controller = _newController;
}
}
/**
* @title MiniMe interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20MiniMe is ERC20, Controlled {
function approveAndCall(address _spender, uint256 _amount, bytes _extraData) public returns (bool);
function totalSupply() public constant returns (uint);
function balanceOfAt(address _owner, uint _blockNumber) public constant returns (uint);
function totalSupplyAt(uint _blockNumber) public constant returns(uint);
function createCloneToken(string _cloneTokenName, uint8 _cloneDecimalUnits, string _cloneTokenSymbol, uint _snapshotBlock, bool _transfersEnabled) public returns(address);
function generateTokens(address _owner, uint _amount) public returns (bool);
function destroyTokens(address _owner, uint _amount) public returns (bool);
function enableTransfers(bool _transfersEnabled) public;
function isContract(address _addr) constant internal returns(bool);
function claimTokens(address _token) public;
event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
event NewCloneToken(address indexed _cloneToken, uint _snapshotBlock);
}
/**
* @title Crowdsale
* @dev Crowdsale is a base contract for managing a token crowdsale.
* Crowdsales have a start and end timestamps, where investors can make
* token purchases and the crowdsale will assign them tokens based
* on a token per ETH rate. Funds collected are forwarded to a wallet
* as they arrive.
*/
contract Crowdsale {
using SafeMath for uint256;
// The token being sold
ERC20MiniMe public token;
// start and end timestamps where investments are allowed (both inclusive)
uint256 public startTime;
uint256 public endTime;
// address where funds are collected
address public wallet;
// how many token units a buyer gets per wei
uint256 public rate;
// amount of raised money in wei
uint256 public weiRaised;
/**
* event for token purchase logging
* @param purchaser who paid for the tokens
* @param beneficiary who got the tokens
* @param value weis paid for purchase
* @param amount amount of tokens purchased
*/
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
function Crowdsale(uint256 _startTime, uint256 _endTime, uint256 _rate, address _wallet) {
require(_startTime >= now);
require(_endTime >= _startTime);
require(_rate > 0);
require(_wallet != 0x0);
startTime = _startTime;
endTime = _endTime;
rate = _rate;
wallet = _wallet;
}
// fallback function can be used to buy tokens
function () payable {
buyTokens(msg.sender);
}
// low level token purchase function
function buyTokens(address beneficiary) public payable {
buyTokens(beneficiary, msg.value);
}
// implementation of low level token purchase function
function buyTokens(address beneficiary, uint256 weiAmount) internal {
require(beneficiary != 0x0);
require(validPurchase(weiAmount));
transferToken(beneficiary, weiAmount);
// update state
weiRaised = weiRaised.add(weiAmount);
forwardFunds(weiAmount);
}
// low level transfer token
// override to create custom token transfer mechanism, eg. pull pattern
function transferToken(address beneficiary, uint256 weiAmount) internal {
// calculate token amount to be created
uint256 tokens = weiAmount.mul(rate);
token.generateTokens(beneficiary, tokens);
TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);
}
// send ether to the fund collection wallet
// override to create custom fund forwarding mechanisms
function forwardFunds(uint256 weiAmount) internal {
wallet.transfer(weiAmount);
}
// @return true if the transaction can buy tokens
function validPurchase(uint256 weiAmount) internal constant returns (bool) {
bool withinPeriod = now >= startTime && now <= endTime;
bool nonZeroPurchase = weiAmount != 0;
return withinPeriod && nonZeroPurchase;
}
// @return true if crowdsale event has ended
function hasEnded() public constant returns (bool) {
return now > endTime;
}
// @return true if crowdsale has started
function hasStarted() public constant returns (bool) {
return now >= startTime;
}
}
/**
* @title CappedCrowdsale
* @dev Extension of Crowdsale with a max amount of funds raised
*/
contract CappedCrowdsale is Crowdsale {
using SafeMath for uint256;
uint256 public cap;
function CappedCrowdsale(uint256 _cap) {
require(_cap > 0);
cap = _cap;
}
// overriding Crowdsale#validPurchase to add extra cap logic
// @return true if investors can buy at the moment
function validPurchase(uint256 weiAmount) internal constant returns (bool) {
return super.validPurchase(weiAmount) && !capReached();
}
// overriding Crowdsale#hasEnded to add cap logic
// @return true if crowdsale event has ended
function hasEnded() public constant returns (bool) {
return super.hasEnded() || capReached();
}
// @return true if cap has been reached
function capReached() internal constant returns (bool) {
return weiRaised >= cap;
}
// overriding Crowdsale#buyTokens to add partial refund logic
function buyTokens(address beneficiary) public payable {
uint256 weiToCap = cap.sub(weiRaised);
uint256 weiAmount = weiToCap < msg.value ? weiToCap : msg.value;
buyTokens(beneficiary, weiAmount);
uint256 refund = msg.value.sub(weiAmount);
if (refund > 0) {
msg.sender.transfer(refund);
}
}
}
/// @dev The token controller contract must implement these functions
contract TokenController {
ERC20MiniMe public ethealToken;
address public SALE; // address where sale tokens are located
/// @notice needed for hodler handling
function addHodlerStake(address _beneficiary, uint256 _stake) public;
function setHodlerStake(address _beneficiary, uint256 _stake) public;
function setHodlerTime(uint256 _time) public;
/// @notice Called when `_owner` sends ether to the MiniMe Token contract
/// @param _owner The address that sent the ether to create tokens
/// @return True if the ether is accepted, false if it throws
function proxyPayment(address _owner) public payable returns(bool);
/// @notice Notifies the controller about a token transfer allowing the
/// controller to react if desired
/// @param _from The origin of the transfer
/// @param _to The destination of the transfer
/// @param _amount The amount of the transfer
/// @return False if the controller does not authorize the transfer
function onTransfer(address _from, address _to, uint _amount) public returns(bool);
/// @notice Notifies the controller about an approval allowing the
/// controller to react if desired
/// @param _owner The address that calls `approve()`
/// @param _spender The spender in the `approve()` call
/// @param _amount The amount in the `approve()` call
/// @return False if the controller does not authorize the approval
function onApprove(address _owner, address _spender, uint _amount) public returns(bool);
}
/**
* @title FinalizableCrowdsale
* @dev Extension of Crowdsale where an owner can do extra work
* after finishing.
*/
contract FinalizableCrowdsale is Crowdsale, Ownable {
using SafeMath for uint256;
bool public isFinalized = false;
event Finalized();
/**
* @dev Must be called after crowdsale ends, to do some extra finalization
* work. Calls the contract's finalization function.
*/
function finalize() onlyOwner public {
require(!isFinalized);
require(hasEnded());
finalization();
Finalized();
isFinalized = true;
}
/**
* @dev Can be overridden to add finalization logic. The overriding function
* should call super.finalization() to ensure the chain of finalization is
* executed entirely.
*/
function finalization() internal {
}
}
/**
* @title Pausable
* @dev Base contract which allows children to implement an emergency stop mechanism.
*/
contract Pausable is Ownable {
event Pause();
event Unpause();
bool public paused = false;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!paused);
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(paused);
_;
}
/**
* @dev called by the owner to pause, triggers stopped state
*/
function pause() onlyOwner whenNotPaused public {
paused = true;
Pause();
}
/**
* @dev called by the owner to unpause, returns to normal state
*/
function unpause() onlyOwner whenPaused public {
paused = false;
Unpause();
}
}
/**
* @title Eliptic curve signature operations
*
* @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
*/
library ECRecovery {
/**
* @dev Recover signer address from a message by using his signature
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
* @param sig bytes signature, the signature is generated using web3.eth.sign()
*/
function recover(bytes32 hash, bytes sig) public pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
//Check the signature length
if (sig.length != 65) {
return (address(0));
}
// Divide the signature in r, s and v variables
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
// Version of signature should be 27 or 28, but 0 and 1 are also possible versions
if (v < 27) {
v += 27;
}
// If the version is correct return the signer address
if (v != 27 && v != 28) {
return (address(0));
} else {
return ecrecover(hash, v, r, s);
}
}
}
/**
* @title EthealWhitelist
* @author thesved
* @notice EthealWhitelist contract which handles KYC
*/
contract EthealWhitelist is Ownable {
using ECRecovery for bytes32;
// signer address for offchain whitelist signing
address public signer;
// storing whitelisted addresses
mapping(address => bool) public isWhitelisted;
event WhitelistSet(address indexed _address, bool _state);
////////////////
// Constructor
////////////////
function EthealWhitelist(address _signer) {
require(_signer != address(0));
signer = _signer;
}
/// @notice set signing address after deployment
function setSigner(address _signer) public onlyOwner {
require(_signer != address(0));
signer = _signer;
}
////////////////
// Whitelisting: only owner
////////////////
/// @notice Set whitelist state for an address.
function setWhitelist(address _addr, bool _state) public onlyOwner {
require(_addr != address(0));
isWhitelisted[_addr] = _state;
WhitelistSet(_addr, _state);
}
/// @notice Set whitelist state for multiple addresses
function setManyWhitelist(address[] _addr, bool _state) public onlyOwner {
for (uint256 i = 0; i < _addr.length; i++) {
setWhitelist(_addr[i], _state);
}
}
/// @notice offchain whitelist check
function isOffchainWhitelisted(address _addr, bytes _sig) public view returns (bool) {
bytes32 hash = keccak256("\x19Ethereum Signed Message:\n20",_addr);
return hash.recover(_sig) == signer;
}
}
/**
* @title EthealNormalSale
* @author thesved
* @notice Etheal Token Sale contract, with softcap and hardcap (cap)
* @dev This contract has to be finalized before token claims are enabled
*/
contract EthealNormalSale is Pausable, FinalizableCrowdsale, CappedCrowdsale {
// the token is here
TokenController public ethealController;
// after reaching {weiRaised} >= {softCap}, there is {softCapTime} seconds until the sale closes
// {softCapClose} contains the closing time
uint256 public rate = 700;
uint256 public softCap = 6800 ether;
uint256 public softCapTime = 120 hours;
uint256 public softCapClose;
uint256 public cap = 14300 ether;
// how many token is sold and not claimed, used for refunding to token controller
uint256 public tokenBalance;
// total token sold
uint256 public tokenSold;
// minimum contribution, 0.1ETH
uint256 public minContribution = 0.1 ether;
// whitelist: above threshold the contract has to approve each transaction
EthealWhitelist public whitelist;
uint256 public whitelistThreshold = 1 ether;
// deposit address from which it can get funds before sale
address public deposit;
// stakes contains token bought and contirbutions contains the value in wei
mapping (address => uint256) public stakes;
mapping (address => uint256) public contributions;
// promo token bonus
address public promoTokenController;
mapping (address => uint256) public bonusExtra;
// addresses of contributors to handle finalization after token sale end (refunds or token claims)
address[] public contributorsKeys;
// events for token purchase during sale and claiming tokens after sale
event LogTokenClaimed(address indexed _claimer, address indexed _beneficiary, uint256 _amount);
event LogTokenPurchase(address indexed _purchaser, address indexed _beneficiary, uint256 _value, uint256 _amount, uint256 _participants, uint256 _weiRaised);
event LogTokenSoftCapReached(uint256 _closeTime);
event LogTokenHardCapReached();
////////////////
// Constructor and inherited function overrides
////////////////
/// @notice Constructor to create PreSale contract
/// @param _ethealController Address of ethealController
/// @param _startTime The start time of token sale in seconds.
/// @param _endTime The end time of token sale in seconds.
/// @param _minContribution The minimum contribution per transaction in wei (0.1 ETH)
/// @param _rate Number of HEAL tokens per 1 ETH
/// @param _softCap Softcap in wei, reaching it ends the sale in _softCapTime seconds
/// @param _softCapTime Seconds until the sale remains open after reaching _softCap
/// @param _cap Maximum cap in wei, we can't raise more funds
/// @param _wallet Address of multisig wallet, which will get all the funds after successful sale
function EthealNormalSale(
address _ethealController,
uint256 _startTime,
uint256 _endTime,
uint256 _minContribution,
uint256 _rate,
uint256 _softCap,
uint256 _softCapTime,
uint256 _cap,
address _wallet
)
CappedCrowdsale(_cap)
FinalizableCrowdsale()
Crowdsale(_startTime, _endTime, _rate, _wallet)
{
// ethealController must be valid
require(_ethealController != address(0));
ethealController = TokenController(_ethealController);
// caps have to be consistent with each other
require(_softCap <= _cap);
softCap = _softCap;
softCapTime = _softCapTime;
// this is needed since super constructor wont overwite overriden variables
cap = _cap;
rate = _rate;
minContribution = _minContribution;
}
////////////////
// Administer contract details
////////////////
/// @notice Sets min contribution
function setMinContribution(uint256 _minContribution) public onlyOwner {
minContribution = _minContribution;
}
/// @notice Sets soft cap and max cap
function setCaps(uint256 _softCap, uint256 _softCapTime, uint256 _cap) public onlyOwner {
require(_softCap <= _cap);
softCap = _softCap;
softCapTime = _softCapTime;
cap = _cap;
}
/// @notice Sets crowdsale start and end time
function setTimes(uint256 _startTime, uint256 _endTime) public onlyOwner {
require(_startTime <= _endTime);
require(!hasEnded());
startTime = _startTime;
endTime = _endTime;
}
/// @notice Set rate
function setRate(uint256 _rate) public onlyOwner {
require(_rate > 0);
rate = _rate;
}
/// @notice Set address of promo token
function setPromoTokenController(address _addr) public onlyOwner {
require(_addr != address(0));
promoTokenController = _addr;
}
/// @notice Set whitelist contract address and minimum threshold
function setWhitelist(address _whitelist, uint256 _threshold) public onlyOwner {
// if whitelist contract address is provided we set it
if (_whitelist != address(0)) {
whitelist = EthealWhitelist(_whitelist);
}
whitelistThreshold = _threshold;
}
/// @notice Set deposit contract address from which it can receive money before sale
function setDeposit(address _deposit) public onlyOwner {
deposit = _deposit;
}
/// @notice move excess tokens, eg to hodler/sale contract
function moveTokens(address _to, uint256 _amount) public onlyOwner {
require(_to != address(0));
require(_amount <= getHealBalance().sub(tokenBalance));
require(ethealController.ethealToken().transfer(_to, _amount));
}
////////////////
// Purchase functions
////////////////
/// @dev Overriding Crowdsale#buyTokens to add partial refund
/// @param _beneficiary Beneficiary of the token purchase
function buyTokens(address _beneficiary) public payable whenNotPaused {
handlePayment(_beneficiary, msg.value, now, "");
}
/// @dev buying tokens for someone with offchain whitelist signature
function buyTokensSigned(address _beneficiary, bytes _whitelistSign) public payable whenNotPaused {
handlePayment(_beneficiary, msg.value, now, _whitelistSign);
}
/// @dev Internal function for handling transactions with ether.
function handlePayment(address _beneficiary, uint256 _amount, uint256 _time, bytes memory _whitelistSign) internal {
require(_beneficiary != address(0));
uint256 weiAmount = handleContribution(_beneficiary, _amount, _time, _whitelistSign);
forwardFunds(weiAmount);
// handle refund excess tokens
uint256 refund = _amount.sub(weiAmount);
if (refund > 0) {
_beneficiary.transfer(refund);
}
}
/// @dev Handling the amount of contribution and cap logic. Internal function.
/// @return Wei successfully contributed.
function handleContribution(address _beneficiary, uint256 _amount, uint256 _time, bytes memory _whitelistSign) internal returns (uint256) {
require(_beneficiary != address(0));
uint256 weiToCap = howMuchCanXContributeNow(_beneficiary);
uint256 weiAmount = uint256Min(weiToCap, _amount);
// account the new contribution
transferToken(_beneficiary, weiAmount, _time, _whitelistSign);
// close sale in softCapTime seconds after reaching softCap
if (weiRaised >= softCap && softCapClose == 0) {
softCapClose = now.add(softCapTime);
LogTokenSoftCapReached(uint256Min(softCapClose, endTime));
}
// event for hard cap reached
if (weiRaised >= cap) {
LogTokenHardCapReached();
}
return weiAmount;
}
/// @dev Handling token distribution and accounting. Overriding Crowdsale#transferToken.
/// @param _beneficiary Address of the recepient of the tokens
/// @param _weiAmount Contribution in wei
/// @param _time When the contribution was made
function transferToken(address _beneficiary, uint256 _weiAmount, uint256 _time, bytes memory _whitelistSign) internal {
require(_beneficiary != address(0));
require(validPurchase(_weiAmount));
// increase wei Raised
weiRaised = weiRaised.add(_weiAmount);
// require whitelist above threshold
contributions[_beneficiary] = contributions[_beneficiary].add(_weiAmount);
require(contributions[_beneficiary] <= whitelistThreshold
|| whitelist.isWhitelisted(_beneficiary)
|| whitelist.isOffchainWhitelisted(_beneficiary, _whitelistSign)
);
// calculate tokens, so we can refund excess tokens to EthealController after token sale
uint256 _bonus = getBonus(_beneficiary, _weiAmount, _time);
uint256 tokens = _weiAmount.mul(rate).mul(_bonus).div(100);
tokenBalance = tokenBalance.add(tokens);
if (stakes[_beneficiary] == 0) {
contributorsKeys.push(_beneficiary);
}
stakes[_beneficiary] = stakes[_beneficiary].add(tokens);
LogTokenPurchase(msg.sender, _beneficiary, _weiAmount, tokens, contributorsKeys.length, weiRaised);
}
/// @dev Get eth deposit from Deposit contract
function depositEth(address _beneficiary, uint256 _time, bytes _whitelistSign) public payable whenNotPaused {
require(msg.sender == deposit);
handlePayment(_beneficiary, msg.value, _time, _whitelistSign);
}
/// @dev Deposit from other currencies
function depositOffchain(address _beneficiary, uint256 _amount, uint256 _time, bytes _whitelistSign) public onlyOwner whenNotPaused {
handleContribution(_beneficiary, _amount, _time, _whitelistSign);
}
/// @dev Overriding Crowdsale#validPurchase to add min contribution logic
/// @param _weiAmount Contribution amount in wei
/// @return true if contribution is okay
function validPurchase(uint256 _weiAmount) internal constant returns (bool) {
bool nonEnded = !hasEnded();
bool nonZero = _weiAmount != 0;
bool enoughContribution = _weiAmount >= minContribution;
return nonEnded && nonZero && enoughContribution;
}
/// @dev Overriding Crowdsale#hasEnded to add soft cap logic
/// @return true if crowdsale event has ended or a softCapClose time is set and passed
function hasEnded() public constant returns (bool) {
return super.hasEnded() || softCapClose > 0 && now > softCapClose;
}
/// @dev Extending RefundableCrowdsale#finalization sending back excess tokens to ethealController
function finalization() internal {
uint256 _balance = getHealBalance();
// saving token balance for future reference
tokenSold = tokenBalance;
// send back the excess token to ethealController
if (_balance > tokenBalance) {
ethealController.ethealToken().transfer(ethealController.SALE(), _balance.sub(tokenBalance));
}
// hodler stake counting starts 14 days after closing normal sale
ethealController.setHodlerTime(now + 14 days);
super.finalization();
}
////////////////
// AFTER token sale
////////////////
/// @notice Modifier for after sale finalization
modifier afterSale() {
require(isFinalized);
_;
}
/// @notice Claim token for msg.sender after token sale based on stake.
function claimToken() public afterSale {
claimTokenFor(msg.sender);
}
/// @notice Claim token after token sale based on stake.
/// @dev Anyone can call this function and distribute tokens after successful token sale
/// @param _beneficiary Address of the beneficiary who gets the token
function claimTokenFor(address _beneficiary) public afterSale whenNotPaused {
uint256 tokens = stakes[_beneficiary];
require(tokens > 0);
// set the stake 0 for beneficiary
stakes[_beneficiary] = 0;
// decrease tokenBalance, to make it possible to withdraw excess HEAL funds
tokenBalance = tokenBalance.sub(tokens);
// distribute hodlr stake
ethealController.addHodlerStake(_beneficiary, tokens);
// distribute token
require(ethealController.ethealToken().transfer(_beneficiary, tokens));
LogTokenClaimed(msg.sender, _beneficiary, tokens);
}
/// @notice claimToken() for multiple addresses
/// @dev Anyone can call this function and distribute tokens after successful token sale
/// @param _beneficiaries Array of addresses for which we want to claim tokens
function claimManyTokenFor(address[] _beneficiaries) external afterSale {
for (uint256 i = 0; i < _beneficiaries.length; i++) {
claimTokenFor(_beneficiaries[i]);
}
}
////////////////
// Bonus functions
////////////////
/// @notice Sets extra 5% bonus for those addresses who send back a promo token
/// @notice It contains an easter egg.
/// @param _addr this address gets the bonus
/// @param _value how many tokens are transferred
function setPromoBonus(address _addr, uint256 _value) public {
require(msg.sender == promoTokenController || msg.sender == owner);
require(_value>0);
uint256 _bonus = keccak256(_value) == 0xbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d2 ? 6 : 5;
if (bonusExtra[ _addr ] < _bonus) {
bonusExtra[ _addr ] = _bonus;
}
}
/// @notice Manual set extra bonus for addresses
function setBonusExtra(address _addr, uint256 _bonus) public onlyOwner {
require(_addr != address(0));
bonusExtra[_addr] = _bonus;
}
/// @notice Mass set extra bonus for addresses
function setManyBonusExtra(address[] _addr, uint256 _bonus) external onlyOwner {
for (uint256 i = 0; i < _addr.length; i++) {
setBonusExtra(_addr[i],_bonus);
}
}
/// @notice Returns bonus for now
function getBonusNow(address _addr, uint256 _size) public view returns (uint256) {
return getBonus(_addr, _size, now);
}
/// @notice Returns the bonus in percentage, eg 130 means 30% bonus
function getBonus(address _addr, uint256 _size, uint256 _time) public view returns (uint256 _bonus) {
// detailed bonus structure: https://etheal.com/#heal-token
_bonus = 100;
// time based bonuses
uint256 _day = getSaleDay(_time);
uint256 _hour = getSaleHour(_time);
if (_day <= 1) {
if (_hour <= 1) _bonus = 130;
else if (_hour <= 5) _bonus = 125;
else if (_hour <= 8) _bonus = 120;
else _bonus = 118;
}
else if (_day <= 2) { _bonus = 116; }
else if (_day <= 3) { _bonus = 115; }
else if (_day <= 5) { _bonus = 114; }
else if (_day <= 7) { _bonus = 113; }
else if (_day <= 9) { _bonus = 112; }
else if (_day <= 11) { _bonus = 111; }
else if (_day <= 13) { _bonus = 110; }
else if (_day <= 15) { _bonus = 108; }
else if (_day <= 17) { _bonus = 107; }
else if (_day <= 19) { _bonus = 106; }
else if (_day <= 21) { _bonus = 105; }
else if (_day <= 23) { _bonus = 104; }
else if (_day <= 25) { _bonus = 103; }
else if (_day <= 27) { _bonus = 102; }
// size based bonuses
if (_size >= 100 ether) { _bonus = _bonus + 4; }
else if (_size >= 10 ether) { _bonus = _bonus + 2; }
// manual bonus
_bonus += bonusExtra[ _addr ];
return _bonus;
}
////////////////
// Constant, helper functions
////////////////
/// @notice How many wei can the msg.sender contribute now.
function howMuchCanIContributeNow() view public returns (uint256) {
return howMuchCanXContributeNow(msg.sender);
}
/// @notice How many wei can an ethereum address contribute now.
/// @param _beneficiary Ethereum address
/// @return Number of wei the _beneficiary can contribute now.
function howMuchCanXContributeNow(address _beneficiary) view public returns (uint256) {
require(_beneficiary != address(0));
if (hasEnded() || paused)
return 0;
// wei to hard cap
uint256 weiToCap = cap.sub(weiRaised);
return weiToCap;
}
/// @notice For a give date how many 24 hour blocks have ellapsed since token sale start
/// Before sale return 0, first day 1, second day 2, ...
/// @param _time Date in seconds for which we want to know which sale day it is
/// @return Number of 24 hour blocks ellapsing since token sale start starting from 1
function getSaleDay(uint256 _time) view public returns (uint256) {
uint256 _day = 0;
if (_time > startTime) {
_day = _time.sub(startTime).div(60*60*24).add(1);
}
return _day;
}
/// @notice How many 24 hour blocks have ellapsed since token sale start
/// @return Number of 24 hour blocks ellapsing since token sale start starting from 1
function getSaleDayNow() view public returns (uint256) {
return getSaleDay(now);
}
/// @notice Returns sale hour: 0 before sale, 1 for the first hour, ...
/// @param _time Date in seconds for which we want to know which sale hour it is
/// @return Number of 1 hour blocks ellapsing since token sale start starting from 1
function getSaleHour(uint256 _time) view public returns (uint256) {
uint256 _hour = 0;
if (_time > startTime) {
_hour = _time.sub(startTime).div(60*60).add(1);
}
return _hour;
}
/// @notice How many 1 hour blocks have ellapsed since token sale start
/// @return Number of 1 hour blocks ellapsing since token sale start starting from 1
function getSaleHourNow() view public returns (uint256) {
return getSaleHour(now);
}
/// @notice Minimum between two uint256 numbers
function uint256Min(uint256 a, uint256 b) pure internal returns (uint256) {
return a > b ? b : a;
}
////////////////
// Test and contribution web app, NO audit is needed
////////////////
/// @notice How many contributors we have.
/// @return Number of different contributor ethereum addresses
function getContributorsCount() view public returns (uint256) {
return contributorsKeys.length;
}
/// @notice Get contributor addresses to manage refunds or token claims.
/// @dev If the sale is not yet successful, then it searches in the RefundVault.
/// If the sale is successful, it searches in contributors.
/// @param _pending If true, then returns addresses which didn't get their tokens distributed to them
/// @param _claimed If true, then returns already distributed addresses
/// @return Array of addresses of contributors
function getContributors(bool _pending, bool _claimed) view public returns (address[] contributors) {
uint256 i = 0;
uint256 results = 0;
address[] memory _contributors = new address[](contributorsKeys.length);
// search in contributors
for (i = 0; i < contributorsKeys.length; i++) {
if (_pending && stakes[contributorsKeys[i]] > 0 || _claimed && stakes[contributorsKeys[i]] == 0) {
_contributors[results] = contributorsKeys[i];
results++;
}
}
contributors = new address[](results);
for (i = 0; i < results; i++) {
contributors[i] = _contributors[i];
}
return contributors;
}
/// @notice How many HEAL tokens do this contract have
function getHealBalance() view public returns (uint256) {
return ethealController.ethealToken().balanceOf(address(this));
}
/// @notice Get current date for web3
function getNow() view public returns (uint256) {
return now;
}
}
Compiler Settings
{"remappings":[],"optimizer":{"runs":200,"enabled":true},"libraries":{},"compilationTarget":{"EthealNormalSale.sol":"EthealNormalSale"}}
Contract ABI
[{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getBonusNow","inputs":[{"type":"address","name":"_addr"},{"type":"uint256","name":"_size"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setManyBonusExtra","inputs":[{"type":"address[]","name":"_addr"},{"type":"uint256","name":"_bonus"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"moveTokens","inputs":[{"type":"address","name":"_to"},{"type":"uint256","name":"_amount"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setWhitelist","inputs":[{"type":"address","name":"_whitelist"},{"type":"uint256","name":"_threshold"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"softCapTime","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"stakes","inputs":[{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setBonusExtra","inputs":[{"type":"address","name":"_addr"},{"type":"uint256","name":"_bonus"}],"constant":false},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"depositEth","inputs":[{"type":"address","name":"_beneficiary"},{"type":"uint256","name":"_time"},{"type":"bytes","name":"_whitelistSign"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setTimes","inputs":[{"type":"uint256","name":"_startTime"},{"type":"uint256","name":"_endTime"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getHealBalance","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getSaleHour","inputs":[{"type":"uint256","name":"_time"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"rate","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"endTime","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"contributors"}],"name":"getContributors","inputs":[{"type":"bool","name":"_pending"},{"type":"bool","name":"_claimed"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setRate","inputs":[{"type":"uint256","name":"_rate"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"cap","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setDeposit","inputs":[{"type":"address","name":"_deposit"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"unpause","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"weiRaised","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"contributions","inputs":[{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"claimToken","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"hasStarted","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"contributorsKeys","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMinContribution","inputs":[{"type":"uint256","name":"_minContribution"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"finalize","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"tokenSold","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"wallet","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"claimManyTokenFor","inputs":[{"type":"address[]","name":"_beneficiaries"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"howMuchCanIContributeNow","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"paused","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"depositOffchain","inputs":[{"type":"address","name":"_beneficiary"},{"type":"uint256","name":"_amount"},{"type":"uint256","name":"_time"},{"type":"bytes","name":"_whitelistSign"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"startTime","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"_bonus"}],"name":"getBonus","inputs":[{"type":"address","name":"_addr"},{"type":"uint256","name":"_size"},{"type":"uint256","name":"_time"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"ethealController","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"pause","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isFinalized","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"softCap","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"whitelist","inputs":[],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"buyTokensSigned","inputs":[{"type":"address","name":"_beneficiary"},{"type":"bytes","name":"_whitelistSign"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"tokenBalance","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getSaleDayNow","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"minContribution","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"bonusExtra","inputs":[{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"softCapClose","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getSaleHourNow","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"whitelistThreshold","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getNow","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"howMuchCanXContributeNow","inputs":[{"type":"address","name":"_beneficiary"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setPromoTokenController","inputs":[{"type":"address","name":"_addr"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"promoTokenController","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getSaleDay","inputs":[{"type":"uint256","name":"_time"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"claimTokenFor","inputs":[{"type":"address","name":"_beneficiary"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setCaps","inputs":[{"type":"uint256","name":"_softCap"},{"type":"uint256","name":"_softCapTime"},{"type":"uint256","name":"_cap"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"deposit","inputs":[],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[],"name":"buyTokens","inputs":[{"type":"address","name":"_beneficiary"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"hasEnded","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"token","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setPromoBonus","inputs":[{"type":"address","name":"_addr"},{"type":"uint256","name":"_value"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getContributorsCount","inputs":[],"constant":true},{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[{"type":"address","name":"_ethealController"},{"type":"uint256","name":"_startTime"},{"type":"uint256","name":"_endTime"},{"type":"uint256","name":"_minContribution"},{"type":"uint256","name":"_rate"},{"type":"uint256","name":"_softCap"},{"type":"uint256","name":"_softCapTime"},{"type":"uint256","name":"_cap"},{"type":"address","name":"_wallet"}]},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"event","name":"LogTokenClaimed","inputs":[{"type":"address","name":"_claimer","indexed":true},{"type":"address","name":"_beneficiary","indexed":true},{"type":"uint256","name":"_amount","indexed":false}],"anonymous":false},{"type":"event","name":"LogTokenPurchase","inputs":[{"type":"address","name":"_purchaser","indexed":true},{"type":"address","name":"_beneficiary","indexed":true},{"type":"uint256","name":"_value","indexed":false},{"type":"uint256","name":"_amount","indexed":false},{"type":"uint256","name":"_participants","indexed":false},{"type":"uint256","name":"_weiRaised","indexed":false}],"anonymous":false},{"type":"event","name":"LogTokenSoftCapReached","inputs":[{"type":"uint256","name":"_closeTime","indexed":false}],"anonymous":false},{"type":"event","name":"LogTokenHardCapReached","inputs":[],"anonymous":false},{"type":"event","name":"Finalized","inputs":[],"anonymous":false},{"type":"event","name":"Pause","inputs":[],"anonymous":false},{"type":"event","name":"Unpause","inputs":[],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","indexed":true},{"type":"address","name":"newOwner","indexed":true}],"anonymous":false},{"type":"event","name":"TokenPurchase","inputs":[{"type":"address","name":"purchaser","indexed":true},{"type":"address","name":"beneficiary","indexed":true},{"type":"uint256","name":"value","indexed":false},{"type":"uint256","name":"amount","indexed":false}],"anonymous":false}]
Contract Creation Code
0x60606040526006805460a060020a61ffff02191690556102bc600955690170a0f5040e50400000600a5562069780600b55690307345d9b5a55f00000600d5567016345785d8a0000601055670de0b6b3a764000060125534156200006257600080fd5b604051610120806200248e83398101604052808051919060200180519190602001805191906020018051919060200180519190602001805191906020018051919060200180519190602001805191508290508888878442841015620000c657600080fd5b83831015620000d457600080fd5b60008211620000e257600080fd5b600160a060020a0381161515620000f857600080fd5b60019390935560029190915560045560038054600160a060020a0319908116600160a060020a03938416179091556006805490911633909216919091179055600081116200014557600080fd5b600755600160a060020a03891615156200015e57600080fd5b60088054600160a060020a031916600160a060020a038b16179055818411156200018757600080fd5b50600a92909255600b55600d556009556010555050506122e180620001ad6000396000f3006060604052600436106102bb5763ffffffff60e060020a6000350416630bf5361381146102c65780630e288064146102fa57806310c1b4141461031c5780631302d03a1461033e57806314cf12d51461036057806316934fc41461037357806320f320d0146103925780632109cf80146103b4578063224348361461040e57806323867979146104275780632674899b1461043a5780632c4e722e146104505780633197cbb614610463578063332e1a811461047657806334fcf437146104e6578063355274ea146104fc5780633b80938e1461050f5780633f4ba83a1461052e5780634042b66f1461054157806342e94c90146105545780634451d89f1461057357806344691f7e1461058657806344a2d0d2146105ad578063473b0d46146105df5780634bb278f3146105f5578063519ee19e14610608578063521eb2731461061b5780635549563c1461062e57806356afd6e31461064c5780635c975abb1461065f57806376cfc3661461067257806378e97925146106da57806379544754146106ed57806379caf670146107125780638456cb59146107255780638d4e4083146107385780638da5cb5b1461074b578063906a26e01461075e57806393e59dc1146107715780639781c3ca146107845780639e1a4d19146107d8578063a7a957ff146107eb578063aaffadf3146107fe578063ab01ba4914610811578063ad1be7c114610830578063b56797fd14610843578063b5dadb1714610856578063bbe4fd5014610869578063bdcbd9d11461087c578063c00757721461089b578063c04ecdb8146108ba578063c7efa689146108cd578063c83261bd146108e3578063caefb79e14610902578063d0e30db01461091e578063ec8ac4d814610931578063ecb70fb714610945578063f2fde38b14610958578063fc0c546a14610977578063fe6129d51461098a578063feed5561146109ac575b6102c4336109bf565b005b34156102d157600080fd5b6102e8600160a060020a03600435166024356109f3565b60405190815260200160405180910390f35b341561030557600080fd5b6102c4602460048035828101929101359035610a07565b341561032757600080fd5b6102c4600160a060020a0360043516602435610a64565b341561034957600080fd5b6102c4600160a060020a0360043516602435610ba3565b341561036b57600080fd5b6102e8610bfc565b341561037e57600080fd5b6102e8600160a060020a0360043516610c02565b341561039d57600080fd5b6102c4600160a060020a0360043516602435610c14565b6102c460048035600160a060020a03169060248035919060649060443590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610c6095505050505050565b341561041957600080fd5b6102c4600435602435610ca3565b341561043257600080fd5b6102e8610ce8565b341561044557600080fd5b6102e8600435610dc3565b341561045b57600080fd5b6102e8610e17565b341561046e57600080fd5b6102e8610e1d565b341561048157600080fd5b61049360043515156024351515610e23565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156104d25780820151838201526020016104ba565b505050509050019250505060405180910390f35b34156104f157600080fd5b6102c4600435610fd3565b341561050757600080fd5b6102e8611000565b341561051a57600080fd5b6102c4600160a060020a0360043516611006565b341561053957600080fd5b6102c4611050565b341561054c57600080fd5b6102e86110cf565b341561055f57600080fd5b6102e8600160a060020a03600435166110d5565b341561057e57600080fd5b6102c46110e7565b341561059157600080fd5b61059961110a565b604051901515815260200160405180910390f35b34156105b857600080fd5b6105c3600435611113565b604051600160a060020a03909116815260200160405180910390f35b34156105ea57600080fd5b6102c460043561113b565b341561060057600080fd5b6102c461115b565b341561061357600080fd5b6102e86111fb565b341561062657600080fd5b6105c3611201565b341561063957600080fd5b6102c46004803560248101910135611210565b341561065757600080fd5b6102e8611263565b341561066a57600080fd5b610599611273565b341561067d57600080fd5b6102c460048035600160a060020a03169060248035916044359160849060643590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061128395505050505050565b34156106e557600080fd5b6102e86112c8565b34156106f857600080fd5b6102e8600160a060020a03600435166024356044356112ce565b341561071d57600080fd5b6105c3611470565b341561073057600080fd5b6102c461147f565b341561074357600080fd5b610599611503565b341561075657600080fd5b6105c3611513565b341561076957600080fd5b6102e8611522565b341561077c57600080fd5b6105c3611528565b6102c460048035600160a060020a03169060446024803590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061153795505050505050565b34156107e357600080fd5b6102e861155a565b34156107f657600080fd5b6102e8611560565b341561080957600080fd5b6102e861156b565b341561081c57600080fd5b6102e8600160a060020a0360043516611571565b341561083b57600080fd5b6102e8611583565b341561084e57600080fd5b6102e8611589565b341561086157600080fd5b6102e8611594565b341561087457600080fd5b6102e861159a565b341561088757600080fd5b6102e8600160a060020a036004351661159e565b34156108a657600080fd5b6102c4600160a060020a03600435166115f5565b34156108c557600080fd5b6105c3611654565b34156108d857600080fd5b6102e8600435611663565b34156108ee57600080fd5b6102c4600160a060020a0360043516611693565b341561090d57600080fd5b6102c46004356024356044356118b5565b341561092957600080fd5b6105c36118eb565b6102c4600160a060020a03600435166109bf565b341561095057600080fd5b6105996118fa565b341561096357600080fd5b6102c4600160a060020a0360043516611920565b341561098257600080fd5b6105c36119bb565b341561099557600080fd5b6102c4600160a060020a03600435166024356119ca565b34156109b757600080fd5b6102e8611a9c565b60065460a060020a900460ff16156109d657600080fd5b6109f0813442602060405190810160405260008152611aa2565b50565b6000610a008383426112ce565b9392505050565b60065460009033600160a060020a03908116911614610a2557600080fd5b5060005b82811015610a5e57610a56848483818110610a4057fe5b90506020020135600160a060020a031683610c14565b600101610a29565b50505050565b60065433600160a060020a03908116911614610a7f57600080fd5b600160a060020a0382161515610a9457600080fd5b610aae600e54610aa2610ce8565b9063ffffffff611b2516565b811115610aba57600080fd5b600854600160a060020a03166303d756cb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610b0257600080fd5b6102c65a03f11515610b1357600080fd5b50505060405180519050600160a060020a031663a9059cbb838360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515610b7957600080fd5b6102c65a03f11515610b8a57600080fd5b505050604051805190501515610b9f57600080fd5b5050565b60065433600160a060020a03908116911614610bbe57600080fd5b600160a060020a03821615610bf6576011805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0384161790555b60125550565b600b5481565b60146020526000908152604090205481565b60065433600160a060020a03908116911614610c2f57600080fd5b600160a060020a0382161515610c4457600080fd5b600160a060020a03909116600090815260176020526040902055565b60065460a060020a900460ff1615610c7757600080fd5b60135433600160a060020a03908116911614610c9257600080fd5b610c9e83348484611aa2565b505050565b60065433600160a060020a03908116911614610cbe57600080fd5b80821115610ccb57600080fd5b610cd36118fa565b15610cdd57600080fd5b600191909155600255565b600854600090600160a060020a03166303d756cb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610d3257600080fd5b6102c65a03f11515610d4357600080fd5b50505060405180519050600160a060020a03166370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515610da357600080fd5b6102c65a03f11515610db457600080fd5b50505060405180519150505b90565b6001546000908190831115610e0d57610e0a6001610dfe610e10610df260015488611b2590919063ffffffff16565b9063ffffffff611b3716565b9063ffffffff611b4e16565b90505b8091505b50919050565b60095481565b60025481565b610e2b612266565b600080610e36612266565b60185460009350839250604051805910610e4d5750595b90808252806020026020018201604052509050600092505b601854831015610f5857858015610eb35750600060146000601886815481101515610e8c57fe5b6000918252602080832090910154600160a060020a03168352820192909252604001902054115b80610efb5750848015610efb575060146000601885815481101515610ed457fe5b6000918252602080832090910154600160a060020a03168352820192909252604001902054155b15610f4d576018805484908110610f0e57fe5b600091825260209091200154600160a060020a0316818381518110610f2f57fe5b600160a060020a039092166020928302909101909101526001909101905b600190920191610e65565b81604051805910610f665750595b90808252806020026020018201604052509350600092505b81831015610fca57808381518110610f9257fe5b90602001906020020151848481518110610fa857fe5b600160a060020a03909216602092830290910190910152600190920191610f7e565b50505092915050565b60065433600160a060020a03908116911614610fee57600080fd5b60008111610ffb57600080fd5b600955565b600d5481565b60065433600160a060020a0390811691161461102157600080fd5b6013805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60065433600160a060020a0390811691161461106b57600080fd5b60065460a060020a900460ff16151561108357600080fd5b6006805474ff0000000000000000000000000000000000000000191690557f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3360405160405180910390a1565b60055481565b60156020526000908152604090205481565b60065460a860020a900460ff1615156110ff57600080fd5b61110833611693565b565b60015442101590565b601880548290811061112157fe5b600091825260209091200154600160a060020a0316905081565b60065433600160a060020a0390811691161461115657600080fd5b601055565b60065433600160a060020a0390811691161461117657600080fd5b60065460a860020a900460ff161561118d57600080fd5b6111956118fa565b15156111a057600080fd5b6111a8611b5d565b7f6823b073d48d6e3a7d385eeb601452d680e74bb46afe3255a7d778f3a9b1768160405160405180910390a16006805475ff000000000000000000000000000000000000000000191660a860020a179055565b600f5481565b600354600160a060020a031681565b60065460009060a860020a900460ff16151561122b57600080fd5b5060005b81811015610c9e5761125b83838381811061124657fe5b90506020020135600160a060020a0316611693565b60010161122f565b600061126e3361159e565b905090565b60065460a060020a900460ff1681565b60065433600160a060020a0390811691161461129e57600080fd5b60065460a060020a900460ff16156112b557600080fd5b6112c184848484611d2e565b5050505050565b60015481565b60646000806112dc84611663565b91506112e784610dc3565b90506001821161132e57600181116113025760829250611329565b6005811161131357607d9250611329565b600881116113245760789250611329565b607692505b611418565b6002821161133f5760749250611418565b600382116113505760739250611418565b600582116113615760729250611418565b600782116113725760719250611418565b600982116113835760709250611418565b600b821161139457606f9250611418565b600d82116113a557606e9250611418565b600f82116113b657606c9250611418565b601182116113c757606b9250611418565b601382116113d857606a9250611418565b601582116113e95760699250611418565b601782116113fa5760689250611418565b6019821161140b5760679250611418565b601b821161141857606692505b68056bc75e2d63100000851061143357826004019250611449565b678ac7230489e800008510611449578260020192505b600160a060020a038616600090815260176020526040902054929092019150509392505050565b600854600160a060020a031681565b60065433600160a060020a0390811691161461149a57600080fd5b60065460a060020a900460ff16156114b157600080fd5b6006805474ff0000000000000000000000000000000000000000191660a060020a1790557f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62560405160405180910390a1565b60065460a860020a900460ff1681565b600654600160a060020a031681565b600a5481565b601154600160a060020a031681565b60065460a060020a900460ff161561154e57600080fd5b610b9f82344284611aa2565b600e5481565b600061126e42611663565b60105481565b60176020526000908152604090205481565b600c5481565b600061126e42610dc3565b60125481565b4290565b600080600160a060020a03831615156115b657600080fd5b6115be6118fa565b806115d2575060065460a060020a900460ff165b156115e05760009150610e11565b600554600d54610e0a9163ffffffff611b2516565b60065433600160a060020a0390811691161461161057600080fd5b600160a060020a038116151561162557600080fd5b6016805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b601654600160a060020a031681565b6001546000908190831115610e0d57610e0a6001610dfe62015180610df260015488611b2590919063ffffffff16565b60065460009060a860020a900460ff1615156116ae57600080fd5b60065460a060020a900460ff16156116c557600080fd5b50600160a060020a0381166000908152601460205260408120549081116116eb57600080fd5b600160a060020a038216600090815260146020526040812055600e54611717908263ffffffff611b2516565b600e55600854600160a060020a03166393a378da838360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561177057600080fd5b6102c65a03f1151561178157600080fd5b5050600854600160a060020a031690506303d756cb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117cd57600080fd5b6102c65a03f115156117de57600080fd5b50505060405180519050600160a060020a031663a9059cbb838360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561184457600080fd5b6102c65a03f1151561185557600080fd5b50505060405180519050151561186a57600080fd5b81600160a060020a031633600160a060020a03167f745f0808907a1633a7823cd566251e5cba0343095ab069646aedeeef4b21db7e8360405190815260200160405180910390a35050565b60065433600160a060020a039081169116146118d057600080fd5b808311156118dd57600080fd5b600a92909255600b55600d55565b601354600160a060020a031681565b6000611904611e1e565b8061126e57506000600c5411801561126e575050600c54421190565b60065433600160a060020a0390811691161461193b57600080fd5b600160a060020a038116151561195057600080fd5b600654600160a060020a0380831691167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600054600160a060020a031681565b60165460009033600160a060020a03908116911614806119f8575060065433600160a060020a039081169116145b1515611a0357600080fd5b60008211611a1057600080fd5b816040519081526020016040519081900390207fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d214611a50576005611a53565b60065b600160a060020a03841660009081526017602052604090205460ff91909116915081901015610c9e57600160a060020a0383166000908152601760205260409020819055505050565b60185490565b600080600160a060020a0386161515611aba57600080fd5b611ac686868686611d2e565b9150611ad182611e36565b611ae1858363ffffffff611b2516565b90506000811115611b1d57600160a060020a03861681156108fc0282604051600060405180830381858888f193505050501515611b1d57600080fd5b505050505050565b600082821115611b3157fe5b50900390565b6000808284811515611b4557fe5b04949350505050565b600082820183811015610a0057fe5b6000611b67610ce8565b600e54600f819055909150811115611cc557600854600160a060020a03166303d756cb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611bc157600080fd5b6102c65a03f11515611bd257600080fd5b5050506040518051600854600160a060020a03918216925063a9059cbb9116634db08aea6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611c2d57600080fd5b6102c65a03f11515611c3e57600080fd5b50505060405180519050611c5d600e5485611b2590919063ffffffff16565b60006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515611ca957600080fd5b6102c65a03f11515611cba57600080fd5b505050604051805150505b600854600160a060020a031663b0e9a1ef62127500420160405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515611d1257600080fd5b6102c65a03f11515611d2357600080fd5b5050506109f0611108565b60008080600160a060020a0387161515611d4757600080fd5b611d508761159e565b9150611d5c8287611e69565b9050611d6a87828787611e78565b600a5460055410158015611d7e5750600c54155b15611ddc57600b54611d9790429063ffffffff611b4e16565b600c8190556002547f3812a5cf05e3a3e326f849747010fac31638a04bcc715d65b7456c64bfcf29d591611dca91611e69565b60405190815260200160405180910390a15b600d5460055410611e14577f66621f0543c2b9a9a0f8a2705df5c21104202b029dc22c3c0e07507e5b13cc5b60405160405180910390a15b9695505050505050565b6000611e286121f3565b8061126e575061126e6121fb565b600354600160a060020a031681156108fc0282604051600060405180830381858888f1935050505015156109f057600080fd5b6000818311610e115782610a00565b600080600160a060020a0386161515611e9057600080fd5b611e9985612206565b1515611ea457600080fd5b600554611eb7908663ffffffff611b4e16565b600555600160a060020a038616600090815260156020526040902054611ee3908663ffffffff611b4e16565b600160a060020a038716600090815260156020526040902081905560125490111580611f7f5750601154600160a060020a0316633af32abf8760006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515611f6357600080fd5b6102c65a03f11515611f7457600080fd5b505050604051805190505b806120705750601154600160a060020a031663a30bdea487856000604051602001526040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015612008578082015183820152602001611ff0565b50505050905090810190601f1680156120355780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b151561205457600080fd5b6102c65a03f1151561206557600080fd5b505050604051805190505b151561207b57600080fd5b6120868686866112ce565b91506120b26064610df2846120a66009548a61224290919063ffffffff16565b9063ffffffff61224216565b600e549091506120c8908263ffffffff611b4e16565b600e55600160a060020a038616600090815260146020526040902054151561212f5760188054600181016120fc8382612278565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0388161790555b600160a060020a038616600090815260146020526040902054612158908263ffffffff611b4e16565b6014600088600160a060020a0316600160a060020a031681526020019081526020016000208190555085600160a060020a031633600160a060020a03167fffff2a5737230ff40ffd57ba6d06d4ca8e5ea76c5d25aefe5538c9942346b7d087846018805490506005546040518085815260200184815260200183815260200182815260200194505050505060405180910390a3505050505050565b600254421190565b600754600554101590565b6000806000806122146118fa565b1592508460001415915060105485101590508280156122305750815b80156122395750805b95945050505050565b600082820283158061225e575082848281151561225b57fe5b04145b1515610a0057fe5b60206040519081016040526000815290565b815481835581811511610c9e57600083815260209020610c9e918101908301610dc091905b808211156122b1576000815560010161229d565b50905600a165627a7a72305820f6fcdff934a92a2e554c996651bf834b7f60f12831e1855cf0b25720ce49fb080029000000000000000000000000b565726e2e44e4ae9e3ce750fc4ba8fa65e701e0000000000000000000000000000000000000000000000000000000005b108c80000000000000000000000000000000000000000000000000000000005b381980000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000028a857425466f800000000000000000000000000000000000000000000000000000000000000028de8000000000000000000000000000000000000000000000054b40b1f852bda00000000000000000000000000000fc5c6c8015962e7035f3bdc5fe7ec94bedc77833
Deployed ByteCode
0x6060604052600436106102bb5763ffffffff60e060020a6000350416630bf5361381146102c65780630e288064146102fa57806310c1b4141461031c5780631302d03a1461033e57806314cf12d51461036057806316934fc41461037357806320f320d0146103925780632109cf80146103b4578063224348361461040e57806323867979146104275780632674899b1461043a5780632c4e722e146104505780633197cbb614610463578063332e1a811461047657806334fcf437146104e6578063355274ea146104fc5780633b80938e1461050f5780633f4ba83a1461052e5780634042b66f1461054157806342e94c90146105545780634451d89f1461057357806344691f7e1461058657806344a2d0d2146105ad578063473b0d46146105df5780634bb278f3146105f5578063519ee19e14610608578063521eb2731461061b5780635549563c1461062e57806356afd6e31461064c5780635c975abb1461065f57806376cfc3661461067257806378e97925146106da57806379544754146106ed57806379caf670146107125780638456cb59146107255780638d4e4083146107385780638da5cb5b1461074b578063906a26e01461075e57806393e59dc1146107715780639781c3ca146107845780639e1a4d19146107d8578063a7a957ff146107eb578063aaffadf3146107fe578063ab01ba4914610811578063ad1be7c114610830578063b56797fd14610843578063b5dadb1714610856578063bbe4fd5014610869578063bdcbd9d11461087c578063c00757721461089b578063c04ecdb8146108ba578063c7efa689146108cd578063c83261bd146108e3578063caefb79e14610902578063d0e30db01461091e578063ec8ac4d814610931578063ecb70fb714610945578063f2fde38b14610958578063fc0c546a14610977578063fe6129d51461098a578063feed5561146109ac575b6102c4336109bf565b005b34156102d157600080fd5b6102e8600160a060020a03600435166024356109f3565b60405190815260200160405180910390f35b341561030557600080fd5b6102c4602460048035828101929101359035610a07565b341561032757600080fd5b6102c4600160a060020a0360043516602435610a64565b341561034957600080fd5b6102c4600160a060020a0360043516602435610ba3565b341561036b57600080fd5b6102e8610bfc565b341561037e57600080fd5b6102e8600160a060020a0360043516610c02565b341561039d57600080fd5b6102c4600160a060020a0360043516602435610c14565b6102c460048035600160a060020a03169060248035919060649060443590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610c6095505050505050565b341561041957600080fd5b6102c4600435602435610ca3565b341561043257600080fd5b6102e8610ce8565b341561044557600080fd5b6102e8600435610dc3565b341561045b57600080fd5b6102e8610e17565b341561046e57600080fd5b6102e8610e1d565b341561048157600080fd5b61049360043515156024351515610e23565b60405160208082528190810183818151815260200191508051906020019060200280838360005b838110156104d25780820151838201526020016104ba565b505050509050019250505060405180910390f35b34156104f157600080fd5b6102c4600435610fd3565b341561050757600080fd5b6102e8611000565b341561051a57600080fd5b6102c4600160a060020a0360043516611006565b341561053957600080fd5b6102c4611050565b341561054c57600080fd5b6102e86110cf565b341561055f57600080fd5b6102e8600160a060020a03600435166110d5565b341561057e57600080fd5b6102c46110e7565b341561059157600080fd5b61059961110a565b604051901515815260200160405180910390f35b34156105b857600080fd5b6105c3600435611113565b604051600160a060020a03909116815260200160405180910390f35b34156105ea57600080fd5b6102c460043561113b565b341561060057600080fd5b6102c461115b565b341561061357600080fd5b6102e86111fb565b341561062657600080fd5b6105c3611201565b341561063957600080fd5b6102c46004803560248101910135611210565b341561065757600080fd5b6102e8611263565b341561066a57600080fd5b610599611273565b341561067d57600080fd5b6102c460048035600160a060020a03169060248035916044359160849060643590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061128395505050505050565b34156106e557600080fd5b6102e86112c8565b34156106f857600080fd5b6102e8600160a060020a03600435166024356044356112ce565b341561071d57600080fd5b6105c3611470565b341561073057600080fd5b6102c461147f565b341561074357600080fd5b610599611503565b341561075657600080fd5b6105c3611513565b341561076957600080fd5b6102e8611522565b341561077c57600080fd5b6105c3611528565b6102c460048035600160a060020a03169060446024803590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284375094965061153795505050505050565b34156107e357600080fd5b6102e861155a565b34156107f657600080fd5b6102e8611560565b341561080957600080fd5b6102e861156b565b341561081c57600080fd5b6102e8600160a060020a0360043516611571565b341561083b57600080fd5b6102e8611583565b341561084e57600080fd5b6102e8611589565b341561086157600080fd5b6102e8611594565b341561087457600080fd5b6102e861159a565b341561088757600080fd5b6102e8600160a060020a036004351661159e565b34156108a657600080fd5b6102c4600160a060020a03600435166115f5565b34156108c557600080fd5b6105c3611654565b34156108d857600080fd5b6102e8600435611663565b34156108ee57600080fd5b6102c4600160a060020a0360043516611693565b341561090d57600080fd5b6102c46004356024356044356118b5565b341561092957600080fd5b6105c36118eb565b6102c4600160a060020a03600435166109bf565b341561095057600080fd5b6105996118fa565b341561096357600080fd5b6102c4600160a060020a0360043516611920565b341561098257600080fd5b6105c36119bb565b341561099557600080fd5b6102c4600160a060020a03600435166024356119ca565b34156109b757600080fd5b6102e8611a9c565b60065460a060020a900460ff16156109d657600080fd5b6109f0813442602060405190810160405260008152611aa2565b50565b6000610a008383426112ce565b9392505050565b60065460009033600160a060020a03908116911614610a2557600080fd5b5060005b82811015610a5e57610a56848483818110610a4057fe5b90506020020135600160a060020a031683610c14565b600101610a29565b50505050565b60065433600160a060020a03908116911614610a7f57600080fd5b600160a060020a0382161515610a9457600080fd5b610aae600e54610aa2610ce8565b9063ffffffff611b2516565b811115610aba57600080fd5b600854600160a060020a03166303d756cb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610b0257600080fd5b6102c65a03f11515610b1357600080fd5b50505060405180519050600160a060020a031663a9059cbb838360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515610b7957600080fd5b6102c65a03f11515610b8a57600080fd5b505050604051805190501515610b9f57600080fd5b5050565b60065433600160a060020a03908116911614610bbe57600080fd5b600160a060020a03821615610bf6576011805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0384161790555b60125550565b600b5481565b60146020526000908152604090205481565b60065433600160a060020a03908116911614610c2f57600080fd5b600160a060020a0382161515610c4457600080fd5b600160a060020a03909116600090815260176020526040902055565b60065460a060020a900460ff1615610c7757600080fd5b60135433600160a060020a03908116911614610c9257600080fd5b610c9e83348484611aa2565b505050565b60065433600160a060020a03908116911614610cbe57600080fd5b80821115610ccb57600080fd5b610cd36118fa565b15610cdd57600080fd5b600191909155600255565b600854600090600160a060020a03166303d756cb82604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610d3257600080fd5b6102c65a03f11515610d4357600080fd5b50505060405180519050600160a060020a03166370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515610da357600080fd5b6102c65a03f11515610db457600080fd5b50505060405180519150505b90565b6001546000908190831115610e0d57610e0a6001610dfe610e10610df260015488611b2590919063ffffffff16565b9063ffffffff611b3716565b9063ffffffff611b4e16565b90505b8091505b50919050565b60095481565b60025481565b610e2b612266565b600080610e36612266565b60185460009350839250604051805910610e4d5750595b90808252806020026020018201604052509050600092505b601854831015610f5857858015610eb35750600060146000601886815481101515610e8c57fe5b6000918252602080832090910154600160a060020a03168352820192909252604001902054115b80610efb5750848015610efb575060146000601885815481101515610ed457fe5b6000918252602080832090910154600160a060020a03168352820192909252604001902054155b15610f4d576018805484908110610f0e57fe5b600091825260209091200154600160a060020a0316818381518110610f2f57fe5b600160a060020a039092166020928302909101909101526001909101905b600190920191610e65565b81604051805910610f665750595b90808252806020026020018201604052509350600092505b81831015610fca57808381518110610f9257fe5b90602001906020020151848481518110610fa857fe5b600160a060020a03909216602092830290910190910152600190920191610f7e565b50505092915050565b60065433600160a060020a03908116911614610fee57600080fd5b60008111610ffb57600080fd5b600955565b600d5481565b60065433600160a060020a0390811691161461102157600080fd5b6013805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60065433600160a060020a0390811691161461106b57600080fd5b60065460a060020a900460ff16151561108357600080fd5b6006805474ff0000000000000000000000000000000000000000191690557f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3360405160405180910390a1565b60055481565b60156020526000908152604090205481565b60065460a860020a900460ff1615156110ff57600080fd5b61110833611693565b565b60015442101590565b601880548290811061112157fe5b600091825260209091200154600160a060020a0316905081565b60065433600160a060020a0390811691161461115657600080fd5b601055565b60065433600160a060020a0390811691161461117657600080fd5b60065460a860020a900460ff161561118d57600080fd5b6111956118fa565b15156111a057600080fd5b6111a8611b5d565b7f6823b073d48d6e3a7d385eeb601452d680e74bb46afe3255a7d778f3a9b1768160405160405180910390a16006805475ff000000000000000000000000000000000000000000191660a860020a179055565b600f5481565b600354600160a060020a031681565b60065460009060a860020a900460ff16151561122b57600080fd5b5060005b81811015610c9e5761125b83838381811061124657fe5b90506020020135600160a060020a0316611693565b60010161122f565b600061126e3361159e565b905090565b60065460a060020a900460ff1681565b60065433600160a060020a0390811691161461129e57600080fd5b60065460a060020a900460ff16156112b557600080fd5b6112c184848484611d2e565b5050505050565b60015481565b60646000806112dc84611663565b91506112e784610dc3565b90506001821161132e57600181116113025760829250611329565b6005811161131357607d9250611329565b600881116113245760789250611329565b607692505b611418565b6002821161133f5760749250611418565b600382116113505760739250611418565b600582116113615760729250611418565b600782116113725760719250611418565b600982116113835760709250611418565b600b821161139457606f9250611418565b600d82116113a557606e9250611418565b600f82116113b657606c9250611418565b601182116113c757606b9250611418565b601382116113d857606a9250611418565b601582116113e95760699250611418565b601782116113fa5760689250611418565b6019821161140b5760679250611418565b601b821161141857606692505b68056bc75e2d63100000851061143357826004019250611449565b678ac7230489e800008510611449578260020192505b600160a060020a038616600090815260176020526040902054929092019150509392505050565b600854600160a060020a031681565b60065433600160a060020a0390811691161461149a57600080fd5b60065460a060020a900460ff16156114b157600080fd5b6006805474ff0000000000000000000000000000000000000000191660a060020a1790557f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62560405160405180910390a1565b60065460a860020a900460ff1681565b600654600160a060020a031681565b600a5481565b601154600160a060020a031681565b60065460a060020a900460ff161561154e57600080fd5b610b9f82344284611aa2565b600e5481565b600061126e42611663565b60105481565b60176020526000908152604090205481565b600c5481565b600061126e42610dc3565b60125481565b4290565b600080600160a060020a03831615156115b657600080fd5b6115be6118fa565b806115d2575060065460a060020a900460ff165b156115e05760009150610e11565b600554600d54610e0a9163ffffffff611b2516565b60065433600160a060020a0390811691161461161057600080fd5b600160a060020a038116151561162557600080fd5b6016805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b601654600160a060020a031681565b6001546000908190831115610e0d57610e0a6001610dfe62015180610df260015488611b2590919063ffffffff16565b60065460009060a860020a900460ff1615156116ae57600080fd5b60065460a060020a900460ff16156116c557600080fd5b50600160a060020a0381166000908152601460205260408120549081116116eb57600080fd5b600160a060020a038216600090815260146020526040812055600e54611717908263ffffffff611b2516565b600e55600854600160a060020a03166393a378da838360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561177057600080fd5b6102c65a03f1151561178157600080fd5b5050600854600160a060020a031690506303d756cb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156117cd57600080fd5b6102c65a03f115156117de57600080fd5b50505060405180519050600160a060020a031663a9059cbb838360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b151561184457600080fd5b6102c65a03f1151561185557600080fd5b50505060405180519050151561186a57600080fd5b81600160a060020a031633600160a060020a03167f745f0808907a1633a7823cd566251e5cba0343095ab069646aedeeef4b21db7e8360405190815260200160405180910390a35050565b60065433600160a060020a039081169116146118d057600080fd5b808311156118dd57600080fd5b600a92909255600b55600d55565b601354600160a060020a031681565b6000611904611e1e565b8061126e57506000600c5411801561126e575050600c54421190565b60065433600160a060020a0390811691161461193b57600080fd5b600160a060020a038116151561195057600080fd5b600654600160a060020a0380831691167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600054600160a060020a031681565b60165460009033600160a060020a03908116911614806119f8575060065433600160a060020a039081169116145b1515611a0357600080fd5b60008211611a1057600080fd5b816040519081526020016040519081900390207fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d214611a50576005611a53565b60065b600160a060020a03841660009081526017602052604090205460ff91909116915081901015610c9e57600160a060020a0383166000908152601760205260409020819055505050565b60185490565b600080600160a060020a0386161515611aba57600080fd5b611ac686868686611d2e565b9150611ad182611e36565b611ae1858363ffffffff611b2516565b90506000811115611b1d57600160a060020a03861681156108fc0282604051600060405180830381858888f193505050501515611b1d57600080fd5b505050505050565b600082821115611b3157fe5b50900390565b6000808284811515611b4557fe5b04949350505050565b600082820183811015610a0057fe5b6000611b67610ce8565b600e54600f819055909150811115611cc557600854600160a060020a03166303d756cb6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611bc157600080fd5b6102c65a03f11515611bd257600080fd5b5050506040518051600854600160a060020a03918216925063a9059cbb9116634db08aea6000604051602001526040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515611c2d57600080fd5b6102c65a03f11515611c3e57600080fd5b50505060405180519050611c5d600e5485611b2590919063ffffffff16565b60006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515611ca957600080fd5b6102c65a03f11515611cba57600080fd5b505050604051805150505b600854600160a060020a031663b0e9a1ef62127500420160405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515611d1257600080fd5b6102c65a03f11515611d2357600080fd5b5050506109f0611108565b60008080600160a060020a0387161515611d4757600080fd5b611d508761159e565b9150611d5c8287611e69565b9050611d6a87828787611e78565b600a5460055410158015611d7e5750600c54155b15611ddc57600b54611d9790429063ffffffff611b4e16565b600c8190556002547f3812a5cf05e3a3e326f849747010fac31638a04bcc715d65b7456c64bfcf29d591611dca91611e69565b60405190815260200160405180910390a15b600d5460055410611e14577f66621f0543c2b9a9a0f8a2705df5c21104202b029dc22c3c0e07507e5b13cc5b60405160405180910390a15b9695505050505050565b6000611e286121f3565b8061126e575061126e6121fb565b600354600160a060020a031681156108fc0282604051600060405180830381858888f1935050505015156109f057600080fd5b6000818311610e115782610a00565b600080600160a060020a0386161515611e9057600080fd5b611e9985612206565b1515611ea457600080fd5b600554611eb7908663ffffffff611b4e16565b600555600160a060020a038616600090815260156020526040902054611ee3908663ffffffff611b4e16565b600160a060020a038716600090815260156020526040902081905560125490111580611f7f5750601154600160a060020a0316633af32abf8760006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515611f6357600080fd5b6102c65a03f11515611f7457600080fd5b505050604051805190505b806120705750601154600160a060020a031663a30bdea487856000604051602001526040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015612008578082015183820152602001611ff0565b50505050905090810190601f1680156120355780820380516001836020036101000a031916815260200191505b509350505050602060405180830381600087803b151561205457600080fd5b6102c65a03f1151561206557600080fd5b505050604051805190505b151561207b57600080fd5b6120868686866112ce565b91506120b26064610df2846120a66009548a61224290919063ffffffff16565b9063ffffffff61224216565b600e549091506120c8908263ffffffff611b4e16565b600e55600160a060020a038616600090815260146020526040902054151561212f5760188054600181016120fc8382612278565b506000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0388161790555b600160a060020a038616600090815260146020526040902054612158908263ffffffff611b4e16565b6014600088600160a060020a0316600160a060020a031681526020019081526020016000208190555085600160a060020a031633600160a060020a03167fffff2a5737230ff40ffd57ba6d06d4ca8e5ea76c5d25aefe5538c9942346b7d087846018805490506005546040518085815260200184815260200183815260200182815260200194505050505060405180910390a3505050505050565b600254421190565b600754600554101590565b6000806000806122146118fa565b1592508460001415915060105485101590508280156122305750815b80156122395750805b95945050505050565b600082820283158061225e575082848281151561225b57fe5b04145b1515610a0057fe5b60206040519081016040526000815290565b815481835581811511610c9e57600083815260209020610c9e918101908301610dc091905b808211156122b1576000815560010161229d565b50905600a165627a7a72305820f6fcdff934a92a2e554c996651bf834b7f60f12831e1855cf0b25720ce49fb080029