From 8fb2d6428ee1d5bf1cf223ecb454314e0c2691dd Mon Sep 17 00:00:00 2001 From: HaoyangLiu Date: Tue, 16 Jun 2020 19:10:15 +0800 Subject: [PATCH] add fail ack handler for transferOut and add unit tests (#22) --- contracts/TokenHub.sol | 153 +++++++++++++------- contracts/TokenHub.template | 153 +++++++++++++------- contracts/test/MiniToken.sol | 241 +++++++++++++++++++++++++++++++ genesis.json | 2 +- migrations/2_deploy_contracts.js | 23 ++- test/TestTokenHub.js | 139 ++++++++++++++---- 6 files changed, 570 insertions(+), 141 deletions(-) create mode 100644 contracts/test/MiniToken.sol diff --git a/contracts/TokenHub.sol b/contracts/TokenHub.sol index 303d049f8..ccd053707 100644 --- a/contracts/TokenHub.sol +++ b/contracts/TokenHub.sol @@ -52,7 +52,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR struct TransferOutAckPackage { address contractAddr; uint256[] refundAmounts; - address payable[] refundAddrs; + address[] refundAddrs; uint32 status; } @@ -61,7 +61,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR bytes32 bep2TokenSymbol; address contractAddr; uint256 amount; - address payable recipient; + address recipient; address refundAddr; uint64 expireTime; } @@ -114,8 +114,8 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR event transferInSuccess(address bep2eAddr, address refundAddr, uint256 amount); event transferOutSuccess(address bep2eAddr, address senderAddr, uint256 amount); - event refundSuccess(address bep2eAddr, address refundAddr, uint256 amount); - event refundFailure(address bep2eAddr, address refundAddr, uint256 amount); + event refundSuccess(address bep2eAddr, address refundAddr, uint256 amount, uint32 status); + event refundFailure(address bep2eAddr, address refundAddr, uint256 amount, uint32 status); event rewardTo(address to, uint256 amount); event unexpectedPackage(uint8 channelId, bytes msgBytes); @@ -142,7 +142,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return relayFee; } - function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory responsePayload){ + function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory){ if (channelId == BIND_CHANNELID) { return handleBindSyncPackage(msgBytes); } else if (channelId == TRANSFER_IN_CHANNELID) { @@ -162,7 +162,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } function handleFailAckPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override { - emit unexpectedPackage(channelId, msgBytes); + if (channelId == TRANSFER_OUT_CHANNELID) { + handleTransferOutFailAckPackage(msgBytes); + } else { + emit unexpectedPackage(channelId, msgBytes); + } } function decodeBindSyncPackage(bytes memory msgBytes) internal pure returns(BindSyncPackage memory, bool) { @@ -187,7 +191,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return (bindSyncPkg, success); } - function handleBindSyncPackage(bytes memory msgBytes) onlyInit internal returns(bytes memory) { + function handleBindSyncPackage(bytes memory msgBytes) internal returns(bytes memory) { (BindSyncPackage memory bindSyncPkg, bool success) = decodeBindSyncPackage(msgBytes); require(success, "unrecognized transferIn package"); if (bindSyncPkg.packageType == BIND_PACKAGE) { @@ -301,7 +305,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if ( idx == 0 ) transInSyncPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); else if ( idx == 1 ) transInSyncPkg.contractAddr = iter.next().toAddress(); else if ( idx == 2 ) transInSyncPkg.amount = iter.next().toUint(); - else if ( idx == 3 ) transInSyncPkg.recipient = address(uint160((iter.next().toAddress()))); + else if ( idx == 3 ) transInSyncPkg.recipient = ((iter.next().toAddress())); else if ( idx == 4 ) transInSyncPkg.refundAddr = iter.next().toAddress(); else if ( idx == 5 ) { transInSyncPkg.expireTime = uint64(iter.next().toUint()); @@ -348,7 +352,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if (address(this).balance < transInSyncPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - if (!transInSyncPkg.recipient.send(transInSyncPkg.amount)) { + if (!address(uint160(transInSyncPkg.recipient)).send(transInSyncPkg.amount)) { return TRANSFER_IN_FAILURE_NON_PAYABLE_RECIPIENT; } emit transferInSuccess(transInSyncPkg.contractAddr, transInSyncPkg.recipient, transInSyncPkg.amount); @@ -360,25 +364,15 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if (contractAddrToBEP2Symbol[transInSyncPkg.contractAddr]!= transInSyncPkg.bep2TokenSymbol) { return TRANSFER_IN_FAILURE_UNBOUND_TOKEN; } - try IBEP2E(transInSyncPkg.contractAddr).balanceOf{gas: MAX_GAS_FOR_CALLING_BEP2E}(address(this)) returns (uint256 actualBalance) { - if (actualBalance < transInSyncPkg.amount) { - return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; - } - } catch Error(string memory) { - return TRANSFER_IN_FAILURE_UNKNOWN; - } catch (bytes memory) { - return TRANSFER_IN_FAILURE_UNKNOWN; + uint256 actualBalance = IBEP2E(transInSyncPkg.contractAddr).balanceOf{gas: MAX_GAS_FOR_CALLING_BEP2E}(address(this)); + if (actualBalance < transInSyncPkg.amount) { + return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - try IBEP2E(transInSyncPkg.contractAddr).transfer{gas: MAX_GAS_FOR_CALLING_BEP2E}(transInSyncPkg.recipient, transInSyncPkg.amount) returns (bool success) { - if (success){ - emit transferInSuccess(transInSyncPkg.contractAddr, transInSyncPkg.recipient, transInSyncPkg.amount); - return TRANSFER_IN_SUCCESS; - } else { - return TRANSFER_IN_FAILURE_UNKNOWN; - } - } catch Error(string memory) { - return TRANSFER_IN_FAILURE_UNKNOWN; - } catch (bytes memory) { + bool success = IBEP2E(transInSyncPkg.contractAddr).transfer{gas: MAX_GAS_FOR_CALLING_BEP2E}(transInSyncPkg.recipient, transInSyncPkg.amount); + if (success){ + emit transferInSuccess(transInSyncPkg.contractAddr, transInSyncPkg.recipient, transInSyncPkg.amount); + return TRANSFER_IN_SUCCESS; + } else { return TRANSFER_IN_FAILURE_UNKNOWN; } } @@ -403,9 +397,9 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } else if ( idx == 2 ) { RLPDecode.RLPItem[] memory list = iter.next().toList(); - transOutAckPkg.refundAddrs = new address payable[](list.length); + transOutAckPkg.refundAddrs = new address[](list.length); for(uint256 index=0; index BEP2_TOKEN_DECIMALS) { + return amount.mul(10**(bep2eTokenDecimals-BEP2_TOKEN_DECIMALS)); + } + return amount.div(10**(BEP2_TOKEN_DECIMALS-bep2eTokenDecimals)); + } + function getBoundContract(string memory bep2Symbol) public view returns (address) { bytes32 bep2TokenSymbol = bep2TokenSymbolConvert(bep2Symbol); return bep2SymbolToContractAddr[bep2TokenSymbol]; @@ -655,7 +700,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint8 bep2SymbolLength = 0; for (uint8 j = 0; j < 32; j++) { if (bep2SymbolBytes[j] != 0) { - bep2SymbolLength++; + bep2SymbolLength++; } else { break; } diff --git a/contracts/TokenHub.template b/contracts/TokenHub.template index 2f12a9010..2115bef6b 100644 --- a/contracts/TokenHub.template +++ b/contracts/TokenHub.template @@ -52,7 +52,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR struct TransferOutAckPackage { address contractAddr; uint256[] refundAmounts; - address payable[] refundAddrs; + address[] refundAddrs; uint32 status; } @@ -61,7 +61,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR bytes32 bep2TokenSymbol; address contractAddr; uint256 amount; - address payable recipient; + address recipient; address refundAddr; uint64 expireTime; } @@ -114,8 +114,8 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR event transferInSuccess(address bep2eAddr, address refundAddr, uint256 amount); event transferOutSuccess(address bep2eAddr, address senderAddr, uint256 amount); - event refundSuccess(address bep2eAddr, address refundAddr, uint256 amount); - event refundFailure(address bep2eAddr, address refundAddr, uint256 amount); + event refundSuccess(address bep2eAddr, address refundAddr, uint256 amount, uint32 status); + event refundFailure(address bep2eAddr, address refundAddr, uint256 amount, uint32 status); event rewardTo(address to, uint256 amount); event unexpectedPackage(uint8 channelId, bytes msgBytes); @@ -147,7 +147,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return relayFee; } - function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory responsePayload){ + function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory){ if (channelId == BIND_CHANNELID) { return handleBindSyncPackage(msgBytes); } else if (channelId == TRANSFER_IN_CHANNELID) { @@ -167,7 +167,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } function handleFailAckPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override { - emit unexpectedPackage(channelId, msgBytes); + if (channelId == TRANSFER_OUT_CHANNELID) { + handleTransferOutFailAckPackage(msgBytes); + } else { + emit unexpectedPackage(channelId, msgBytes); + } } function decodeBindSyncPackage(bytes memory msgBytes) internal pure returns(BindSyncPackage memory, bool) { @@ -192,7 +196,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return (bindSyncPkg, success); } - function handleBindSyncPackage(bytes memory msgBytes) onlyInit internal returns(bytes memory) { + function handleBindSyncPackage(bytes memory msgBytes) internal returns(bytes memory) { (BindSyncPackage memory bindSyncPkg, bool success) = decodeBindSyncPackage(msgBytes); require(success, "unrecognized transferIn package"); if (bindSyncPkg.packageType == BIND_PACKAGE) { @@ -306,7 +310,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if ( idx == 0 ) transInSyncPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); else if ( idx == 1 ) transInSyncPkg.contractAddr = iter.next().toAddress(); else if ( idx == 2 ) transInSyncPkg.amount = iter.next().toUint(); - else if ( idx == 3 ) transInSyncPkg.recipient = address(uint160((iter.next().toAddress()))); + else if ( idx == 3 ) transInSyncPkg.recipient = ((iter.next().toAddress())); else if ( idx == 4 ) transInSyncPkg.refundAddr = iter.next().toAddress(); else if ( idx == 5 ) { transInSyncPkg.expireTime = uint64(iter.next().toUint()); @@ -353,7 +357,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if (address(this).balance < transInSyncPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - if (!transInSyncPkg.recipient.send(transInSyncPkg.amount)) { + if (!address(uint160(transInSyncPkg.recipient)).send(transInSyncPkg.amount)) { return TRANSFER_IN_FAILURE_NON_PAYABLE_RECIPIENT; } emit transferInSuccess(transInSyncPkg.contractAddr, transInSyncPkg.recipient, transInSyncPkg.amount); @@ -365,25 +369,15 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if (contractAddrToBEP2Symbol[transInSyncPkg.contractAddr]!= transInSyncPkg.bep2TokenSymbol) { return TRANSFER_IN_FAILURE_UNBOUND_TOKEN; } - try IBEP2E(transInSyncPkg.contractAddr).balanceOf{gas: MAX_GAS_FOR_CALLING_BEP2E}(address(this)) returns (uint256 actualBalance) { - if (actualBalance < transInSyncPkg.amount) { - return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; - } - } catch Error(string memory) { - return TRANSFER_IN_FAILURE_UNKNOWN; - } catch (bytes memory) { - return TRANSFER_IN_FAILURE_UNKNOWN; + uint256 actualBalance = IBEP2E(transInSyncPkg.contractAddr).balanceOf{gas: MAX_GAS_FOR_CALLING_BEP2E}(address(this)); + if (actualBalance < transInSyncPkg.amount) { + return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - try IBEP2E(transInSyncPkg.contractAddr).transfer{gas: MAX_GAS_FOR_CALLING_BEP2E}(transInSyncPkg.recipient, transInSyncPkg.amount) returns (bool success) { - if (success){ - emit transferInSuccess(transInSyncPkg.contractAddr, transInSyncPkg.recipient, transInSyncPkg.amount); - return TRANSFER_IN_SUCCESS; - } else { - return TRANSFER_IN_FAILURE_UNKNOWN; - } - } catch Error(string memory) { - return TRANSFER_IN_FAILURE_UNKNOWN; - } catch (bytes memory) { + bool success = IBEP2E(transInSyncPkg.contractAddr).transfer{gas: MAX_GAS_FOR_CALLING_BEP2E}(transInSyncPkg.recipient, transInSyncPkg.amount); + if (success){ + emit transferInSuccess(transInSyncPkg.contractAddr, transInSyncPkg.recipient, transInSyncPkg.amount); + return TRANSFER_IN_SUCCESS; + } else { return TRANSFER_IN_FAILURE_UNKNOWN; } } @@ -408,9 +402,9 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } else if ( idx == 2 ) { RLPDecode.RLPItem[] memory list = iter.next().toList(); - transOutAckPkg.refundAddrs = new address payable[](list.length); + transOutAckPkg.refundAddrs = new address[](list.length); for(uint256 index=0; index BEP2_TOKEN_DECIMALS) { + return amount.mul(10**(bep2eTokenDecimals-BEP2_TOKEN_DECIMALS)); + } + return amount.div(10**(BEP2_TOKEN_DECIMALS-bep2eTokenDecimals)); + } + function getBoundContract(string memory bep2Symbol) public view returns (address) { bytes32 bep2TokenSymbol = bep2TokenSymbolConvert(bep2Symbol); return bep2SymbolToContractAddr[bep2TokenSymbol]; @@ -660,7 +705,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint8 bep2SymbolLength = 0; for (uint8 j = 0; j < 32; j++) { if (bep2SymbolBytes[j] != 0) { - bep2SymbolLength++; + bep2SymbolLength++; } else { break; } diff --git a/contracts/test/MiniToken.sol b/contracts/test/MiniToken.sol new file mode 100644 index 000000000..5c0dfa158 --- /dev/null +++ b/contracts/test/MiniToken.sol @@ -0,0 +1,241 @@ +pragma solidity 0.6.4; + +import "../interface/IBEP2E.sol"; +import "openzeppelin-solidity/contracts/GSN/Context.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "openzeppelin-solidity/contracts/access/Ownable.sol"; + +contract MiniToken is Context, IBEP2E, Ownable { + using SafeMath for uint256; + + mapping (address => uint256) private _balances; + + mapping (address => mapping (address => uint256)) private _allowances; + + uint256 private _totalSupply; + uint8 public _decimals; + string public _symbol; + string public _name; + + constructor() public { + _name = "XYZ token"; + _symbol = "XYZ"; + _decimals = 18; + _totalSupply = 10000000000000000000000; + _balances[msg.sender] = _totalSupply; + + emit Transfer(address(0), msg.sender, _totalSupply); + } + + /** + * @dev Returns the bep token owner. + */ + function getOwner() external override view returns (address) { + return owner(); + } + + /** + * @dev Returns the token decimals. + */ + function decimals() external override view returns (uint256) { + return _decimals; + } + + /** + * @dev Returns the contract owner. + */ + function symbol() external override view returns (string memory) { + return _symbol; + } + + /** + * @dev See {BEP2E-totalSupply}. + */ + function totalSupply() external override view returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {BEP2E-balanceOf}. + */ + function balanceOf(address account) external override view returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {BEP2E-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) external override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {BEP2E-allowance}. + */ + function allowance(address owner, address spender) external override view returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {BEP2E-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) external override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {BEP2E-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {BEP2E}; + * + * Requirements: + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for `sender`'s tokens of at least + * `amount`. + */ + function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { + _transfer(sender, recipient, amount); + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP2E: transfer amount exceeds allowance")); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP2E-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {BEP2E-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "BEP2E: decreased allowance below zero")); + return true; + } + + /** + * @dev Moves tokens `amount` from `sender` to `recipient`. + * + * This is internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer(address sender, address recipient, uint256 amount) internal { + require(sender != address(0), "BEP2E: transfer from the zero address"); + require(recipient != address(0), "BEP2E: transfer to the zero address"); + + _balances[sender] = _balances[sender].sub(amount, "BEP2E: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); + emit Transfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements + * + * - `to` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal { + require(account != address(0), "BEP2E: mint to the zero address"); + + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal { + require(account != address(0), "BEP2E: burn from the zero address"); + + _balances[account] = _balances[account].sub(amount, "BEP2E: burn amount exceeds balance"); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. + * + * This is internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve(address owner, address spender, uint256 amount) internal { + require(owner != address(0), "BEP2E: approve from the zero address"); + require(spender != address(0), "BEP2E: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`.`amount` is then deducted + * from the caller's allowance. + * + * See {_burn} and {_approve}. + */ + function _burnFrom(address account, uint256 amount) internal { + _burn(account, amount); + _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "BEP2E: burn amount exceeds allowance")); + } +} \ No newline at end of file diff --git a/genesis.json b/genesis.json index d235d74ce..88edd279d 100644 --- a/genesis.json +++ b/genesis.json @@ -45,7 +45,7 @@ }, "0x0000000000000000000000000000000000001004": { "balance": "180000000000000000000000000", - "code": "0x60806040526004361061038c5760003560e01c80639a854bbd116101dc578063c8509d8111610102578063ece9d81e116100a0578063fc3e59081161006f578063fc3e59081461074a578063fd6a687914610e6f578063fe3a2af51461061c578063ff9c00271461088b5761038c565b8063ece9d81e1461088b578063f014847214610e12578063f9a2bbc714610e27578063fc1a598f14610e3c5761038c565b8063dc6f5e90116100dc578063dc6f5e901461074a578063dc927faf14610de8578063e1c7392a14610dfd578063ebf71d53146104f95761038c565b8063c8509d8114610ce3578063cc12eabc1461088b578063d117a11014610d685761038c565b8063a7c9f02d1161017a578063b770186111610149578063b770186114610ca4578063b9fd21e314610cb9578063c3dc4d9a146104e4578063c81b166214610cce5761038c565b8063a7c9f02d1461074a578063aa7415f514610b7e578063ab51bb9614610bc4578063ac43175114610bd95761038c565b8063a1a11bf5116101b6578063a1a11bf514610b21578063a496fba21461061c578063a5cd588b14610b36578063a78abc1614610b695761038c565b80639a854bbd14610abe5780639a99b4f014610ad35780639dc0926214610b0c5761038c565b806361368475116102c157806372c4e0861161025f578063831d65d11161022e578063831d65d114610a225780638b87b21f146104e457806395b9ad261461074a57806396713da914610aa95761038c565b806372c4e086146108b557806377d9dae8146109595780637942fd0514610a0d5780637d078e13146104e45761038c565b80636e0565201161029b5780636e0565201461075f5780636e47b4821461087657806370fd5bad1461088b57806371d30863146108a05761038c565b806361368475146103915780636b3f1307146106825780636bc2ecdb1461074a5761038c565b806343756e5c1161032e5780634bf6c882116103085780634bf6c8821461039157806350432d32146106315780635170639c1461065857806351e806721461066d5761038c565b806343756e5c146105db578063493279b1146105f05780634a6888181461061c5761038c565b806323996b531161036a57806323996b53146104e45780632ab36d83146104f95780633d7132231461050e5780633dffc387146104e45761038c565b8063077b8f35146103915780630bee7a67146103bc5780631182b875146103ea575b600080fd5b34801561039d57600080fd5b506103a6610e84565b6040805160ff9092168252519081900360200190f35b3480156103c857600080fd5b506103d1610e89565b6040805163ffffffff9092168252519081900360200190f35b3480156103f657600080fd5b5061046f6004803603604081101561040d57600080fd5b60ff8235169190810190604081016020820135600160201b81111561043157600080fd5b82018360208201111561044357600080fd5b803590602001918460018302840111600160201b8311171561046457600080fd5b509092509050610e8e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104a9578181015183820152602001610491565b50505050905090810190601f1680156104d65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104f057600080fd5b506103a6611007565b34801561050557600080fd5b506103a661100c565b34801561051a57600080fd5b506105bf6004803603602081101561053157600080fd5b810190602081018135600160201b81111561054b57600080fd5b82018360208201111561055d57600080fd5b803590602001918460018302840111600160201b8311171561057e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611011945050505050565b604080516001600160a01b039092168252519081900360200190f35b3480156105e757600080fd5b506105bf61103e565b3480156105fc57600080fd5b50610605611044565b6040805161ffff9092168252519081900360200190f35b34801561062857600080fd5b506103a6611049565b34801561063d57600080fd5b5061064661104e565b60408051918252519081900360200190f35b34801561066457600080fd5b50610646611059565b34801561067957600080fd5b506105bf61105f565b6107366004803603604081101561069857600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156106c257600080fd5b8201836020820111156106d457600080fd5b803590602001918460018302840111600160201b831117156106f557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611065945050505050565b604080519115158252519081900360200190f35b34801561075657600080fd5b506103a6611b52565b6107366004803603608081101561077557600080fd5b810190602081018135600160201b81111561078f57600080fd5b8201836020820111156107a157600080fd5b803590602001918460208302840111600160201b831117156107c257600080fd5b919390929091602081019035600160201b8111156107df57600080fd5b8201836020820111156107f157600080fd5b803590602001918460208302840111600160201b8311171561081257600080fd5b919390929091602081019035600160201b81111561082f57600080fd5b82018360208201111561084157600080fd5b803590602001918460208302840111600160201b8311171561086257600080fd5b9193509150356001600160401b0316611b57565b34801561088257600080fd5b506105bf611fe0565b34801561089757600080fd5b506103a6611fe6565b3480156108ac57600080fd5b50610646611feb565b610736600480360360208110156108cb57600080fd5b810190602081018135600160201b8111156108e557600080fd5b8201836020820111156108f757600080fd5b803590602001918460018302840111600160201b8311171561091857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611ff1945050505050565b6107366004803603604081101561096f57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561099957600080fd5b8201836020820111156109ab57600080fd5b803590602001918460018302840111600160201b831117156109cc57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122ec945050505050565b348015610a1957600080fd5b506103a66126a4565b348015610a2e57600080fd5b50610aa760048036036040811015610a4557600080fd5b60ff8235169190810190604081016020820135600160201b811115610a6957600080fd5b820183602082011115610a7b57600080fd5b803590602001918460018302840111600160201b83111715610a9c57600080fd5b5090925090506126a9565b005b348015610ab557600080fd5b506103a66127f2565b348015610aca57600080fd5b506106466127f7565b348015610adf57600080fd5b5061064660048036036040811015610af657600080fd5b506001600160a01b038135169060200135612803565b348015610b1857600080fd5b506105bf612924565b348015610b2d57600080fd5b506105bf61292a565b348015610b4257600080fd5b5061064660048036036020811015610b5957600080fd5b50356001600160a01b0316612930565b348015610b7557600080fd5b50610736612942565b61073660048036036080811015610b9457600080fd5b5080356001600160a01b0390811691602081013590911690604081013590606001356001600160401b031661294b565b348015610bd057600080fd5b506103d1611049565b348015610be557600080fd5b50610aa760048036036040811015610bfc57600080fd5b810190602081018135600160201b811115610c1657600080fd5b820183602082011115610c2857600080fd5b803590602001918460018302840111600160201b83111715610c4957600080fd5b919390929091602081019035600160201b811115610c6657600080fd5b820183602082011115610c7857600080fd5b803590602001918460018302840111600160201b83111715610c9957600080fd5b509092509050612f78565b348015610cb057600080fd5b506106466131e7565b348015610cc557600080fd5b506106466131ed565b348015610cda57600080fd5b506105bf6131f7565b348015610cef57600080fd5b50610aa760048036036040811015610d0657600080fd5b60ff8235169190810190604081016020820135600160201b811115610d2a57600080fd5b820183602082011115610d3c57600080fd5b803590602001918460018302840111600160201b83111715610d5d57600080fd5b5090925090506131fd565b348015610d7457600080fd5b50610d9260048036036020811015610d8b57600080fd5b5035613282565b6040805160ff988916815260208101979097526001600160a01b03909516868601526060860193909352608085019190915290931660a08301526001600160401b0390921660c082015290519081900360e00190f35b348015610df457600080fd5b506105bf6132d8565b348015610e0957600080fd5b50610aa76132de565b348015610e1e57600080fd5b506103a6613352565b348015610e3357600080fd5b506105bf613357565b348015610e4857600080fd5b5061046f60048036036020811015610e5f57600080fd5b50356001600160a01b031661335d565b348015610e7b57600080fd5b506105bf613484565b600881565b606481565b60005460609060ff16610ed6576040805162461bcd60e51b81526020600482015260196024820152600080516020615a9f833981519152604482015290519081900360640190fd5b3361200014610f165760405162461bcd60e51b815260040180806020018281038252602f815260200180615a43602f913960400191505060405180910390fd5b60ff841660011415610f6857610f6183838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061348a92505050565b9050611000565b60ff841660021415610fb357610f6183838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506136c892505050565b6040805162461bcd60e51b815260206004820152601960248201527f756e7265636f676e697a65642073796e63207061636b61676500000000000000604482015290519081900360640190fd5b9392505050565b600181565b600481565b60008061101d836137ec565b6000908152600560205260409020546001600160a01b03169150505b919050565b61100181565b606081565b600081565b662386f26fc1000081565b60015490565b61200081565b600080611071836137ec565b905061107b61557b565b50600081815260026020818152604092839020835160e081018552815460ff90811682526001830154938201849052938201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c0830152611140576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b600061115d826080015183606001516137f390919063ffffffff16565b905081604001516001600160a01b0316866001600160a01b0316146111b35760405162461bcd60e51b81526004018080602001828103825260458152602001806157f36045913960600191505060405180910390fd5b336001600160a01b0316866001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b1580156111f657600080fd5b505afa15801561120a573d6000803e3d6000fd5b505050506040513d602081101561122057600080fd5b50516001600160a01b0316146112675760405162461bcd60e51b815260040180806020018281038252602e815260200180615955602e913960400191505060405180910390fd5b60408051636eb1769f60e11b8152336004820152306024820152905182916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b1580156112b657600080fd5b505afa1580156112ca573d6000803e3d6000fd5b505050506040513d60208110156112e057600080fd5b50511461131e5760405162461bcd60e51b81526004018080602001828103825260368152602001806159d26036913960400191505060405180910390fd5b600154341461135e5760405162461bcd60e51b81526004018080602001828103825260238152602001806157166023913960400191505060405180910390fd5b428260c001516001600160401b031610156114f55760008381526002602081905260408220805460ff191681556001810183905590810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556113cd6155b7565b50604080518082019091526001808252602082018590526120009063f7a251d7906113f784613835565b60015461140f906402540be40063ffffffff6138bf16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561146d578181015183820152602001611455565b50505050905090810190601f16801561149a5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156114bb57600080fd5b505af11580156114cf573d6000803e3d6000fd5b505050506040513d60208110156114e557600080fd5b5060009550611b4c945050505050565b6000866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561153057600080fd5b505afa158015611544573d6000803e3d6000fd5b505050506040513d602081101561155a57600080fd5b5051604080516395d89b4160e01b815290519192506060916001600160a01b038a16916395d89b41916004808301926000929190829003018186803b1580156115a257600080fd5b505afa1580156115b6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156115df57600080fd5b8101908080516040519392919084600160201b8211156115fe57600080fd5b90830190602082018581111561161357600080fd5b8251600160201b81118282018810171561162c57600080fd5b82525081516020918201929091019080838360005b83811015611659578181015183820152602001611641565b50505050905090810190601f1680156116865780820380516001836020036101000a031916815260200191505b5060405250505090506116998186613901565b15806116c157506020808501516000908152600590915260409020546001600160a01b031615155b806116e557506040808501516001600160a01b031660009081526004602052205415155b8061175c5750836060015184604001516001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561172d57600080fd5b505afa158015611741573d6000803e3d6000fd5b505050506040513d602081101561175757600080fd5b505114155b8061176e57508360a0015160ff168214155b156118f65760008581526002602081905260408220805460ff191681556001810183905590810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556117cd6155b7565b5060408051808201909152600281526020810186905261200063f7a251d760016117f684613835565b60015461180e906402540be40063ffffffff6138bf16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561186c578181015183820152602001611854565b50505050905090810190601f1680156118995780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156118ba57600080fd5b505af11580156118ce573d6000803e3d6000fd5b505050506040513d60208110156118e457600080fd5b5060009750611b4c9650505050505050565b604080516323b872dd60e01b81523360048201523060248201526044810185905290516001600160a01b038a16916323b872dd9160648083019260209291908290030181600087803b15801561194b57600080fd5b505af115801561195f573d6000803e3d6000fd5b505050506040513d602081101561197557600080fd5b505060208481018051604080880180516001600160a01b03908116600090815260048088528482209590955560a08b0151835183168252600380895285832060ff90921690915592519551815260058088528482208054979093166001600160a01b0319978816179092558b8152600296879052928320805460ff1916815560018101849055958601805490951690945584018190559083015501805468ffffffffffffffffff19169055611a286155b7565b5060408051808201909152600081526020810186905261200063f7a251d76001611a5184613835565b600154611a69906402540be40063ffffffff6138bf16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611ac7578181015183820152602001611aaf565b50505050905090810190601f168015611af45780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015611b1557600080fd5b505af1158015611b29573d6000803e3d6000fd5b505050506040513d6020811015611b3f57600080fd5b5060019750505050505050505b92915050565b600381565b6000868514611b975760405162461bcd60e51b815260040180806020018281038252603b815260200180615a08603b913960400191505060405180910390fd5b868314611bd55760405162461bcd60e51b815260040180806020018281038252603f8152602001806158da603f913960400191505060405180910390fd5b42607801826001600160401b03161015611c205760405162461bcd60e51b815260040180806020018281038252602481526020018061579a6024913960400191505060405180910390fd5b846000805b82811015611c5c57611c52898983818110611c3c57fe5b90506020020135836139df90919063ffffffff16565b9150600101611c25565b50606082604051908082528060200260200182016040528015611c89578160200160208202803683370190505b50905060005b838160ff161015611d5f576402540be4008a8a8360ff16818110611caf57fe5b9050602002013581611cbd57fe5b0615611d10576040805162461bcd60e51b815260206004820152601760248201527f696e76616c6964207472616e7366657220616d6f756e74000000000000000000604482015290519081900360640190fd5b611d3d6402540be4008b8b8460ff16818110611d2857fe5b905060200201356138bf90919063ffffffff16565b828260ff1681518110611d4c57fe5b6020908102919091010152600101611c8f565b50600154611d8490611d77908563ffffffff613a3916565b839063ffffffff6139df16565b3414611dc15760405162461bcd60e51b815260040180806020018281038252604c815260200180615869604c913960600191505060405180910390fd5b611dc96155ce565b6040518060c001604052806221272160e91b60001b815260200160006001600160a01b031681526020018381526020018d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208b810282810182019093528b82529283019290918c918c9182918501908490808284376000920191909152505050908252506001600160401b038816602090910152905061200063f7a251d76003611e8c84613a92565b611eb66402540be400611eaa8a600154613a3990919063ffffffff16565b9063ffffffff6138bf16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611f14578181015183820152602001611efc565b50505050905090810190601f168015611f415780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015611f6257600080fd5b505af1158015611f76573d6000803e3d6000fd5b505050506040513d6020811015611f8c57600080fd5b5050604080516000815233602082015280820185905290517fe9750a449d7c7d8f872b7ee10d75b95a948bc425b3c2d52052587665742c81ec9181900360600190a15060019b9a5050505050505050505050565b61100581565b600281565b60015481565b600080611ffd836137ec565b905061200761557b565b50600081815260026020818152604092839020835160e081018552815460ff90811682526001830154938201849052938201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526120cc576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b428160c001516001600160401b03161061212d576040805162461bcd60e51b815260206004820152601b60248201527f62696e642072657175657374206973206e6f7420657870697265640000000000604482015290519081900360640190fd5b600154341461216d5760405162461bcd60e51b81526004018080602001828103825260278152602001806157736027913960400191505060405180910390fd5b60008281526002602081905260408220805460ff191681556001810183905590810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556121c76155b7565b50604080518082019091526001808252602082018490526120009063f7a251d7906121f184613835565b600154612209906402540be40063ffffffff6138bf16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561226757818101518382015260200161224f565b50505050905090810190601f1680156122945780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156122b557600080fd5b505af11580156122c9573d6000803e3d6000fd5b505050506040513d60208110156122df57600080fd5b5060019695505050505050565b6000806122f8836137ec565b905061230261557b565b50600081815260026020818152604092839020835160e081018552815460ff90811682526001830154938201849052938201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526123c7576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b80604001516001600160a01b0316856001600160a01b03161461241b5760405162461bcd60e51b81526004018080602001828103825260458152602001806157f36045913960600191505060405180910390fd5b336001600160a01b0316856001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b15801561245e57600080fd5b505afa158015612472573d6000803e3d6000fd5b505050506040513d602081101561248857600080fd5b50516001600160a01b0316146124e5576040805162461bcd60e51b815260206004820152601b60248201527f6f6e6c79206265703265206f776e65722063616e2072656a6563740000000000604482015290519081900360640190fd5b60015434146125255760405162461bcd60e51b81526004018080602001828103825260278152602001806157736027913960400191505060405180910390fd5b60008281526002602081905260408220805460ff191681556001810183905590810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff1916905561257f6155b7565b5060408051808201909152600381526020810183905261200063f7a251d760016125a884613835565b6001546125c0906402540be40063ffffffff6138bf16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561261e578181015183820152602001612606565b50505050905090810190601f16801561264b5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561266c57600080fd5b505af1158015612680573d6000803e3d6000fd5b505050506040513d602081101561269657600080fd5b506001979650505050505050565b600b81565b60005460ff166126ee576040805162461bcd60e51b81526020600482015260196024820152600080516020615a9f833981519152604482015290519081900360640190fd5b336120001461272e5760405162461bcd60e51b815260040180806020018281038252602f815260200180615a43602f913960400191505060405180910390fd5b60ff83166003141561277e5761277982828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d4c92505050565b6127ed565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a15b505050565b600981565b677ce66c50e284000081565b6000805460ff16612849576040805162461bcd60e51b81526020600482015260196024820152600080516020615a9f833981519152604482015290519081900360640190fd5b33611005146128895760405162461bcd60e51b815260040180806020018281038252602f8152602001806156e7602f913960400191505060405180910390fd5b6000478310612898574761289a565b825b90508015611000576040516001600160a01b0385169082156108fc029083906000818181858888f193505050501580156128d8573d6000803e3d6000fd5b50604080516001600160a01b03861681526020810183905281517ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0929181900390910190a19392505050565b61100781565b61100681565b60036020526000908152604090205481565b60005460ff1681565b600042607801826001600160401b031610156129985760405162461bcd60e51b815260040180806020018281038252602481526020018061579a6024913960400191505060405180910390fd5b6000806001600160a01b038716612a63576402540be4008506156129ed5760405162461bcd60e51b815260040180806020018281038252603c815260200180615919603c913960400191505060405180910390fd5b600154612a0190869063ffffffff6139df16565b3414612a3e5760405162461bcd60e51b815260040180806020018281038252604c815260200180615869604c913960600191505060405180910390fd5b612a53856402540be40063ffffffff6138bf16565b6221272160e91b92509050612d02565b6001600160a01b038716600090815260046020526040902054915081612aba5760405162461bcd60e51b81526004018080602001828103825260318152602001806158386031913960400191505060405180910390fd5b6001543414612afa5760405162461bcd60e51b815260040180806020018281038252602d815260200180615a72602d913960400191505060405180910390fd5b6001600160a01b038716600090815260036020526040902054600881111580612b425750600881118015612b425750612b40866007198301600a0a63ffffffff61422216565b155b612b7d5760405162461bcd60e51b815260040180806020018281038252603c815260200180615919603c913960400191505060405180910390fd5b612b878682614264565b9150612b92836142a4565b15612bda576305f5e100821015612bda5760405162461bcd60e51b815260040180806020018281038252603a815260200180615739603a913960400191505060405180910390fd5b600881101580612bf45750600881108015612bf457508582115b612c2f5760405162461bcd60e51b81526004018080602001828103825260258152602001806158b56025913960400191505060405180910390fd5b677ce66c50e2840000821115612c765760405162461bcd60e51b81526004018080602001828103825260358152602001806157be6035913960400191505060405180910390fd5b604080516323b872dd60e01b81523360048201523060248201526044810188905290516001600160a01b038a16916323b872dd9160648083019260209291908290030181600087803b158015612ccb57600080fd5b505af1158015612cdf573d6000803e3d6000fd5b505050506040513d6020811015612cf557600080fd5b5051612d0057600080fd5b505b612d0a6155ce565b6040805160c0810182528481526001600160a01b038a16602082015281516001808252818401845291928301918160200160208202803683375050508152604080516001808252818301909252602092830192909190808301908036833750505081526040805160018082528183019092526020928301929091908083019080368337019050508152602001866001600160401b03168152509050818160400151600081518110612db757fe5b602002602001018181525050868160600151600081518110612dd557fe5b60200260200101906001600160a01b031690816001600160a01b031681525050338160800151600081518110612e0757fe5b6001600160a01b039092166020928302919091019091015261200063f7a251d76003612e3284613a92565b600154612e4a906402540be40063ffffffff6138bf16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015612ea8578181015183820152602001612e90565b50505050905090810190601f168015612ed55780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015612ef657600080fd5b505af1158015612f0a573d6000803e3d6000fd5b505050506040513d6020811015612f2057600080fd5b5050604080516001600160a01b038a16815233602082015280820188905290517fe9750a449d7c7d8f872b7ee10d75b95a948bc425b3c2d52052587665742c81ec9181900360600190a1506001979650505050505050565b3361100714612fb85760405162461bcd60e51b815260040180806020018281038252602e8152602001806159a4602e913960400191505060405180910390fd5b6020811461300d576040805162461bcd60e51b815260206004820152601b60248201527f65787065637465642076616c7565206c656e6774682069732033320000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152939450606093925086915085908190840183828082843760009201919091525050505060208301519091506772656c617946656560c01b811415613115576020820151670de0b6b3a764000081111580156130bc57506402540be4008106155b61310d576040805162461bcd60e51b815260206004820152601960248201527f7468652072656c6179466565206f7574206f662072616e676500000000000000604482015290519081900360640190fd5b600155613152565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b61c35081565b6221272160e91b81565b61100281565b60005460ff16613242576040805162461bcd60e51b81526020600482015260196024820152600080516020615a9f833981519152604482015290519081900360640190fd5b336120001461277e5760405162461bcd60e51b815260040180806020018281038252602f815260200180615a43602f913960400191505060405180910390fd5b600260208190526000918252604090912080546001820154928201546003830154600484015460059094015460ff93841695946001600160a01b039093169391929181169061010090046001600160401b031687565b61100381565b60005460ff1615613336576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b662386f26fc1000060019081556000805460ff19169091179055565b600581565b61100081565b6001600160a01b03811660009081526004602090815260409182902054825182815280840190935260609290918391906020820181803683375050506020810183905290506000805b60208160ff1610156133ed57828160ff16815181106133c157fe5b01602001516001600160f81b031916156133e0576001909101906133e5565b6133ed565b6001016133a6565b5060608160ff166040519080825280601f01601f19166020018201604052801561341e576020820181803683370190505b50905060005b8260ff168160ff16101561347a57838160ff168151811061344157fe5b602001015160f81c60f81b828260ff168151811061345b57fe5b60200101906001600160f81b031916908160001a905350600101613424565b5095945050505050565b61100481565b60005460609060ff166134d2576040805162461bcd60e51b81526020600482015260196024820152600080516020615a9f833981519152604482015290519081900360640190fd5b6134da61557b565b60006134e5846143aa565b915091508061353b576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b815160ff166135ef576020828101805160009081526002928390526040908190208551815460ff1990811660ff928316178355935160018301559186015193810180546001600160a01b0319166001600160a01b0390951694909417909355606085015160038401556080850151600484015560a08501516005909301805460c08701519316939091169290921768ffffffffffffffff0019166101006001600160401b03909216919091021790556136ad565b815160ff1660011415613660576020808301516000908152600590915260409020546001600160a01b0316801561365a576001600160a01b03811660009081526004602090815260408083208390558582015183526005909152902080546001600160a01b03191690555b506136ad565b6040805162461bcd60e51b815260206004820152601960248201527f756e7265636f676e697a65642062696e64207061636b61676500000000000000604482015290519081900360640190fd5b60408051600080825260208201909252905b50949350505050565b60606136d2615619565b60006136dd846144fb565b9150915080613733576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b600061373e83614614565b905063ffffffff8116156137d2576040808401516020808601516001600160a01b031660009081526003909152918220546137799190614264565b905061378361564e565b60405180608001604052808660000151815260200183815260200186608001516001600160a01b031681526020018463ffffffff1681525090506137c681614a29565b95505050505050611039565b505060408051600081526020810190915291506110399050565b6020015190565b600061100083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614af1565b6040805160028082526060828101909352829190816020015b606081526020019060019003908161384e57505083519091506138769063ffffffff16614b88565b8160008151811061388357fe5b602002602001018190525061389e836020015160001c614b88565b816001815181106138ab57fe5b602002602001018190525061100081614b9b565b600061100083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614bf8565b8151600090839060081080613917575080516003115b15613926576000915050611b4c565b6040805160208082528183019092526060916020820181803683370190505090508360208201528082518151811061395a57fe5b6020910101516001600160f81b031916602d60f81b1461397f57600092505050611b4c565b600160005b835181101561347a5782818151811061399957fe5b602001015160f81c60f81b6001600160f81b0319168482815181106139ba57fe5b01602001516001600160f81b031916146139d7576000915061347a565b600101613984565b600082820183811015611000576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082613a4857506000611b4c565b82820282848281613a5557fe5b04146110005760405162461bcd60e51b81526004018080602001828103825260218152602001806159836021913960400191505060405180910390fd5b60408051600680825260e08201909252606091829190816020015b6060815260200190600190039081613aad5750508351909150613acf90614b88565b81600081518110613adc57fe5b6020026020010181905250613afd83602001516001600160a01b0316614c5d565b81600181518110613b0a57fe5b602002602001018190525060008360400151519050606081604051908082528060200260200182016040528015613b5557816020015b6060815260200190600190039081613b405790505b50905060005b82811015613ba257613b8386604001518281518110613b7657fe5b6020026020010151614b88565b828281518110613b8f57fe5b6020908102919091010152600101613b5b565b50613bac81614b9b565b83600281518110613bb957fe5b6020026020010181905250606082604051908082528060200260200182016040528015613bfa57816020015b6060815260200190600190039081613be55790505b50905060005b83811015613c5057613c3187606001518281518110613c1b57fe5b60200260200101516001600160a01b0316614c5d565b828281518110613c3d57fe5b6020908102919091010152600101613c00565b50613c5a81614b9b565b84600381518110613c6757fe5b6020026020010181905250606083604051908082528060200260200182016040528015613ca857816020015b6060815260200190600190039081613c935790505b50905060005b84811015613ce857613cc988608001518281518110613c1b57fe5b828281518110613cd557fe5b6020908102919091010152600101613cae565b50613cf281614b9b565b85600481518110613cff57fe5b6020026020010181905250613d208760a001516001600160401b0316614b88565b85600581518110613d2d57fe5b6020026020010181905250613d4185614b9b565b979650505050505050565b8051613d575761421f565b613d5f615675565b6000613d6a83614c80565b9150915080613d7a57505061421f565b81516001600160a01b0316613f415760005b826020015151811015613f3b5782604001518181518110613da957fe5b60200260200101516001600160a01b03166108fc84602001518381518110613dcd57fe5b60200260200101519081150290604051600060405180830381858888f19350505050613e95577f1ea8ad5a464cfa84623ec8a881307f46a40b76b3fb8947f39fabcc52471474aa836000015184604001518381518110613e2957fe5b602002602001015185602001518481518110613e4157fe5b602002602001015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a1613f33565b7fd75a89530cbec0a9eed0b88a6f7eb726de5d1c5c234cf1e260dfcf921cdc61c3836000015184604001518381518110613ecb57fe5b602002602001015185602001518481518110613ee357fe5b602002602001015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15b600101613d8c565b506127ed565b60005b82602001515181101561421b5782600001516001600160a01b031663a9059cbb61c35085604001518481518110613f7757fe5b602002602001015186602001518581518110613f8f57fe5b60200260200101516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015613fe657600080fd5b5087f19350505050801561400c57506040513d602081101561400757600080fd5b505160015b6141d7576040516000815260443d1015614028575060006140c3565b60046000803e60005160e01c6308c379a081146140495760009150506140c3565b60043d036004833e81513d60248201116001600160401b0382111715614074576000925050506140c3565b80830180516001600160401b038111156140955760009450505050506140c3565b8060208301013d86018111156140b3576000955050505050506140c3565b601f01601f191660405250925050505b806140ce5750614171565b7f1ea8ad5a464cfa84623ec8a881307f46a40b76b3fb8947f39fabcc52471474aa84600001518560400151848151811061410457fe5b60200260200101518660200151858151811061411c57fe5b602002602001015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a150614213565b3d80801561419b576040519150601f19603f3d011682016040523d82523d6000602084013e6141a0565b606091505b507f1ea8ad5a464cfa84623ec8a881307f46a40b76b3fb8947f39fabcc52471474aa84600001518560400151848151811061410457fe5b80156140ce577fd75a89530cbec0a9eed0b88a6f7eb726de5d1c5c234cf1e260dfcf921cdc61c384600001518560400151848151811061410457fe5b600101613f44565b5050505b50565b600061100083836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250614e4b565b6000600882111561428d57614286836007198401600a0a63ffffffff6138bf16565b9050611b4c565b611000836008849003600a0a63ffffffff613a3916565b604080516020808252818301909252600091606091906020820181803683375050506020810184905290506000805b60208160ff16101561431a57828160ff16815181106142ee57fe5b01602001516001600160f81b0319161561430d57600190910190614312565b61431a565b6001016142d3565b50600860ff8216101561433257600092505050611039565b816005820360ff168151811061434457fe5b6020910101516001600160f81b031916602d60f81b1461436957600092505050611039565b816001820360ff168151811061437b57fe5b6020910101516001600160f81b031916604d60f81b146143a057600092505050611039565b5060019392505050565b6143b261557b565b60006143bc61557b565b6143c46156ac565b6143d56143d086614ead565b614ed2565b90506000805b6143e483614f1c565b156144ee5780614409576143ff6143fa84614f3d565b614f8b565b60ff1684526144e6565b80600114156144285761441e6143fa84614f3d565b60208501526144e6565b80600214156144555761444261443d84614f3d565b614fe9565b6001600160a01b031660408501526144e6565b80600314156144745761446a6143fa84614f3d565b60608501526144e6565b8060041415614493576144896143fa84614f3d565b60808501526144e6565b80600514156144b5576144a86143fa84614f3d565b60ff1660a08501526144e6565b80600614156144e1576144ca6143fa84614f3d565b6001600160401b031660c0850152600191506144e6565b6144ee565b6001016143db565b5091935090915050915091565b614503615619565b600061450d615619565b6145156156ac565b6145216143d086614ead565b90506000805b61453083614f1c565b156144ee578061454d576145466143fa84614f3d565b845261460c565b80600114156145755761456261443d84614f3d565b6001600160a01b0316602085015261460c565b80600214156145945761458a6143fa84614f3d565b604085015261460c565b80600314156145bc576145a961443d84614f3d565b6001600160a01b0316606085015261460c565b80600414156145e4576145d161443d84614f3d565b6001600160a01b0316608085015261460c565b80600514156144e1576145f96143fa84614f3d565b6001600160401b031660a0850152600191505b600101614527565b60208101516000906001600160a01b0316614715578160a001516001600160401b031642111561464657506001611039565b816040015147101561465a57506003611039565b81606001516001600160a01b03166108fc83604001519081150290604051600060405180830381858888f1935050505061469657506004611039565b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5982602001518360600151846040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a1506000611039565b8160a001516001600160401b031642111561473257506001611039565b81516020808401516001600160a01b03166000908152600490915260409020541461475f57506002611039565b602080830151604080516370a0823160e01b815230600482015290516001600160a01b03909216926370a082319261c350926024808201939291829003018187803b1580156147ad57600080fd5b5086fa935050505080156147d357506040513d60208110156147ce57600080fd5b505160015b6148da576040516000815260443d10156147ef5750600061488a565b60046000803e60005160e01c6308c379a0811461481057600091505061488a565b60043d036004833e81513d60248201116001600160401b038211171561483b5760009250505061488a565b80830180516001600160401b0381111561485c57600094505050505061488a565b8060208301013d860181111561487a5760009550505050505061488a565b601f01601f191660405250925050505b80614895575061489f565b5060059050611039565b3d8080156148c9576040519150601f19603f3d011682016040523d82523d6000602084013e6148ce565b606091505b50600591506110399050565b82604001518110156148f0575060039050611039565b5081602001516001600160a01b031663a9059cbb61c350846060015185604001516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b15801561496057600080fd5b5087f19350505050801561498657506040513d602081101561498157600080fd5b505160015b6149a2576040516000815260443d10156147ef5750600061488a565b8015614895577f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5983602001518460600151856040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060009050611039565b60408051600480825260a08201909252606091829190816020015b6060815260200190600190039081614a445750508351909150614a6690614b88565b81600081518110614a7357fe5b6020026020010181905250614a8b8360200151614b88565b81600181518110614a9857fe5b6020026020010181905250614ab983604001516001600160a01b0316614c5d565b81600281518110614ac657fe5b6020026020010181905250614ae4836060015163ffffffff16614b88565b816003815181106138ab57fe5b60008184841115614b805760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614b45578181015183820152602001614b2d565b50505050905090810190601f168015614b725780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6060611b4c614b9683615003565b6150f3565b604080516000808252602082019092526060915b8351811015614bdf57614bd582858381518110614bc857fe5b6020026020010151615145565b9150600101614baf565b50611000614bf2825160c060ff1661522a565b82615145565b60008183614c475760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b45578181015183820152602001614b2d565b506000838581614c5357fe5b0495945050505050565b60408051600560a21b8318601482015260348101909152606090611000816150f3565b614c88615675565b6000614c92615675565b614c9a6156ac565b614ca66143d086614ead565b90506000805b614cb583614f1c565b156144ee5780614cdb57614ccb61443d84614f3d565b6001600160a01b03168452614e43565b8060011415614d7c576060614cf7614cf285614f3d565b615322565b90508051604051908082528060200260200182016040528015614d24578160200160208202803683370190505b50602086015260005b8151811015614d7557614d52828281518110614d4557fe5b6020026020010151614f8b565b86602001518281518110614d6257fe5b6020908102919091010152600101614d2d565b5050614e43565b8060021415614e1e576060614d93614cf285614f3d565b90508051604051908082528060200260200182016040528015614dc0578160200160208202803683370190505b50604086015260005b8151811015614d7557614dee828281518110614de157fe5b6020026020010151614fe9565b86604001518281518110614dfe57fe5b6001600160a01b0390921660209283029190910190910152600101614dc9565b80600314156144e157614e336143fa84614f3d565b63ffffffff166060850152600191505b600101614cac565b60008183614e9a5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b45578181015183820152602001614b2d565b50828481614ea457fe5b06949350505050565b614eb56156cc565b506040805180820190915281518152602082810190820152919050565b614eda6156ac565b614ee3826153f3565b614eec57600080fd5b6000614efb8360200151615423565b60208085015160408051808201909152868152920190820152915050919050565b6000614f266156cc565b505080518051602091820151919092015191011190565b614f456156cc565b614f4e82614f1c565b614f5757600080fd5b60208201516000614f6782615486565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590614fa057508151602110155b614fa957600080fd5b6000614fb88360200151615423565b835160208086015183018051939450918490039291908310156136bf57506020919091036101000a90049392505050565b8051600090601514614ffa57600080fd5b611b4c82614f8b565b6040805160208082528183019092526060916000918391602082018180368337019050509050836020820152600091505b602082101561506d5780828151811061504957fe5b01602001516001600160f81b031916156150625761506d565b600190910190615034565b6060826020036040519080825280601f01601f19166020018201604052801561509d576020820181803683370190505b50905060005b81518110156136bf5782516001850194849181106150bd57fe5b602001015160f81c60f81b8282815181106150d457fe5b60200101906001600160f81b031916908160001a9053506001016150a3565b6060815160011480156151255750607f60f81b8260008151811061511357fe5b01602001516001600160f81b03191611155b15615131575080611039565b611b4c6151438351608060ff1661522a565b835b60608082518451016040519080825280601f01601f191660200182016040528015615177576020820181803683370190505b5090506000805b85518110156151cd5785818151811061519357fe5b602001015160f81c60f81b8383815181106151aa57fe5b60200101906001600160f81b031916908160001a9053506001918201910161517e565b5060005b8451811015615220578481815181106151e657fe5b602001015160f81c60f81b8383815181106151fd57fe5b60200101906001600160f81b031916908160001a905350600191820191016151d1565b5090949350505050565b606068010000000000000000831061527a576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116152d45782840160f81b816000815181106152b657fe5b60200101906001600160f81b031916908160001a9053509050611b4c565b60606152df85615003565b90508381510160370160f81b826000815181106152f857fe5b60200101906001600160f81b031916908160001a9053506153198282615145565b95945050505050565b606061532d826153f3565b61533657600080fd5b60006153418361551f565b905060608160405190808252806020026020018201604052801561537f57816020015b61536c6156cc565b8152602001906001900390816153645790505b50905060006153918560200151615423565b60208601510190506000805b848110156153e8576153ae83615486565b91506040518060400160405280838152602001848152508482815181106153d157fe5b60209081029190910101529181019160010161539d565b509195945050505050565b805160009061540457506000611039565b6020820151805160001a9060c08210156143a057600092505050611039565b8051600090811a608081101561543d576000915050611039565b60b8811080615458575060c08110801590615458575060f881105b15615467576001915050611039565b60c081101561547b5760b519019050611039565b60f519019050611039565b80516000908190811a60808110156154a15760019150615518565b60b88110156154b657607e1981019150615518565b60c08110156154e35760b78103600185019450806020036101000a85510460018201810193505050615518565b60f88110156154f85760be1981019150615518565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b805160009061553057506000611039565b600080905060006155448460200151615423565b602085015185519181019250015b808210156155725761556382615486565b60019093019290910190615552565b50909392505050565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080518082019091526000808252602082015290565b6040518060c001604052806000801916815260200160006001600160a01b0316815260200160608152602001606081526020016060815260200160006001600160401b031681525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806080016040528060006001600160a01b031681526020016060815260200160608152602001600063ffffffff1681525090565b60405180604001604052806156bf6156cc565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d75737420626520696e63656e746976697a6520636f6e74726163746d73672e76616c756520646f65736e277420657175616c20746f2072656c6179466565466f72206d696e69546f6b656e2c20746865207472616e7366657220616d6f756e74206d757374206e6f74206265206c657373207468616e20316d73672e76616c756520646f65736e277420657175616c20746f2073796e6352656c617946656565787069726554696d65206d7573742062652074776f206d696e75746573206c61746572616d6f756e7420697320746f6f206c617267652c20657863656564206d6178696d756d206265703220746f6b656e20616d6f756e74636f6e74616374206164647265737320646f65736e277420657175616c20746f2074686520636f6e7472616374206164647265737320696e2062696e64207265717565737474686520636f6e747261637420686173206e6f74206265656e20626f756e6420746f20616e79206265703220746f6b656e726563656976656420424e4220616d6f756e7420646f65736e277420657175616c20746f207468652073756d206f66207472616e7366657220616d6f756e7420616e642072656c6179466565616d6f756e7420697320746f6f206c617267652c2075696e74323536206f766572666c6f774c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620726566756e644164647273696e76616c6964207472616e7366657220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6e6f6e6c79206265703265206f776e65722063616e20617070726f766520746869732062696e642072657175657374536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374616c6c6f77616e636520646f65736e277420657175616c20746f2028746f74616c537570706c79202d207065676779416d6f756e74294c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620616d6f756e7473746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374726563656976656420424e4220616d6f756e7420646f65736e277420657175616c20746f2072656c617946656574686520636f6e7472616374206e6f7420696e69742079657400000000000000a264697066735822122005d48b77aed37279e750639a5ecad9a713ad637015e24f6e9659f5bef07bcfcc64736f6c63430006040033" + "code": "0x60806040526004361061038c5760003560e01c80639a854bbd116101dc578063c8509d8111610102578063ece9d81e116100a0578063fc3e59081161006f578063fc3e59081461074a578063fd6a687914610e6f578063fe3a2af51461061c578063ff9c00271461088b5761038c565b8063ece9d81e1461088b578063f014847214610e12578063f9a2bbc714610e27578063fc1a598f14610e3c5761038c565b8063dc6f5e90116100dc578063dc6f5e901461074a578063dc927faf14610de8578063e1c7392a14610dfd578063ebf71d53146104f95761038c565b8063c8509d8114610ce3578063cc12eabc1461088b578063d117a11014610d685761038c565b8063a7c9f02d1161017a578063b770186111610149578063b770186114610ca4578063b9fd21e314610cb9578063c3dc4d9a146104e4578063c81b166214610cce5761038c565b8063a7c9f02d1461074a578063aa7415f514610b7e578063ab51bb9614610bc4578063ac43175114610bd95761038c565b8063a1a11bf5116101b6578063a1a11bf514610b21578063a496fba21461061c578063a5cd588b14610b36578063a78abc1614610b695761038c565b80639a854bbd14610abe5780639a99b4f014610ad35780639dc0926214610b0c5761038c565b806361368475116102c157806372c4e0861161025f578063831d65d11161022e578063831d65d114610a225780638b87b21f146104e457806395b9ad261461074a57806396713da914610aa95761038c565b806372c4e086146108b557806377d9dae8146109595780637942fd0514610a0d5780637d078e13146104e45761038c565b80636e0565201161029b5780636e0565201461075f5780636e47b4821461087657806370fd5bad1461088b57806371d30863146108a05761038c565b806361368475146103915780636b3f1307146106825780636bc2ecdb1461074a5761038c565b806343756e5c1161032e5780634bf6c882116103085780634bf6c8821461039157806350432d32146106315780635170639c1461065857806351e806721461066d5761038c565b806343756e5c146105db578063493279b1146105f05780634a6888181461061c5761038c565b806323996b531161036a57806323996b53146104e45780632ab36d83146104f95780633d7132231461050e5780633dffc387146104e45761038c565b8063077b8f35146103915780630bee7a67146103bc5780631182b875146103ea575b600080fd5b34801561039d57600080fd5b506103a6610e84565b6040805160ff9092168252519081900360200190f35b3480156103c857600080fd5b506103d1610e89565b6040805163ffffffff9092168252519081900360200190f35b3480156103f657600080fd5b5061046f6004803603604081101561040d57600080fd5b60ff8235169190810190604081016020820135600160201b81111561043157600080fd5b82018360208201111561044357600080fd5b803590602001918460018302840111600160201b8311171561046457600080fd5b509092509050610e8e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104a9578181015183820152602001610491565b50505050905090810190601f1680156104d65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104f057600080fd5b506103a6611015565b34801561050557600080fd5b506103a661101a565b34801561051a57600080fd5b506105bf6004803603602081101561053157600080fd5b810190602081018135600160201b81111561054b57600080fd5b82018360208201111561055d57600080fd5b803590602001918460018302840111600160201b8311171561057e57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061101f945050505050565b604080516001600160a01b039092168252519081900360200190f35b3480156105e757600080fd5b506105bf61104c565b3480156105fc57600080fd5b50610605611052565b6040805161ffff9092168252519081900360200190f35b34801561062857600080fd5b506103a6611057565b34801561063d57600080fd5b5061064661105c565b60408051918252519081900360200190f35b34801561066457600080fd5b50610646611067565b34801561067957600080fd5b506105bf61106d565b6107366004803603604081101561069857600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156106c257600080fd5b8201836020820111156106d457600080fd5b803590602001918460018302840111600160201b831117156106f557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611073945050505050565b604080519115158252519081900360200190f35b34801561075657600080fd5b506103a6611b60565b6107366004803603608081101561077557600080fd5b810190602081018135600160201b81111561078f57600080fd5b8201836020820111156107a157600080fd5b803590602001918460208302840111600160201b831117156107c257600080fd5b919390929091602081019035600160201b8111156107df57600080fd5b8201836020820111156107f157600080fd5b803590602001918460208302840111600160201b8311171561081257600080fd5b919390929091602081019035600160201b81111561082f57600080fd5b82018360208201111561084157600080fd5b803590602001918460208302840111600160201b8311171561086257600080fd5b9193509150356001600160401b0316611b65565b34801561088257600080fd5b506105bf611fee565b34801561089757600080fd5b506103a6611ff4565b3480156108ac57600080fd5b50610646611ff9565b610736600480360360208110156108cb57600080fd5b810190602081018135600160201b8111156108e557600080fd5b8201836020820111156108f757600080fd5b803590602001918460018302840111600160201b8311171561091857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611fff945050505050565b6107366004803603604081101561096f57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561099957600080fd5b8201836020820111156109ab57600080fd5b803590602001918460018302840111600160201b831117156109cc57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122fa945050505050565b348015610a1957600080fd5b506103a66126b2565b348015610a2e57600080fd5b50610aa760048036036040811015610a4557600080fd5b60ff8235169190810190604081016020820135600160201b811115610a6957600080fd5b820183602082011115610a7b57600080fd5b803590602001918460018302840111600160201b83111715610a9c57600080fd5b5090925090506126b7565b005b348015610ab557600080fd5b506103a661280e565b348015610aca57600080fd5b50610646612813565b348015610adf57600080fd5b5061064660048036036040811015610af657600080fd5b506001600160a01b03813516906020013561281f565b348015610b1857600080fd5b506105bf61294e565b348015610b2d57600080fd5b506105bf612954565b348015610b4257600080fd5b5061064660048036036020811015610b5957600080fd5b50356001600160a01b031661295a565b348015610b7557600080fd5b5061073661296c565b61073660048036036080811015610b9457600080fd5b5080356001600160a01b0390811691602081013590911690604081013590606001356001600160401b0316612975565b348015610bd057600080fd5b506103d1611057565b348015610be557600080fd5b50610aa760048036036040811015610bfc57600080fd5b810190602081018135600160201b811115610c1657600080fd5b820183602082011115610c2857600080fd5b803590602001918460018302840111600160201b83111715610c4957600080fd5b919390929091602081019035600160201b811115610c6657600080fd5b820183602082011115610c7857600080fd5b803590602001918460018302840111600160201b83111715610c9957600080fd5b509092509050612fa2565b348015610cb057600080fd5b50610646613211565b348015610cc557600080fd5b50610646613217565b348015610cda57600080fd5b506105bf613221565b348015610cef57600080fd5b50610aa760048036036040811015610d0657600080fd5b60ff8235169190810190604081016020820135600160201b811115610d2a57600080fd5b820183602082011115610d3c57600080fd5b803590602001918460018302840111600160201b83111715610d5d57600080fd5b509092509050613227565b348015610d7457600080fd5b50610d9260048036036020811015610d8b57600080fd5b5035613305565b6040805160ff988916815260208101979097526001600160a01b03909516868601526060860193909352608085019190915290931660a08301526001600160401b0390921660c082015290519081900360e00190f35b348015610df457600080fd5b506105bf61335b565b348015610e0957600080fd5b50610aa7613361565b348015610e1e57600080fd5b506103a66133d5565b348015610e3357600080fd5b506105bf6133da565b348015610e4857600080fd5b5061046f60048036036020811015610e5f57600080fd5b50356001600160a01b03166133e0565b348015610e7b57600080fd5b506105bf613507565b600881565b606481565b60005460609060ff16610ee4576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b3361200014610f245760405162461bcd60e51b815260040180806020018281038252602f815260200180615d52602f913960400191505060405180910390fd5b60ff841660011415610f7657610f6f83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061350d92505050565b905061100e565b60ff841660021415610fc157610f6f83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061370592505050565b6040805162461bcd60e51b815260206004820152601960248201527f756e7265636f676e697a65642073796e63207061636b61676500000000000000604482015290519081900360640190fd5b9392505050565b600181565b600481565b60008061102b83613829565b6000908152600560205260409020546001600160a01b03169150505b919050565b61100181565b606081565b600081565b662386f26fc1000081565b60015490565b61200081565b60008061107f83613829565b9050611089615841565b50600081815260026020818152604092839020835160e081018552815460ff90811682526001830154938201849052938201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c083015261114e576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b600061116b8260800151836060015161383090919063ffffffff16565b905081604001516001600160a01b0316866001600160a01b0316146111c15760405162461bcd60e51b8152600401808060200182810382526045815260200180615ade6045913960600191505060405180910390fd5b336001600160a01b0316866001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b15801561120457600080fd5b505afa158015611218573d6000803e3d6000fd5b505050506040513d602081101561122e57600080fd5b50516001600160a01b0316146112755760405162461bcd60e51b815260040180806020018281038252602e815260200180615c40602e913960400191505060405180910390fd5b60408051636eb1769f60e11b8152336004820152306024820152905182916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b1580156112c457600080fd5b505afa1580156112d8573d6000803e3d6000fd5b505050506040513d60208110156112ee57600080fd5b50511461132c5760405162461bcd60e51b8152600401808060200182810382526036815260200180615ce16036913960400191505060405180910390fd5b600154341461136c5760405162461bcd60e51b81526004018080602001828103825260238152602001806159dc6023913960400191505060405180910390fd5b428260c001516001600160401b031610156115035760008381526002602081905260408220805460ff191681556001810183905590810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556113db61587d565b50604080518082019091526001808252602082018590526120009063f7a251d79061140584613872565b60015461141d906402540be40063ffffffff6138fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561147b578181015183820152602001611463565b50505050905090810190601f1680156114a85780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156114c957600080fd5b505af11580156114dd573d6000803e3d6000fd5b505050506040513d60208110156114f357600080fd5b5060009550611b5a945050505050565b6000866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561153e57600080fd5b505afa158015611552573d6000803e3d6000fd5b505050506040513d602081101561156857600080fd5b5051604080516395d89b4160e01b815290519192506060916001600160a01b038a16916395d89b41916004808301926000929190829003018186803b1580156115b057600080fd5b505afa1580156115c4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156115ed57600080fd5b8101908080516040519392919084600160201b82111561160c57600080fd5b90830190602082018581111561162157600080fd5b8251600160201b81118282018810171561163a57600080fd5b82525081516020918201929091019080838360005b8381101561166757818101518382015260200161164f565b50505050905090810190601f1680156116945780820380516001836020036101000a031916815260200191505b5060405250505090506116a7818661393e565b15806116cf57506020808501516000908152600590915260409020546001600160a01b031615155b806116f357506040808501516001600160a01b031660009081526004602052205415155b8061176a5750836060015184604001516001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561173b57600080fd5b505afa15801561174f573d6000803e3d6000fd5b505050506040513d602081101561176557600080fd5b505114155b8061177c57508360a0015160ff168214155b156119045760008581526002602081905260408220805460ff191681556001810183905590810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556117db61587d565b5060408051808201909152600281526020810186905261200063f7a251d7600161180484613872565b60015461181c906402540be40063ffffffff6138fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561187a578181015183820152602001611862565b50505050905090810190601f1680156118a75780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156118c857600080fd5b505af11580156118dc573d6000803e3d6000fd5b505050506040513d60208110156118f257600080fd5b5060009750611b5a9650505050505050565b604080516323b872dd60e01b81523360048201523060248201526044810185905290516001600160a01b038a16916323b872dd9160648083019260209291908290030181600087803b15801561195957600080fd5b505af115801561196d573d6000803e3d6000fd5b505050506040513d602081101561198357600080fd5b505060208481018051604080880180516001600160a01b03908116600090815260048088528482209590955560a08b0151835183168252600380895285832060ff90921690915592519551815260058088528482208054979093166001600160a01b0319978816179092558b8152600296879052928320805460ff1916815560018101849055958601805490951690945584018190559083015501805468ffffffffffffffffff19169055611a3661587d565b5060408051808201909152600081526020810186905261200063f7a251d76001611a5f84613872565b600154611a77906402540be40063ffffffff6138fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611ad5578181015183820152602001611abd565b50505050905090810190601f168015611b025780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015611b2357600080fd5b505af1158015611b37573d6000803e3d6000fd5b505050506040513d6020811015611b4d57600080fd5b5060019750505050505050505b92915050565b600381565b6000868514611ba55760405162461bcd60e51b815260040180806020018281038252603b815260200180615d17603b913960400191505060405180910390fd5b868314611be35760405162461bcd60e51b815260040180806020018281038252603f815260200180615bc5603f913960400191505060405180910390fd5b42607801826001600160401b03161015611c2e5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a606024913960400191505060405180910390fd5b846000805b82811015611c6a57611c60898983818110611c4a57fe5b9050602002013583613a1c90919063ffffffff16565b9150600101611c33565b50606082604051908082528060200260200182016040528015611c97578160200160208202803683370190505b50905060005b838160ff161015611d6d576402540be4008a8a8360ff16818110611cbd57fe5b9050602002013581611ccb57fe5b0615611d1e576040805162461bcd60e51b815260206004820152601760248201527f696e76616c6964207472616e7366657220616d6f756e74000000000000000000604482015290519081900360640190fd5b611d4b6402540be4008b8b8460ff16818110611d3657fe5b905060200201356138fc90919063ffffffff16565b828260ff1681518110611d5a57fe5b6020908102919091010152600101611c9d565b50600154611d9290611d85908563ffffffff613a7616565b839063ffffffff613a1c16565b3414611dcf5760405162461bcd60e51b815260040180806020018281038252604c815260200180615b54604c913960600191505060405180910390fd5b611dd7615894565b6040518060c001604052806221272160e91b60001b815260200160006001600160a01b031681526020018381526020018d8d808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208b810282810182019093528b82529283019290918c918c9182918501908490808284376000920191909152505050908252506001600160401b038816602090910152905061200063f7a251d76003611e9a84613acf565b611ec46402540be400611eb88a600154613a7690919063ffffffff16565b9063ffffffff6138fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611f22578181015183820152602001611f0a565b50505050905090810190601f168015611f4f5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015611f7057600080fd5b505af1158015611f84573d6000803e3d6000fd5b505050506040513d6020811015611f9a57600080fd5b5050604080516000815233602082015280820185905290517fe9750a449d7c7d8f872b7ee10d75b95a948bc425b3c2d52052587665742c81ec9181900360600190a15060019b9a5050505050505050505050565b61100581565b600281565b60015481565b60008061200b83613829565b9050612015615841565b50600081815260026020818152604092839020835160e081018552815460ff90811682526001830154938201849052938201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526120da576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b428160c001516001600160401b03161061213b576040805162461bcd60e51b815260206004820152601b60248201527f62696e642072657175657374206973206e6f7420657870697265640000000000604482015290519081900360640190fd5b600154341461217b5760405162461bcd60e51b8152600401808060200182810382526027815260200180615a396027913960400191505060405180910390fd5b60008281526002602081905260408220805460ff191681556001810183905590810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556121d561587d565b50604080518082019091526001808252602082018490526120009063f7a251d7906121ff84613872565b600154612217906402540be40063ffffffff6138fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561227557818101518382015260200161225d565b50505050905090810190601f1680156122a25780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156122c357600080fd5b505af11580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b5060019695505050505050565b60008061230683613829565b9050612310615841565b50600081815260026020818152604092839020835160e081018552815460ff90811682526001830154938201849052938201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526123d5576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b80604001516001600160a01b0316856001600160a01b0316146124295760405162461bcd60e51b8152600401808060200182810382526045815260200180615ade6045913960600191505060405180910390fd5b336001600160a01b0316856001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b15801561246c57600080fd5b505afa158015612480573d6000803e3d6000fd5b505050506040513d602081101561249657600080fd5b50516001600160a01b0316146124f3576040805162461bcd60e51b815260206004820152601b60248201527f6f6e6c79206265703265206f776e65722063616e2072656a6563740000000000604482015290519081900360640190fd5b60015434146125335760405162461bcd60e51b8152600401808060200182810382526027815260200180615a396027913960400191505060405180910390fd5b60008281526002602081905260408220805460ff191681556001810183905590810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff1916905561258d61587d565b5060408051808201909152600381526020810183905261200063f7a251d760016125b684613872565b6001546125ce906402540be40063ffffffff6138fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561262c578181015183820152602001612614565b50505050905090810190601f1680156126595780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561267a57600080fd5b505af115801561268e573d6000803e3d6000fd5b505050506040513d60208110156126a457600080fd5b506001979650505050505050565b600b81565b60005460ff1661270a576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b336120001461274a5760405162461bcd60e51b815260040180806020018281038252602f815260200180615d52602f913960400191505060405180910390fd5b60ff83166003141561279a5761279582828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d8992505050565b612809565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a15b505050565b600981565b677ce66c50e284000081565b6000805460ff16612873576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b33611005146128b35760405162461bcd60e51b815260040180806020018281038252602f8152602001806159ad602f913960400191505060405180910390fd5b60004783106128c257476128c4565b825b9050801561100e576040516001600160a01b0385169082156108fc029083906000818181858888f19350505050158015612902573d6000803e3d6000fd5b50604080516001600160a01b03861681526020810183905281517ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0929181900390910190a19392505050565b61100781565b61100681565b60036020526000908152604090205481565b60005460ff1681565b600042607801826001600160401b031610156129c25760405162461bcd60e51b8152600401808060200182810382526024815260200180615a606024913960400191505060405180910390fd5b6000806001600160a01b038716612a8d576402540be400850615612a175760405162461bcd60e51b815260040180806020018281038252603c815260200180615c04603c913960400191505060405180910390fd5b600154612a2b90869063ffffffff613a1c16565b3414612a685760405162461bcd60e51b815260040180806020018281038252604c815260200180615b54604c913960600191505060405180910390fd5b612a7d856402540be40063ffffffff6138fc16565b6221272160e91b92509050612d2c565b6001600160a01b038716600090815260046020526040902054915081612ae45760405162461bcd60e51b8152600401808060200182810382526031815260200180615b236031913960400191505060405180910390fd5b6001543414612b245760405162461bcd60e51b815260040180806020018281038252602d815260200180615d81602d913960400191505060405180910390fd5b6001600160a01b038716600090815260036020526040902054600881111580612b6c5750600881118015612b6c5750612b6a866007198301600a0a63ffffffff613de516565b155b612ba75760405162461bcd60e51b815260040180806020018281038252603c815260200180615c04603c913960400191505060405180910390fd5b612bb18682613e27565b9150612bbc83613e67565b15612c04576305f5e100821015612c045760405162461bcd60e51b815260040180806020018281038252603a8152602001806159ff603a913960400191505060405180910390fd5b600881101580612c1e5750600881108015612c1e57508582115b612c595760405162461bcd60e51b8152600401808060200182810382526025815260200180615ba06025913960400191505060405180910390fd5b677ce66c50e2840000821115612ca05760405162461bcd60e51b8152600401808060200182810382526035815260200180615a846035913960400191505060405180910390fd5b604080516323b872dd60e01b81523360048201523060248201526044810188905290516001600160a01b038a16916323b872dd9160648083019260209291908290030181600087803b158015612cf557600080fd5b505af1158015612d09573d6000803e3d6000fd5b505050506040513d6020811015612d1f57600080fd5b5051612d2a57600080fd5b505b612d34615894565b6040805160c0810182528481526001600160a01b038a16602082015281516001808252818401845291928301918160200160208202803683375050508152604080516001808252818301909252602092830192909190808301908036833750505081526040805160018082528183019092526020928301929091908083019080368337019050508152602001866001600160401b03168152509050818160400151600081518110612de157fe5b602002602001018181525050868160600151600081518110612dff57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050338160800151600081518110612e3157fe5b6001600160a01b039092166020928302919091019091015261200063f7a251d76003612e5c84613acf565b600154612e74906402540be40063ffffffff6138fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015612ed2578181015183820152602001612eba565b50505050905090810190601f168015612eff5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015612f2057600080fd5b505af1158015612f34573d6000803e3d6000fd5b505050506040513d6020811015612f4a57600080fd5b5050604080516001600160a01b038a16815233602082015280820188905290517fe9750a449d7c7d8f872b7ee10d75b95a948bc425b3c2d52052587665742c81ec9181900360600190a1506001979650505050505050565b3361100714612fe25760405162461bcd60e51b815260040180806020018281038252602e815260200180615c8f602e913960400191505060405180910390fd5b60208114613037576040805162461bcd60e51b815260206004820152601b60248201527f65787065637465642076616c7565206c656e6774682069732033320000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152939450606093925086915085908190840183828082843760009201919091525050505060208301519091506772656c617946656560c01b81141561313f576020820151670de0b6b3a764000081111580156130e657506402540be4008106155b613137576040805162461bcd60e51b815260206004820152601960248201527f7468652072656c6179466565206f7574206f662072616e676500000000000000604482015290519081900360640190fd5b60015561317c565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b61c35081565b6221272160e91b81565b61100281565b60005460ff1661327a576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b33612000146132ba5760405162461bcd60e51b815260040180806020018281038252602f815260200180615d52602f913960400191505060405180910390fd5b60ff83166003141561279a5761279582828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613f6d92505050565b600260208190526000918252604090912080546001820154928201546003830154600484015460059094015460ff93841695946001600160a01b039093169391929181169061010090046001600160401b031687565b61100381565b60005460ff16156133b9576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b662386f26fc1000060019081556000805460ff19169091179055565b600581565b61100081565b6001600160a01b03811660009081526004602090815260409182902054825182815280840190935260609290918391906020820181803683375050506020810183905290506000805b60208160ff16101561347057828160ff168151811061344457fe5b01602001516001600160f81b0319161561346357600190910190613468565b613470565b600101613429565b5060608160ff166040519080825280601f01601f1916602001820160405280156134a1576020820181803683370190505b50905060005b8260ff168160ff1610156134fd57838160ff16815181106134c457fe5b602001015160f81c60f81b828260ff16815181106134de57fe5b60200101906001600160f81b031916908160001a9053506001016134a7565b5095945050505050565b61100481565b6060613517615841565b60006135228461406b565b9150915080613578576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b815160ff1661362c576020828101805160009081526002928390526040908190208551815460ff1990811660ff928316178355935160018301559186015193810180546001600160a01b0319166001600160a01b0390951694909417909355606085015160038401556080850151600484015560a08501516005909301805460c08701519316939091169290921768ffffffffffffffff0019166101006001600160401b03909216919091021790556136ea565b815160ff166001141561369d576020808301516000908152600590915260409020546001600160a01b03168015613697576001600160a01b03811660009081526004602090815260408083208390558582015183526005909152902080546001600160a01b03191690555b506136ea565b6040805162461bcd60e51b815260206004820152601960248201527f756e7265636f676e697a65642062696e64207061636b61676500000000000000604482015290519081900360640190fd5b60408051600080825260208201909252905b50949350505050565b606061370f6158df565b600061371a846141bc565b9150915080613770576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b600061377b836142d5565b905063ffffffff81161561380f576040808401516020808601516001600160a01b031660009081526003909152918220546137b69190613e27565b90506137c0615914565b60405180608001604052808660000151815260200183815260200186608001516001600160a01b031681526020018463ffffffff168152509050613803816145eb565b95505050505050611047565b505060408051600081526020810190915291506110479050565b6020015190565b600061100e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506146b3565b6040805160028082526060828101909352829190816020015b606081526020019060019003908161388b57505083519091506138b39063ffffffff1661474a565b816000815181106138c057fe5b60200260200101819052506138db836020015160001c61474a565b816001815181106138e857fe5b602002602001018190525061100e8161475d565b600061100e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506147ba565b8151600090839060081080613954575080516003115b15613963576000915050611b5a565b6040805160208082528183019092526060916020820181803683370190505090508360208201528082518151811061399757fe5b6020910101516001600160f81b031916602d60f81b146139bc57600092505050611b5a565b600160005b83518110156134fd578281815181106139d657fe5b602001015160f81c60f81b6001600160f81b0319168482815181106139f757fe5b01602001516001600160f81b03191614613a1457600091506134fd565b6001016139c1565b60008282018381101561100e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082613a8557506000611b5a565b82820282848281613a9257fe5b041461100e5760405162461bcd60e51b8152600401808060200182810382526021815260200180615c6e6021913960400191505060405180910390fd5b60408051600680825260e08201909252606091829190816020015b6060815260200190600190039081613aea5750508351909150613b0c9061474a565b81600081518110613b1957fe5b6020026020010181905250613b3a83602001516001600160a01b031661481f565b81600181518110613b4757fe5b602002602001018190525060008360400151519050606081604051908082528060200260200182016040528015613b9257816020015b6060815260200190600190039081613b7d5790505b50905060005b82811015613bdf57613bc086604001518281518110613bb357fe5b602002602001015161474a565b828281518110613bcc57fe5b6020908102919091010152600101613b98565b50613be98161475d565b83600281518110613bf657fe5b6020026020010181905250606082604051908082528060200260200182016040528015613c3757816020015b6060815260200190600190039081613c225790505b50905060005b83811015613c8d57613c6e87606001518281518110613c5857fe5b60200260200101516001600160a01b031661481f565b828281518110613c7a57fe5b6020908102919091010152600101613c3d565b50613c978161475d565b84600381518110613ca457fe5b6020026020010181905250606083604051908082528060200260200182016040528015613ce557816020015b6060815260200190600190039081613cd05790505b50905060005b84811015613d2557613d0688608001518281518110613c5857fe5b828281518110613d1257fe5b6020908102919091010152600101613ceb565b50613d2f8161475d565b85600481518110613d3c57fe5b6020026020010181905250613d5d8760a001516001600160401b031661474a565b85600581518110613d6a57fe5b6020026020010181905250613d7e8561475d565b979650505050505050565b613d9161593b565b6000613d9c83614842565b9150915080613ddc5760405162461bcd60e51b8152600401808060200182810382526024815260200180615cbd6024913960400191505060405180910390fd5b61280982614a0d565b600061100e83836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250614e5e565b60006008821115613e5057613e49836007198401600a0a63ffffffff6138fc16565b9050611b5a565b61100e836008849003600a0a63ffffffff613a7616565b604080516020808252818301909252600091606091906020820181803683375050506020810184905290506000805b60208160ff161015613edd57828160ff1681518110613eb157fe5b01602001516001600160f81b03191615613ed057600190910190613ed5565b613edd565b600101613e96565b50600860ff82161015613ef557600092505050611047565b816005820360ff1681518110613f0757fe5b6020910101516001600160f81b031916602d60f81b14613f2c57600092505050611047565b816001820360ff1681518110613f3e57fe5b6020910101516001600160f81b031916604d60f81b14613f6357600092505050611047565b5060019392505050565b613f75615894565b6000613f8083614ec0565b9150915080613fc05760405162461bcd60e51b8152600401808060200182810382526025815260200180615ab96025913960400191505060405180910390fd5b613fc861593b565b602080840180516001600160a01b0390811684526040808701518585015291511660009081526003909252812054905b846040015151811015614049576140268560400151828151811061401857fe5b60200260200101518361513a565b8560400151828151811061403657fe5b6020908102919091010152600101613ff8565b50608084015160408301526005606083015261406482614a0d565b5050505050565b614073615841565b600061407d615841565b614085615972565b61409661409186615173565b615198565b90506000805b6140a5836151e2565b156141af57806140ca576140c06140bb84615203565b615251565b60ff1684526141a7565b80600114156140e9576140df6140bb84615203565b60208501526141a7565b8060021415614116576141036140fe84615203565b6152af565b6001600160a01b031660408501526141a7565b80600314156141355761412b6140bb84615203565b60608501526141a7565b80600414156141545761414a6140bb84615203565b60808501526141a7565b8060051415614176576141696140bb84615203565b60ff1660a08501526141a7565b80600614156141a25761418b6140bb84615203565b6001600160401b031660c0850152600191506141a7565b6141af565b60010161409c565b5091935090915050915091565b6141c46158df565b60006141ce6158df565b6141d6615972565b6141e261409186615173565b90506000805b6141f1836151e2565b156141af578061420e576142076140bb84615203565b84526142cd565b8060011415614236576142236140fe84615203565b6001600160a01b031660208501526142cd565b80600214156142555761424b6140bb84615203565b60408501526142cd565b806003141561427d5761426a6140fe84615203565b6001600160a01b031660608501526142cd565b80600414156142a5576142926140fe84615203565b6001600160a01b031660808501526142cd565b80600514156141a2576142ba6140bb84615203565b6001600160401b031660a0850152600191505b6001016141e8565b60208101516000906001600160a01b03166143d6578160a001516001600160401b031642111561430757506001611047565b816040015147101561431b57506003611047565b81606001516001600160a01b03166108fc83604001519081150290604051600060405180830381858888f1935050505061435757506004611047565b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5982602001518360600151846040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a1506000611047565b8160a001516001600160401b03164211156143f357506001611047565b81516020808401516001600160a01b03166000908152600490915260409020541461442057506002611047565b602080830151604080516370a0823160e01b815230600482015290516000936001600160a01b03909316926370a082319261c3509260248083019392829003018187803b15801561447057600080fd5b5086fa158015614484573d6000803e3d6000fd5b50505050506040513d602081101561449b57600080fd5b505160408401519091508110156144b6575060039050611047565b600083602001516001600160a01b031663a9059cbb61c350866060015187604001516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b15801561452757600080fd5b5087f115801561453b573d6000803e3d6000fd5b50505050506040513d602081101561455257600080fd5b5051905080156145df577f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5984602001518560600151866040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a150600091506110479050565b50600591506110479050565b60408051600480825260a08201909252606091829190816020015b606081526020019060019003908161460657505083519091506146289061474a565b8160008151811061463557fe5b602002602001018190525061464d836020015161474a565b8160018151811061465a57fe5b602002602001018190525061467b83604001516001600160a01b031661481f565b8160028151811061468857fe5b60200260200101819052506146a6836060015163ffffffff1661474a565b816003815181106138e857fe5b600081848411156147425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156147075781810151838201526020016146ef565b50505050905090810190601f1680156147345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6060611b5a614758836152c9565b6153b9565b604080516000808252602082019092526060915b83518110156147a1576147978285838151811061478a57fe5b602002602001015161540b565b9150600101614771565b5061100e6147b4825160c060ff166154f0565b8261540b565b600081836148095760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156147075781810151838201526020016146ef565b50600083858161481557fe5b0495945050505050565b60408051600560a21b831860148201526034810190915260609061100e816153b9565b61484a61593b565b600061485461593b565b61485c615972565b61486861409186615173565b90506000805b614877836151e2565b156141af578061489d5761488d6140fe84615203565b6001600160a01b03168452614a05565b806001141561493e5760606148b96148b485615203565b6155e8565b905080516040519080825280602002602001820160405280156148e6578160200160208202803683370190505b50602086015260005b81518110156149375761491482828151811061490757fe5b6020026020010151615251565b8660200151828151811061492457fe5b60209081029190910101526001016148ef565b5050614a05565b80600214156149e05760606149556148b485615203565b90508051604051908082528060200260200182016040528015614982578160200160208202803683370190505b50604086015260005b8151811015614937576149b08282815181106149a357fe5b60200260200101516152af565b866040015182815181106149c057fe5b6001600160a01b039092166020928302919091019091015260010161498b565b80600314156141a2576149f56140bb84615203565b63ffffffff166060850152600191505b60010161486e565b80516001600160a01b0316614c045760005b816020015151811015614bfe5781604001518181518110614a3c57fe5b60200260200101516001600160a01b03166108fc83602001518381518110614a6057fe5b60200260200101519081150290604051600060405180830381858888f19350505050614b40577f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e826000015183604001518381518110614abc57fe5b602002602001015184602001518481518110614ad457fe5b6020026020010151856060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a1614bf6565b7fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a826000015183604001518381518110614b7657fe5b602002602001015184602001518481518110614b8e57fe5b6020026020010151856060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b600101614a1f565b50614e5b565b60005b816020015151811015614e5957600082600001516001600160a01b031663a9059cbb61c35085604001518581518110614c3c57fe5b602002602001015186602001518681518110614c5457fe5b60200260200101516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015614cab57600080fd5b5087f1158015614cbf573d6000803e3d6000fd5b50505050506040513d6020811015614cd657600080fd5b505190508015614d9a577fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a836000015184604001518481518110614d1657fe5b602002602001015185602001518581518110614d2e57fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a1614e50565b7f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e836000015184604001518481518110614dd057fe5b602002602001015185602001518581518110614de857fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101614c07565b505b50565b60008183614ead5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156147075781810151838201526020016146ef565b50828481614eb757fe5b06949350505050565b614ec8615894565b6000614ed2615894565b614eda615972565b614ee661409186615173565b90506000805b614ef5836151e2565b1561512c5780614f1257614f0b6140bb84615203565b8452615124565b8060011415614f3a57614f276140fe84615203565b6001600160a01b03166020850152615124565b8060021415614fc9576060614f516148b485615203565b90508051604051908082528060200260200182016040528015614f7e578160200160208202803683370190505b50604086015260005b8151811015614fc257614f9f82828151811061490757fe5b86604001518281518110614faf57fe5b6020908102919091010152600101614f87565b5050615124565b806003141561505e576060614fe06148b485615203565b9050805160405190808252806020026020018201604052801561500d578160200160208202803683370190505b50606086015260005b8151811015614fc25761502e8282815181106149a357fe5b8660600151828151811061503e57fe5b6001600160a01b0390921660209283029190910190910152600101615016565b80600414156150f35760606150756148b485615203565b905080516040519080825280602002602001820160405280156150a2578160200160208202803683370190505b50608086015260005b8151811015614fc2576150c38282815181106149a357fe5b866080015182815181106150d357fe5b6001600160a01b03909216602092830291909101909101526001016150ab565b806005141561511f576151086140bb84615203565b6001600160401b031660a085015260019150615124565b61512c565b600101614eec565b509195600195509350505050565b6000600882111561515c57613e49836007198401600a0a63ffffffff613a7616565b61100e836008849003600a0a63ffffffff6138fc16565b61517b615992565b506040805180820190915281518152602082810190820152919050565b6151a0615972565b6151a9826156b9565b6151b257600080fd5b60006151c183602001516156e9565b60208085015160408051808201909152868152920190820152915050919050565b60006151ec615992565b505080518051602091820151919092015191011190565b61520b615992565b615214826151e2565b61521d57600080fd5b6020820151600061522d8261574c565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061526657508151602110155b61526f57600080fd5b600061527e83602001516156e9565b835160208086015183018051939450918490039291908310156136fc57506020919091036101000a90049392505050565b80516000906015146152c057600080fd5b611b5a82615251565b6040805160208082528183019092526060916000918391602082018180368337019050509050836020820152600091505b60208210156153335780828151811061530f57fe5b01602001516001600160f81b0319161561532857615333565b6001909101906152fa565b6060826020036040519080825280601f01601f191660200182016040528015615363576020820181803683370190505b50905060005b81518110156136fc57825160018501948491811061538357fe5b602001015160f81c60f81b82828151811061539a57fe5b60200101906001600160f81b031916908160001a905350600101615369565b6060815160011480156153eb5750607f60f81b826000815181106153d957fe5b01602001516001600160f81b03191611155b156153f7575080611047565b611b5a6154098351608060ff166154f0565b835b60608082518451016040519080825280601f01601f19166020018201604052801561543d576020820181803683370190505b5090506000805b85518110156154935785818151811061545957fe5b602001015160f81c60f81b83838151811061547057fe5b60200101906001600160f81b031916908160001a90535060019182019101615444565b5060005b84518110156154e6578481815181106154ac57fe5b602001015160f81c60f81b8383815181106154c357fe5b60200101906001600160f81b031916908160001a90535060019182019101615497565b5090949350505050565b6060680100000000000000008310615540576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b6040805160018082528183019092526060916020820181803683370190505090506037841161559a5782840160f81b8160008151811061557c57fe5b60200101906001600160f81b031916908160001a9053509050611b5a565b60606155a5856152c9565b90508381510160370160f81b826000815181106155be57fe5b60200101906001600160f81b031916908160001a9053506155df828261540b565b95945050505050565b60606155f3826156b9565b6155fc57600080fd5b6000615607836157e5565b905060608160405190808252806020026020018201604052801561564557816020015b615632615992565b81526020019060019003908161562a5790505b509050600061565785602001516156e9565b60208601510190506000805b848110156156ae576156748361574c565b915060405180604001604052808381526020018481525084828151811061569757fe5b602090810291909101015291810191600101615663565b509195945050505050565b80516000906156ca57506000611047565b6020820151805160001a9060c0821015613f6357600092505050611047565b8051600090811a6080811015615703576000915050611047565b60b881108061571e575060c0811080159061571e575060f881105b1561572d576001915050611047565b60c08110156157415760b519019050611047565b60f519019050611047565b80516000908190811a608081101561576757600191506157de565b60b881101561577c57607e19810191506157de565b60c08110156157a95760b78103600185019450806020036101000a855104600182018101935050506157de565b60f88110156157be5760be19810191506157de565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b80516000906157f657506000611047565b6000809050600061580a84602001516156e9565b602085015185519181019250015b80821015615838576158298261574c565b60019093019290910190615818565b50909392505050565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080518082019091526000808252602082015290565b6040518060c001604052806000801916815260200160006001600160a01b0316815260200160608152602001606081526020016060815260200160006001600160401b031681525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806080016040528060006001600160a01b031681526020016060815260200160608152602001600063ffffffff1681525090565b6040518060400160405280615985615992565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d75737420626520696e63656e746976697a6520636f6e74726163746d73672e76616c756520646f65736e277420657175616c20746f2072656c6179466565466f72206d696e69546f6b656e2c20746865207472616e7366657220616d6f756e74206d757374206e6f74206265206c657373207468616e20316d73672e76616c756520646f65736e277420657175616c20746f2073796e6352656c617946656565787069726554696d65206d7573742062652074776f206d696e75746573206c61746572616d6f756e7420697320746f6f206c617267652c20657863656564206d6178696d756d206265703220746f6b656e20616d6f756e74756e7265636f676e697a6564207472616e736665724f75742073796e63207061636b616765636f6e74616374206164647265737320646f65736e277420657175616c20746f2074686520636f6e7472616374206164647265737320696e2062696e64207265717565737474686520636f6e747261637420686173206e6f74206265656e20626f756e6420746f20616e79206265703220746f6b656e726563656976656420424e4220616d6f756e7420646f65736e277420657175616c20746f207468652073756d206f66207472616e7366657220616d6f756e7420616e642072656c6179466565616d6f756e7420697320746f6f206c617267652c2075696e74323536206f766572666c6f774c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620726566756e644164647273696e76616c6964207472616e7366657220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6e6f6e6c79206265703265206f776e65722063616e20617070726f766520746869732062696e642072657175657374536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374756e7265636f676e697a6564207472616e736665724f75742061636b207061636b616765616c6c6f77616e636520646f65736e277420657175616c20746f2028746f74616c537570706c79202d207065676779416d6f756e74294c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620616d6f756e7473746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374726563656976656420424e4220616d6f756e7420646f65736e277420657175616c20746f2072656c6179466565a2646970667358221220b0732d8c657f30730ac940767a9200a6bd3e6dc96bfb0de8acce8bab34a4127964736f6c63430006040033" }, "0x0000000000000000000000000000000000001005": { "balance": "0x0", diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 31ea29ff6..161838e82 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -6,6 +6,7 @@ const RLPDecode = artifacts.require("rlp/RLPDecode"); const RLPEncode = artifacts.require("rlp/RLPEncode"); const BytesToTypes = artifacts.require("rlp/BytesToTypes"); const Memory = artifacts.require("Seriality/Memory"); +const SafeMath = artifacts.require("lib/SafeMath"); const BytesLib = artifacts.require("solidity-bytes-utils/contracts/BytesLib"); const MockLightClient = artifacts.require("mock/MockLightClient"); @@ -21,6 +22,7 @@ const CrossChain = artifacts.require("CrossChain"); const TokenHub = artifacts.require("TokenHub"); const ABCToken = artifacts.require("test/ABCToken"); const DEFToken = artifacts.require("test/DEFToken"); +const MiniToken = artifacts.require("test/MiniToken"); const MaliciousToken = artifacts.require("test/MaliciousToken"); const BSCValidatorSetTool = artifacts.require("tool/BSCValidatorSetTool"); @@ -39,19 +41,13 @@ module.exports = function(deployer, network, accounts) { tendermintLightClientInstance=_tendermintLightClientInstance; tendermintLightClientInstance.init(); }); - let tokenHubInstance; - deployer.deploy(TokenHub).then(function(_tokenHubInstance){ - tokenHubInstance=_tokenHubInstance; - tokenHubInstance.init({ - from: accounts[0], - value: 50e18}) - }); let crossChainInstance; deployer.deploy(CrossChain).then(function (_crossChainInstance) { crossChainInstance = _crossChainInstance; }); deployer.deploy(ABCToken); deployer.deploy(DEFToken); + deployer.deploy(MiniToken); deployer.deploy(MaliciousToken); deployer.deploy(MockRelayerHub); deployer.deploy(BSCValidatorSetTool); @@ -65,12 +61,15 @@ module.exports = function(deployer, network, accounts) { instance.addOperator(RelayerIncentivize.address, {from: accounts[0]}); }); + let tokenHubInstance; let relayerHubInstance; // deploy lib deployer.deploy(TypesToBytes).then(function() { return deployer.deploy(BytesToTypes); }).then(function() { return deployer.deploy(Memory); + }).then(function() { + return deployer.deploy(SafeMath); }).then(function() { return deployer.deploy(BytesLib); }).then(function() { @@ -82,6 +81,16 @@ module.exports = function(deployer, network, accounts) { }).then(function() { // deploy mock return deployer.deploy(MockLightClient); + }).then(function() { + deployer.deploy(TokenHub).then(function(_tokenHubInstance){ + deployer.link(RLPEncode, TokenHub); + deployer.link(RLPDecode, TokenHub); + deployer.link(SafeMath, TokenHub); + tokenHubInstance=_tokenHubInstance; + tokenHubInstance.init({ + from: accounts[0], + value: 50e18}) + }); }).then(function() { // deploy mock deployer.link(Memory, RelayerHub); diff --git a/test/TestTokenHub.js b/test/TestTokenHub.js index 4ac6acadf..e1d0238d3 100644 --- a/test/TestTokenHub.js +++ b/test/TestTokenHub.js @@ -10,6 +10,7 @@ const TokenHub = artifacts.require("TokenHub"); const CrossChain = artifacts.require("CrossChain"); const ABCToken = artifacts.require("ABCToken"); const DEFToken = artifacts.require("DEFToken"); +const MiniToken = artifacts.require("test/MiniToken"); const MaliciousToken = artifacts.require("test/MaliciousToken"); const RelayerHub = artifacts.require("RelayerHub"); @@ -155,9 +156,9 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); - let sequence = 0; + let bindSequence = 0; - await crossChain.handlePackage(bindPackage, proof, merkleHeight, sequence, BIND_CHANNEL_ID, {from: relayer}); + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); let bindRequenst = await tokenHub.bindPackageRecord.call(toBytes32Bep2Symbol("ABC-9C7")); // symbol: ABC-9C7 assert.equal(bindRequenst.bep2TokenSymbol.toString(), toBytes32Bep2Symbol("ABC-9C7"), "wrong bep2TokenSymbol"); @@ -207,9 +208,9 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); //expire time - let sequence = 1; + let bindSequence = 1; - await crossChain.handlePackage(bindPackage, proof, merkleHeight, sequence, BIND_CHANNEL_ID, {from: relayer}); + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); try { await tokenHub.rejectBind(abcToken.address, "ABC-9C7", {from: relayer, value: 1e16}); @@ -238,9 +239,9 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); - let sequence = 2; + let bindSequence = 2; - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, sequence, BIND_CHANNEL_ID, {from: relayer}); + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); try { await tokenHub.expireBind("ABC-9C7", {from: accounts[2], value: 1e16}); @@ -270,9 +271,9 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const bindPackage = buildBindPackage(0, "DEF-9C7", abcToken.address, 1e8, 99e6, 18); - let sequence = 3; + let bindSequence = 3; - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, sequence, BIND_CHANNEL_ID, {from: relayer}); + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); tx = await tokenHub.approveBind(abcToken.address, "DEF-9C7", {from: owner, value: 1e16}); @@ -293,9 +294,9 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); - let sequence = 4; + let bindSequence = 4; - await crossChain.handlePackage(bindPackage, proof, merkleHeight, sequence, BIND_CHANNEL_ID, {from: relayer}); + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); let tx = await tokenHub.approveBind(abcToken.address, "ABC-9C7", {from: owner, value: 1e16}); @@ -317,12 +318,12 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const transferInPackage = buildTransferInPackage("ABC-9C7", abcToken.address, 155e17, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - let sequence = 0; + let transferInSequence = 0; let balance = await abcToken.balanceOf.call(accounts[2]); assert.equal(balance.toNumber(), 0, "wrong balance"); - await crossChain.handlePackage(transferInPackage, proof, merkleHeight, sequence, TRANSFER_IN_CHANNELID, {from: relayer}); + await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); balance = await abcToken.balanceOf.call(accounts[2]); assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); @@ -335,11 +336,11 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const transferInPackage = buildTransferInPackage("ABC-9C7", abcToken.address, 155e17, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - let sequence = 1; + let transferInSequence = 1; await sleep(5 * 1000); - let tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, sequence, TRANSFER_IN_CHANNELID, {from: relayer}); + let tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); let event; truffleAssert.eventEmitted(tx, "crossChainPackage",(ev) => { let matched = false; @@ -364,11 +365,11 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const transferInPackage = buildTransferInPackage("BNB", "0x0000000000000000000000000000000000000000", 1e18, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - let sequence = 2; + let transferInSequence = 2; const initBalance = await web3.eth.getBalance(accounts[2]); - await crossChain.handlePackage(transferInPackage, proof, merkleHeight, sequence, TRANSFER_IN_CHANNELID, {from: relayer}); + await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); const newBalance = await web3.eth.getBalance(accounts[2]); @@ -457,13 +458,13 @@ contract('TokenHub', (accounts) => { [refundAddr], //refund address 1]); //status - let sequence = 0; + let refundSequence = 0; const amount = web3.utils.toBN(1e18); let balance = await abcToken.balanceOf.call(refundAddr); assert.equal(balance.eq(web3.utils.toBN(155e17).sub(amount)), true, "wrong balance"); - tx = await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, sequence, TRANSFER_OUT_CHANNELID, {from: relayer}); + tx = await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); let nestedEventValues = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs[0].args; assert.equal(nestedEventValues[0].toString().toLowerCase(), abcToken.address.toLowerCase(), "wrong refund contract address"); @@ -510,9 +511,9 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const bindPackage = buildBindPackage(0, "MALICIOU-A09", maliciousToken.address, 1e8, 99e6, 18); - let sequence = 5; + let bindSequence = 5; - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, sequence, BIND_CHANNEL_ID, {from: relayer}); + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); assert.equal(tx.receipt.status, true, "failed transaction"); await maliciousToken.approve(tokenHub.address, web3.utils.toBN('1000000000000000000000000'), {from: owner}); @@ -582,6 +583,38 @@ contract('TokenHub', (accounts) => { assert.ok(error.toString().includes("SafeMath: addition overflow")); } }); + it('fail ack for transfer out', async () => { + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + const relayer = accounts[1]; + + let initBalance3 = await abcToken.balanceOf.call(accounts[3]); + let initBalance4 = await abcToken.balanceOf.call(accounts[4]); + + packageBytesPrefix = Buffer.from(web3.utils.hexToBytes( + "0x02" + + "0000000000000000000000000000000000000000000000000000000000000000" + )); + + packageBytes = RLP.encode([ + toBytes32Bep2Symbol("ABC-9C7"), + abcToken.address, + [1e6, 2e6], + ["0x37B8516a0F88E65D677229b402ec6C1e0E333004", "0xfA5E36a04EeF3152092099F352DDbe88953bB540"], + [accounts[3], accounts[4]], + Math.floor(Date.now() / 1000) + ]); + let refundSequence = 2; + + await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); + + let newBalance3 = await abcToken.balanceOf.call(accounts[3]); + let newBalance4 = await abcToken.balanceOf.call(accounts[4]); + + assert.equal(newBalance3.sub(initBalance3).eq(web3.utils.toBN(1e16)), true, "wrong balance"); + assert.equal(newBalance4.sub(initBalance4).eq(web3.utils.toBN(2e16)), true, "wrong balance"); + }); it('Unbind Token', async () => { const tokenHub = await TokenHub.deployed(); const abcToken = await ABCToken.deployed(); @@ -590,9 +623,9 @@ contract('TokenHub', (accounts) => { const relayer = accounts[1]; const bindPackage = buildBindPackage(1, "ABC-9C7", abcToken.address, 0, 0, 0); - let sequence = 6; + let bindSequence = 6; - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, sequence, BIND_CHANNEL_ID, {from: relayer}); + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); assert.equal(tx.receipt.status, true, "failed transaction"); const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); @@ -602,9 +635,9 @@ contract('TokenHub', (accounts) => { const transferInPackage = buildTransferInPackage("ABC-9C7", abcToken.address, 1e18, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - sequence = 4; + let transferInSequence = 4; - tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, sequence, TRANSFER_IN_CHANNELID, {from: relayer}); + tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); assert.equal(tx.receipt.status, true, "failed transaction"); // refund should be successful @@ -619,7 +652,7 @@ contract('TokenHub', (accounts) => { [refundAddr], //refund address 1]); //refund address - refundSequence = 2; + let refundSequence = 3; let beforeRefundBalance = await abcToken.balanceOf.call(refundAddr); @@ -647,4 +680,60 @@ contract('TokenHub', (accounts) => { assert.ok(error.toString().includes("the contract has not been bound to any bep2 token")); } }); + it('bind and transfer miniToken', async () => { + const tokenHub = await TokenHub.deployed(); + const miniToken = await MiniToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const owner = accounts[0]; + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(0, "XYZ-9C7M", miniToken.address, 1e4, 5e3, 18); + let bindSequence = 7; + + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); + + await miniToken.approve(tokenHub.address, web3.utils.toBN(1e18).mul(web3.utils.toBN(5e3)), {from: owner}); + let tx = await tokenHub.approveBind(miniToken.address, "XYZ-9C7M", {from: owner, value: 1e16}); + + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x", "bind status should be successful"); + assert.equal(web3.utils.bytesToHex(decoded[1]), toBytes32Bep2Symbol("XYZ-9C7M"), "wrong bep2TokenSymbol"); + + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(miniToken.address); + assert.equal(bep2Symbol, "XYZ-9C7M", "wrong symbol"); + const contractAddr = await tokenHub.getBoundContract.call("XYZ-9C7M"); + assert.equal(contractAddr, miniToken.address, "wrong contract addr"); + + let amount = web3.utils.toBN(1e18); + let recipient = accounts[3]; + await miniToken.approve(tokenHub.address, amount, {from: owner}); + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = (timestamp + 300); + const relayFee = web3.utils.toBN(1e16); + tx = await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, {from: owner, value: relayFee}); + truffleAssert.eventEmitted(tx, "transferOutSuccess",(ev) => { + return ev.amount.eq(web3.utils.toBN(amount)) && ev.bep2eAddr.toString().toLowerCase() === miniToken.address.toLowerCase(); + }); + amount = web3.utils.toBN(5e17); + await miniToken.approve(tokenHub.address, amount, {from: owner}); + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = (timestamp + 300); + try { + await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, {from: owner, value: relayFee}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("For miniToken, the transfer amount must not be less than 1")); + } + + amount = web3.utils.toBN(1e18); + const transferInPackage = buildTransferInPackage("XYZ-9C7M", miniToken.address, amount, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); + let transferInSequence = 5; + + const initBalance = await miniToken.balanceOf.call(accounts[2]); + await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + const newBalance = await miniToken.balanceOf.call(accounts[2]); + assert.equal(newBalance.sub(initBalance).eq(amount), true, "wrong balance"); + }); });