diff --git a/abi/tokenmanager.abi b/abi/tokenmanager.abi index 445e1b59..1d03235b 100644 --- a/abi/tokenmanager.abi +++ b/abi/tokenmanager.abi @@ -61,6 +61,95 @@ "name": "bindSuccess", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "mirrorFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "bep2Symbol", + "type": "bytes32" + } + ], + "name": "mirrorSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "syncFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + } + ], + "name": "syncSuccess", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -80,6 +169,21 @@ "name": "unexpectedPackage", "type": "event" }, + { + "constant": true, + "inputs": [], + "name": "BEP2_TOKEN_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -350,6 +454,36 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "MAX_BEP2_TOTAL_SUPPLY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_GAS_FOR_TRANSFER_BNB", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -365,6 +499,81 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "MIRROR_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MIRROR_STATUS_ALREADY_BOUND", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MIRROR_STATUS_DUPLICATED_BEP2_SYMBOL", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MIRROR_STATUS_SUCCESS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MIRROR_STATUS_TIMEOUT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -425,6 +634,66 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "SYNC_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "SYNC_STATUS_NOT_BOUND_MIRROR", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "SYNC_STATUS_SUCCESS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "SYNC_STATUS_TIMEOUT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -560,6 +829,32 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "internalType": "string", + "name": "bep2Symbol", + "type": "string" + } + ], + "name": "approveBind", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, { "constant": true, "inputs": [ @@ -611,6 +906,27 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "boundByMirror", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -630,8 +946,29 @@ "constant": false, "inputs": [ { - "internalType": "uint8", + "internalType": "string", + "name": "bep2Symbol", + "type": "string" + } + ], + "name": "expireBind", + "outputs": [ + { + "internalType": "bool", "name": "", + "type": "bool" + } + ], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", "type": "uint8" }, { @@ -640,14 +977,8 @@ "type": "bytes" } ], - "name": "handleSynPackage", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], + "name": "handleAckPackage", + "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -666,7 +997,7 @@ "type": "bytes" } ], - "name": "handleAckPackage", + "name": "handleFailAckPackage", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -686,8 +1017,14 @@ "type": "bytes" } ], - "name": "handleFailAckPackage", - "outputs": [], + "name": "handleSynPackage", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -697,16 +1034,16 @@ "inputs": [ { "internalType": "address", - "name": "contractAddr", + "name": "bep20Addr", "type": "address" }, { - "internalType": "string", - "name": "bep2Symbol", - "type": "string" + "internalType": "uint64", + "name": "expireTime", + "type": "uint64" } ], - "name": "approveBind", + "name": "mirror", "outputs": [ { "internalType": "bool", @@ -718,6 +1055,63 @@ "stateMutability": "payable", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "mirrorFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mirrorPendingRecord", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "string", + "name": "symbol", + "type": "string" + } + ], + "name": "queryRequiredLockAmountForBind", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": false, "inputs": [ @@ -748,12 +1142,17 @@ "constant": false, "inputs": [ { - "internalType": "string", - "name": "bep2Symbol", - "type": "string" + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "expireTime", + "type": "uint64" } ], - "name": "expireBind", + "name": "sync", "outputs": [ { "internalType": "bool", @@ -767,14 +1166,8 @@ }, { "constant": true, - "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "queryRequiredLockAmountForBind", + "inputs": [], + "name": "syncFee", "outputs": [ { "internalType": "uint256", @@ -785,5 +1178,25 @@ "payable": false, "stateMutability": "view", "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/contracts/TokenManager.sol b/contracts/TokenManager.sol index 31d77e05..735b4594 100644 --- a/contracts/TokenManager.sol +++ b/contracts/TokenManager.sol @@ -41,6 +41,7 @@ contract TokenManager is System, IApplication, IParamSubscriber { struct MirrorSynPackage { address mirrorSender; address bep20Addr; + bytes32 bep20Name; bytes32 bep20Symbol; uint256 bep20Supply; uint8 bep20Decimals; @@ -54,7 +55,7 @@ contract TokenManager is System, IApplication, IParamSubscriber { address bep20Addr; uint8 bep20Decimals; bytes32 bep2Symbol; - uint256 refundAmount; + uint256 mirrorFee; uint8 errorCode; } @@ -62,6 +63,7 @@ contract TokenManager is System, IApplication, IParamSubscriber { struct SyncSynPackage { address syncSender; address bep20Addr; + bytes32 bep2Symbol; uint256 bep20Supply; uint256 syncFee; uint64 expireTime; @@ -71,7 +73,7 @@ contract TokenManager is System, IApplication, IParamSubscriber { struct SyncAckPackage { address syncSender; address bep20Addr; - uint256 refundAmount; + uint256 syncFee; uint8 errorCode; } @@ -111,6 +113,7 @@ contract TokenManager is System, IApplication, IParamSubscriber { mapping(bytes32 => BindSynPackage) public bindPackageRecord; mapping(address => bool) public mirrorPendingRecord; + mapping(address => bool) public boundByMirror; uint256 public mirrorFee; uint256 public syncFee; @@ -119,11 +122,9 @@ contract TokenManager is System, IApplication, IParamSubscriber { event unexpectedPackage(uint8 channelId, bytes msgBytes); event paramChange(string key, bytes value); event mirrorSuccess(address indexed bep20Addr, bytes32 bep2Symbol); - event mirrorFailure(address indexed bep20Addr, string reason); + event mirrorFailure(address indexed bep20Addr, uint8 errCode); event syncSuccess(address indexed bep20Addr); - event syncFailure(address indexed bep20Addr, string reason); - event refundFeeSuccess(address recipient, uint256 value); - event refundFeeFailure(address recipient, uint256 value); + event syncFailure(address indexed bep20Addr, uint8 errCode); constructor() public {} @@ -202,6 +203,7 @@ contract TokenManager is System, IApplication, IParamSubscriber { } function approveBind(address contractAddr, string memory bep2Symbol) payable public returns (bool) { + require(!mirrorPendingRecord[contractAddr], "the bep20 token is in mirror pending status"); bytes32 bep2TokenSymbol = bep2TokenSymbolConvert(bep2Symbol); BindSynPackage memory bindSynPkg = bindPackageRecord[bep2TokenSymbol]; require(bindSynPkg.bep2TokenSymbol!=bytes32(0x00), "bind request doesn't exist"); @@ -233,7 +235,6 @@ contract TokenManager is System, IApplication, IParamSubscriber { } function rejectBind(address contractAddr, string memory bep2Symbol) payable public returns (bool) { - require(!mirrorPendingRecord[contractAddr], "the bep20 token is in mirror pending status"); bytes32 bep2TokenSymbol = bep2TokenSymbolConvert(bep2Symbol); BindSynPackage memory bindSynPkg = bindPackageRecord[bep2TokenSymbol]; require(bindSynPkg.bep2TokenSymbol!=bytes32(0x00), "bind request doesn't exist"); @@ -273,14 +274,15 @@ contract TokenManager is System, IApplication, IParamSubscriber { } function encodeMirrorSynPackage(MirrorSynPackage memory mirrorSynPackage) internal pure returns (bytes memory) { - bytes[] memory elements = new bytes[](7); + bytes[] memory elements = new bytes[](8); elements[0] = mirrorSynPackage.mirrorSender.encodeAddress(); elements[1] = mirrorSynPackage.bep20Addr.encodeAddress(); - elements[2] = uint256(mirrorSynPackage.bep20Symbol).encodeUint(); - elements[3] = mirrorSynPackage.bep20Supply.encodeUint(); - elements[4] = uint256(mirrorSynPackage.bep20Decimals).encodeUint(); - elements[5] = mirrorSynPackage.mirrorFee.encodeUint(); - elements[6] = uint256(mirrorSynPackage.expireTime).encodeUint(); + elements[2] = uint256(mirrorSynPackage.bep20Name).encodeUint(); + elements[3] = uint256(mirrorSynPackage.bep20Symbol).encodeUint(); + elements[4] = mirrorSynPackage.bep20Supply.encodeUint(); + elements[5] = uint256(mirrorSynPackage.bep20Decimals).encodeUint(); + elements[6] = mirrorSynPackage.mirrorFee.encodeUint(); + elements[7] = uint256(mirrorSynPackage.expireTime).encodeUint(); return elements.encodeList(); } @@ -292,11 +294,12 @@ contract TokenManager is System, IApplication, IParamSubscriber { while (iter.hasNext()) { if (idx == 0) mirrorSynPackage.mirrorSender = iter.next().toAddress(); else if (idx == 1) mirrorSynPackage.bep20Addr = iter.next().toAddress(); - else if (idx == 2) mirrorSynPackage.bep20Symbol = bytes32(iter.next().toUint()); - else if (idx == 3) mirrorSynPackage.bep20Supply = iter.next().toUint(); - else if (idx == 4) mirrorSynPackage.bep20Decimals = uint8(iter.next().toUint()); - else if (idx == 5) mirrorSynPackage.mirrorFee = iter.next().toUint(); - else if (idx == 6) { + else if (idx == 2) mirrorSynPackage.bep20Name = bytes32(iter.next().toUint()); + else if (idx == 3) mirrorSynPackage.bep20Symbol = bytes32(iter.next().toUint()); + else if (idx == 4) mirrorSynPackage.bep20Supply = iter.next().toUint(); + else if (idx == 5) mirrorSynPackage.bep20Decimals = uint8(iter.next().toUint()); + else if (idx == 6) mirrorSynPackage.mirrorFee = iter.next().toUint(); + else if (idx == 7) { mirrorSynPackage.expireTime = uint64(iter.next().toUint()); success = true; } @@ -316,7 +319,7 @@ contract TokenManager is System, IApplication, IParamSubscriber { else if (idx == 1) mirrorAckPackage.bep20Addr = iter.next().toAddress(); else if (idx == 2) mirrorAckPackage.bep20Decimals = uint8(iter.next().toUint()); else if (idx == 3) mirrorAckPackage.bep2Symbol = bytes32(iter.next().toUint()); - else if (idx == 4) mirrorAckPackage.refundAmount = iter.next().toUint(); + else if (idx == 4) mirrorAckPackage.mirrorFee = iter.next().toUint(); else if (idx == 5) { mirrorAckPackage.errorCode = uint8(iter.next().toUint()); success = true; @@ -328,24 +331,29 @@ contract TokenManager is System, IApplication, IParamSubscriber { } function mirror(address bep20Addr, uint64 expireTime) payable public returns (bool) { - require(ITokenHub(TOKEN_HUB_ADDR).getBep2SymbolByContractAddr(bep20Addr) == bytes32(0x00), "the bep20 token has already been bound"); - require(!mirrorPendingRecord[bep20Addr], "the bep20 token is in mirror pending status"); + require(ITokenHub(TOKEN_HUB_ADDR).getBep2SymbolByContractAddr(bep20Addr) == bytes32(0x00), "already bound"); + require(!mirrorPendingRecord[bep20Addr], "mirror pending"); uint256 miniRelayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee(); require(msg.value%TEN_DECIMALS == 0 && msg.value>=mirrorFee.add(miniRelayFee), "msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee"); require(expireTime>=block.timestamp + 120 && expireTime <= block.timestamp + 86400, "expireTime must be two minutes later and one day earlier"); uint8 decimals = IBEP20(bep20Addr).decimals(); uint256 totalSupply = IBEP20(bep20Addr).totalSupply(); - require(convertToBep2Amount(totalSupply, decimals) <= MAX_BEP2_TOTAL_SUPPLY, "bep20 total supply is to large"); + require(convertToBep2Amount(totalSupply, decimals) <= MAX_BEP2_TOTAL_SUPPLY, "too large total supply"); + string memory name = IBEP20(bep20Addr).name(); + bytes memory nameBytes = bytes(name); + require(nameBytes.length>=1 && nameBytes.length<=32, "name length must be in [1,32]"); string memory symbol = IBEP20(bep20Addr).symbol(); bytes memory symbolBytes = bytes(symbol); - require(symbolBytes.length>=MINIMUM_BEP20_SYMBOL_LEN && symbolBytes.length<=MAXIMUM_BEP20_SYMBOL_LEN, "bep20 symbol length should be in [3,8]"); + require(symbolBytes.length>=MINIMUM_BEP20_SYMBOL_LEN && symbolBytes.length<=MAXIMUM_BEP20_SYMBOL_LEN, "symbol length must be in [3,8]"); for (uint8 i = 0; i < symbolBytes.length; i++) { - require((symbolBytes[i]>='a' && symbolBytes[i]<='a') || (symbolBytes[i]>='A' && symbolBytes[i]<='Z'), "bep20 symbol must not contain non-alphabet"); + require((symbolBytes[i]>='a' && symbolBytes[i]<='a') || (symbolBytes[i]>='A' && symbolBytes[i]<='Z'), "symbol must not contain non-alphabet"); } - - address(uint160(TOKEN_HUB_ADDR)).transfer(msg.value); + address(uint160(TOKEN_HUB_ADDR)).transfer(msg.value.sub(mirrorFee)); mirrorPendingRecord[bep20Addr] = true; - + bytes32 bytes32Name; + assembly { + bytes32Name := mload(add(name, 32)) + } bytes32 bytes32Symbol; assembly { bytes32Symbol := mload(add(symbol, 32)) @@ -353,10 +361,11 @@ contract TokenManager is System, IApplication, IParamSubscriber { MirrorSynPackage memory mirrorSynPackage = MirrorSynPackage({ mirrorSender: msg.sender, bep20Addr: bep20Addr, + bep20Name: bytes32Name, bep20Symbol: bytes32Symbol, bep20Supply: totalSupply, bep20Decimals: decimals, - mirrorFee: mirrorFee, + mirrorFee: mirrorFee/TEN_DECIMALS, expireTime: expireTime }); ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(MIRROR_CHANNELID, encodeMirrorSynPackage(mirrorSynPackage), msg.value.sub(mirrorFee).div(TEN_DECIMALS)); @@ -365,49 +374,41 @@ contract TokenManager is System, IApplication, IParamSubscriber { function handleMirrorAckPackage(bytes memory msgBytes) internal { (MirrorAckPackage memory mirrorAckPackage, bool decodeSuccess) = decodeMirrorAckPackage(msgBytes); - require(decodeSuccess, "unrecognized mirror syn package"); + require(decodeSuccess, "unrecognized package"); mirrorPendingRecord[mirrorAckPackage.bep20Addr] = false; if (mirrorAckPackage.errorCode == MIRROR_STATUS_SUCCESS ) { + address(uint160(TOKEN_HUB_ADDR)).transfer(mirrorAckPackage.mirrorFee); ITokenHub(TOKEN_HUB_ADDR).bindToken(mirrorAckPackage.bep2Symbol, mirrorAckPackage.bep20Addr, mirrorAckPackage.bep20Decimals); + boundByMirror[mirrorAckPackage.bep20Addr] = true; emit mirrorSuccess(mirrorAckPackage.bep20Addr, mirrorAckPackage.bep2Symbol); - } else if (mirrorAckPackage.errorCode == MIRROR_STATUS_TIMEOUT ) { - emit mirrorFailure(mirrorAckPackage.bep20Addr, "mirror timeout"); - } else if (mirrorAckPackage.errorCode == MIRROR_STATUS_DUPLICATED_BEP2_SYMBOL ) { - emit mirrorFailure(mirrorAckPackage.bep20Addr, "duplicated BEP2 symbol"); - } else if (mirrorAckPackage.errorCode == MIRROR_STATUS_ALREADY_BOUND ) { - emit mirrorFailure(mirrorAckPackage.bep20Addr, "ready bound"); + return; } else { - emit mirrorFailure(mirrorAckPackage.bep20Addr, "unknown reason"); - } - if (mirrorAckPackage.refundAmount != 0) { - (bool success, ) = mirrorAckPackage.mirrorSender.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: mirrorAckPackage.refundAmount}(""); - if (!success) { - emit refundFeeSuccess(mirrorAckPackage.mirrorSender, mirrorAckPackage.refundAmount); - } else { - emit refundFeeFailure(mirrorAckPackage.mirrorSender, mirrorAckPackage.refundAmount); - } + emit mirrorFailure(mirrorAckPackage.bep20Addr, mirrorAckPackage.errorCode); + } + (bool success, ) = mirrorAckPackage.mirrorSender.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: mirrorAckPackage.mirrorFee}(""); + if (!success) { + address(uint160(SYSTEM_REWARD_ADDR)).transfer(mirrorAckPackage.mirrorFee); } } function handleMirrorFailAckPackage(bytes memory msgBytes) internal { (MirrorSynPackage memory mirrorSynPackage, bool decodeSuccess) = decodeMirrorSynPackage(msgBytes); - require(decodeSuccess, "unrecognized mirror syn package"); + require(decodeSuccess, "unrecognized package"); mirrorPendingRecord[mirrorSynPackage.bep20Addr] = false; - (bool success, ) = mirrorSynPackage.mirrorSender.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: mirrorSynPackage.mirrorFee}(""); + (bool success, ) = mirrorSynPackage.mirrorSender.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: mirrorSynPackage.mirrorFee*TEN_DECIMALS}(""); if (!success) { - emit refundFeeSuccess(mirrorSynPackage.mirrorSender, mirrorSynPackage.mirrorFee); - } else { - emit refundFeeFailure(mirrorSynPackage.mirrorSender, mirrorSynPackage.mirrorFee); + address(uint160(SYSTEM_REWARD_ADDR)).transfer(mirrorSynPackage.mirrorFee*TEN_DECIMALS); } } function encodeSyncSynPackage(SyncSynPackage memory syncSynPackage) internal pure returns (bytes memory) { - bytes[] memory elements = new bytes[](5); + bytes[] memory elements = new bytes[](6); elements[0] = syncSynPackage.syncSender.encodeAddress(); elements[1] = syncSynPackage.bep20Addr.encodeAddress(); - elements[2] = syncSynPackage.bep20Supply.encodeUint(); - elements[3] = syncSynPackage.syncFee.encodeUint(); - elements[4] = uint256(syncSynPackage.expireTime).encodeUint(); + elements[2] = uint256(syncSynPackage.bep2Symbol).encodeUint(); + elements[3] = syncSynPackage.bep20Supply.encodeUint(); + elements[4] = syncSynPackage.syncFee.encodeUint(); + elements[5] = uint256(syncSynPackage.expireTime).encodeUint(); return elements.encodeList(); } @@ -419,9 +420,10 @@ contract TokenManager is System, IApplication, IParamSubscriber { while (iter.hasNext()) { if (idx == 0) syncSynPackage.syncSender = iter.next().toAddress(); else if (idx == 1) syncSynPackage.bep20Addr = iter.next().toAddress(); - else if (idx == 2) syncSynPackage.bep20Supply = iter.next().toUint(); - else if (idx == 3) syncSynPackage.syncFee = iter.next().toUint(); - else if (idx == 4) { + else if (idx == 2) syncSynPackage.bep2Symbol = bytes32(iter.next().toUint()); + else if (idx == 3) syncSynPackage.bep20Supply = iter.next().toUint(); + else if (idx == 4) syncSynPackage.syncFee = iter.next().toUint(); + else if (idx == 5) { syncSynPackage.expireTime = uint64(iter.next().toUint()); success = true; } @@ -439,7 +441,7 @@ contract TokenManager is System, IApplication, IParamSubscriber { while (iter.hasNext()) { if (idx == 0) syncAckPackage.syncSender = iter.next().toAddress(); else if (idx == 1) syncAckPackage.bep20Addr = iter.next().toAddress(); - else if (idx == 2) syncAckPackage.refundAmount = uint8(iter.next().toUint()); + else if (idx == 2) syncAckPackage.syncFee = iter.next().toUint(); else if (idx == 3) { syncAckPackage.errorCode = uint8(iter.next().toUint()); success = true; @@ -451,20 +453,23 @@ contract TokenManager is System, IApplication, IParamSubscriber { } function sync(address bep20Addr, uint64 expireTime) payable public returns (bool) { - require(ITokenHub(TOKEN_HUB_ADDR).getBep2SymbolByContractAddr(bep20Addr) != bytes32(0x00), "the bep20 token is not bound"); + bytes32 bep2Symbol = ITokenHub(TOKEN_HUB_ADDR).getBep2SymbolByContractAddr(bep20Addr); + require(bep2Symbol != bytes32(0x00), "not bound"); + require(boundByMirror[bep20Addr], "not bound by mirror"); uint256 miniRelayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee(); - require(msg.value%TEN_DECIMALS == 0 && msg.value>=syncFee.add(miniRelayFee), "msg.value must be N * 1e10 and greater than sum of miniRelayFee and syncFee"); + require(msg.value%TEN_DECIMALS == 0 && msg.value>=syncFee.add(miniRelayFee), "msg.value must be N * 1e10 and no less sum of miniRelayFee and syncFee"); require(expireTime>=block.timestamp + 120 && expireTime <= block.timestamp + 86400, "expireTime must be two minutes later and one day earlier"); uint256 totalSupply = IBEP20(bep20Addr).totalSupply(); uint8 decimals = IBEP20(bep20Addr).decimals(); - require(convertToBep2Amount(totalSupply, decimals) <= MAX_BEP2_TOTAL_SUPPLY, "bep20 total supply is to large"); + require(convertToBep2Amount(totalSupply, decimals) <= MAX_BEP2_TOTAL_SUPPLY, "too large total supply"); - address(uint160(TOKEN_HUB_ADDR)).transfer(msg.value); + address(uint160(TOKEN_HUB_ADDR)).transfer(msg.value.sub(syncFee)); SyncSynPackage memory syncSynPackage = SyncSynPackage({ syncSender: msg.sender, bep20Addr: bep20Addr, + bep2Symbol: bep2Symbol, bep20Supply: totalSupply, - syncFee: syncFee, + syncFee: syncFee/TEN_DECIMALS, expireTime: expireTime }); ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SYNC_CHANNELID, encodeSyncSynPackage(syncSynPackage), msg.value.sub(syncFee).div(TEN_DECIMALS)); @@ -473,39 +478,31 @@ contract TokenManager is System, IApplication, IParamSubscriber { function handleSyncAckPackage(bytes memory msgBytes) internal { (SyncAckPackage memory syncAckPackage, bool decodeSuccess) = decodeSyncAckPackage(msgBytes); - require(decodeSuccess, "unrecognized sync ack package"); + require(decodeSuccess, "unrecognized package"); if (syncAckPackage.errorCode == SYNC_STATUS_SUCCESS ) { + address(uint160(TOKEN_HUB_ADDR)).transfer(syncAckPackage.syncFee); emit syncSuccess(syncAckPackage.bep20Addr); - } else if (syncAckPackage.errorCode == SYNC_STATUS_TIMEOUT ) { - emit syncFailure(syncAckPackage.bep20Addr, "sync timeout"); - } else if (syncAckPackage.errorCode == SYNC_STATUS_NOT_BOUND_MIRROR ) { - emit syncFailure(syncAckPackage.bep20Addr, "not bound by mirror"); - } else { - emit syncFailure(syncAckPackage.bep20Addr, "unknown reason"); - } - if (syncAckPackage.refundAmount != 0) { - (bool success, ) = syncAckPackage.syncSender.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: syncAckPackage.refundAmount}(""); - if (!success) { - emit refundFeeSuccess(syncAckPackage.syncSender, syncAckPackage.refundAmount); - } else { - emit refundFeeFailure(syncAckPackage.syncSender, syncAckPackage.refundAmount); - } + return; + } else { + emit syncFailure(syncAckPackage.bep20Addr, syncAckPackage.errorCode); + } + (bool success, ) = syncAckPackage.syncSender.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: syncAckPackage.syncFee}(""); + if (!success) { + address(uint160(SYSTEM_REWARD_ADDR)).transfer(syncAckPackage.syncFee); } } function handleSyncFailAckPackage(bytes memory msgBytes) internal { (SyncSynPackage memory syncSynPackage, bool decodeSuccess) = decodeSyncSynPackage(msgBytes); - require(decodeSuccess, "unrecognized sync syn package"); - (bool success, ) = syncSynPackage.syncSender.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: syncSynPackage.syncFee}(""); + require(decodeSuccess, "unrecognized package"); + (bool success, ) = syncSynPackage.syncSender.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: syncSynPackage.syncFee*TEN_DECIMALS}(""); if (!success) { - emit refundFeeSuccess(syncSynPackage.syncSender, syncSynPackage.syncFee); - } else { - emit refundFeeFailure(syncSynPackage.syncSender, syncSynPackage.syncFee); + address(uint160(SYSTEM_REWARD_ADDR)).transfer(syncSynPackage.syncFee*TEN_DECIMALS); } } - function updateParam(string calldata key, bytes calldata value) override external onlyGov{ - require(value.length == 32, "expected value length is 32"); + function updateParam(string calldata key, bytes calldata value) override external onlyGov { + require(value.length == 32, "expected value length 32"); string memory localKey = key; bytes memory localValue = value; bytes32 bytes32Key; @@ -517,14 +514,14 @@ contract TokenManager is System, IApplication, IParamSubscriber { assembly { newMirrorFee := mload(add(localValue, 32)) } - require(newMirrorFee%(TEN_DECIMALS)==0, "the mirrorFee should be N * 10**10"); + require(newMirrorFee%(TEN_DECIMALS)==0, "mirrorFee must be N * 1e10"); mirrorFee = newMirrorFee; } else if (bytes32Key == bytes32(0x73796e6346656500000000000000000000000000000000000000000000000000)) { // syncFee uint256 newSyncFee; assembly { newSyncFee := mload(add(localValue, 32)) } - require(newSyncFee%(TEN_DECIMALS)==0, "the syncFee should be N * 10**10"); + require(newSyncFee%(TEN_DECIMALS)==0, "syncFee must be N * 1e10"); syncFee = newSyncFee; } else { require(false, "unknown param"); @@ -610,12 +607,4 @@ contract TokenManager is System, IApplication, IParamSubscriber { } return amount.mul(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); } - - function convertFromBep2Amount(uint256 amount, uint256 bep20TokenDecimals) internal pure returns (uint256) { - if (bep20TokenDecimals > BEP2_TOKEN_DECIMALS) { - return amount.mul(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS)); - } - return amount.div(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); - } - } diff --git a/contracts/test/XYZToken.sol b/contracts/test/XYZToken.sol new file mode 100644 index 00000000..47c16900 --- /dev/null +++ b/contracts/test/XYZToken.sol @@ -0,0 +1,298 @@ +pragma solidity 0.6.4; + +import "../interface/IBEP20.sol"; +import "openzeppelin-solidity/contracts/GSN/Context.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "openzeppelin-solidity/contracts/access/Ownable.sol"; + +contract XYZToken is Context, IBEP20, Ownable { + using SafeMath for uint256; + + mapping (address => uint256) private _balances; + + mapping (address => mapping (address => uint256)) private _allowances; + + uint256 private _totalSupply; + uint8 private _decimals; + string private _symbol; + string private _name; + + constructor() public { + _name = "XYZ token"; + _symbol = "XYZ"; + _decimals = 18; + _totalSupply = 100000000000000000000000000; + _balances[msg.sender] = _totalSupply; + + emit Transfer(address(0), msg.sender, _totalSupply); + } + + /** + * @dev Just for test + * + * - `newName` new name + */ + function setName(string calldata newName) external { + _name = newName; + } + + /** + * @dev Just for test + * + * - `newDecimals` new decimals + */ + function setDecimals(uint8 newDecimals) external { + _decimals = newDecimals; + } + + /** + * @dev Just for test + * + * - `newTotalSupply` new totalSupply + */ + function setTotalSupply(uint256 newTotalSupply) external { + _totalSupply = newTotalSupply; + } + + + /** + * @dev Just for test + * + * - `newSymbol` new symbol + */ + function setSymbol(string calldata newSymbol) external { + _symbol = newSymbol; + } + + /** + * @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 (uint8) { + return _decimals; + } + + /** + * @dev Returns the token symbol. + */ + function symbol() external override view returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the token name. + */ + function name() external override view returns (string memory) { + return _name; + } + + /** + * @dev See {BEP20-totalSupply}. + */ + function totalSupply() external override view returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {BEP20-balanceOf}. + */ + function balanceOf(address account) external override view returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {BEP20-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 {BEP20-allowance}. + */ + function allowance(address owner, address spender) external override view returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {BEP20-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 {BEP20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {BEP20}; + * + * 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, "BEP20: 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 {BEP20-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 {BEP20-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, "BEP20: decreased allowance below zero")); + return true; + } + + /** + * @dev Creates `amount` tokens and assigns them to `msg.sender`, increasing + * the total supply. + * + * Requirements + * + * - `msg.sender` must be the token owner + */ + function mint(uint256 amount) public onlyOwner returns (bool) { + _mint(_msgSender(), amount); + 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), "BEP20: transfer from the zero address"); + require(recipient != address(0), "BEP20: transfer to the zero address"); + + _balances[sender] = _balances[sender].sub(amount, "BEP20: 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), "BEP20: 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), "BEP20: burn from the zero address"); + + _balances[account] = _balances[account].sub(amount, "BEP20: 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), "BEP20: approve from the zero address"); + require(spender != address(0), "BEP20: 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, "BEP20: burn amount exceeds allowance")); + } +} \ No newline at end of file diff --git a/genesis.json b/genesis.json index 84e71a0e..2634424f 100644 --- a/genesis.json +++ b/genesis.json @@ -47,7 +47,7 @@ }, "0x0000000000000000000000000000000000001004": { "balance": "176405560900000000000000000", - "code": "0x60806040526004361061031e5760003560e01c80639a99b4f0116101ab578063bd466461116100f7578063f014847211610095578063fc1a598f1161006f578063fc1a598f14610cb3578063fc3e5908146109c9578063fd6a687914610ce6578063ff9c0027146107c757610366565b8063f014847214610c74578063f9a2bbc714610c89578063fa9e915914610c9e57610366565b8063dc6f5e90116100d1578063dc6f5e90146109c9578063dc927faf14610c35578063e1c7392a14610c4a578063ebf71d5314610c5f57610366565b8063bd46646114610b68578063c81b166214610b9b578063c8509d8114610bb057610366565b8063a7c9f02d11610164578063ac4317511161013e578063ac43175114610a3a578063b770186114610b05578063b99328c514610b1a578063b9fd21e314610b5357610366565b8063a7c9f02d146109c9578063aa7415f5146109de578063ab51bb9614610a2557610366565b80639a99b4f0146109095780639dc0926214610942578063a1a11bf514610957578063a496fba21461096c578063a5cd588b14610981578063a78abc16146109b457610366565b80635d499b1b1161026a57806375d47a0a116102235780638b87b21f116101fd5780638b87b21f146105b25780638eff336c146108a057806396713da9146108df5780639a854bbd146108f457610366565b806375d47a0a146107f15780637942fd0514610806578063831d65d11461081b57610366565b80635d499b1b14610671578063613684751461036b5780636e056520146106865780636e47b482146107b257806370fd5bad146107c757806371d30863146107dc57610366565b806343756e5c116102d75780634bf6c882116102b15780634bf6c8821461036b57806350432d321461061d57806351e806721461063257806359b927891461064757610366565b806343756e5c146105c757806343a368b9146105dc578063493279b1146105f157610366565b8063077b8f351461036b5780630bee7a67146103965780631182b875146103c4578063149d14d9146104be5780633d713223146104e55780633dffc387146105b257610366565b36610366573415610364576040805133815234602082015281517f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db929181900390910190a15b005b600080fd5b34801561037757600080fd5b50610380610cfb565b6040805160ff9092168252519081900360200190f35b3480156103a257600080fd5b506103ab610d00565b6040805163ffffffff9092168252519081900360200190f35b3480156103d057600080fd5b50610449600480360360408110156103e757600080fd5b60ff8235169190810190604081016020820135600160201b81111561040b57600080fd5b82018360208201111561041d57600080fd5b803590602001918460018302840111600160201b8311171561043e57600080fd5b509092509050610d05565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561048357818101518382015260200161046b565b50505050905090810190601f1680156104b05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104ca57600080fd5b506104d3610e33565b60408051918252519081900360200190f35b3480156104f157600080fd5b506105966004803603602081101561050857600080fd5b810190602081018135600160201b81111561052257600080fd5b82018360208201111561053457600080fd5b803590602001918460018302840111600160201b8311171561055557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610e39945050505050565b604080516001600160a01b039092168252519081900360200190f35b3480156105be57600080fd5b50610380610e5d565b3480156105d357600080fd5b50610596610e62565b3480156105e857600080fd5b506104d3610e68565b3480156105fd57600080fd5b50610606610e74565b6040805161ffff9092168252519081900360200190f35b34801561062957600080fd5b506104d3610e79565b34801561063e57600080fd5b50610596610e84565b34801561065357600080fd5b506105966004803603602081101561066a57600080fd5b5035610e8a565b34801561067d57600080fd5b506104d3610ea5565b61079e6004803603608081101561069c57600080fd5b810190602081018135600160201b8111156106b657600080fd5b8201836020820111156106c857600080fd5b803590602001918460208302840111600160201b831117156106e957600080fd5b919390929091602081019035600160201b81111561070657600080fd5b82018360208201111561071857600080fd5b803590602001918460208302840111600160201b8311171561073957600080fd5b919390929091602081019035600160201b81111561075657600080fd5b82018360208201111561076857600080fd5b803590602001918460208302840111600160201b8311171561078957600080fd5b91935091503567ffffffffffffffff16610eae565b604080519115158252519081900360200190f35b3480156107be57600080fd5b50610596611383565b3480156107d357600080fd5b50610380611389565b3480156107e857600080fd5b506104d361138e565b3480156107fd57600080fd5b50610596611394565b34801561081257600080fd5b5061038061139a565b34801561082757600080fd5b506103646004803603604081101561083e57600080fd5b60ff8235169190810190604081016020820135600160201b81111561086257600080fd5b82018360208201111561087457600080fd5b803590602001918460018302840111600160201b8311171561089557600080fd5b50909250905061139f565b3480156108ac57600080fd5b50610364600480360360608110156108c357600080fd5b508035906001600160a01b0360208201351690604001356114e8565b3480156108eb57600080fd5b5061038061156e565b34801561090057600080fd5b506104d3611573565b34801561091557600080fd5b506104d36004803603604081101561092c57600080fd5b506001600160a01b03813516906020013561157f565b34801561094e57600080fd5b506105966116bd565b34801561096357600080fd5b506105966116c3565b34801561097857600080fd5b506103806116c9565b34801561098d57600080fd5b506104d3600480360360208110156109a457600080fd5b50356001600160a01b03166116ce565b3480156109c057600080fd5b5061079e6116e0565b3480156109d557600080fd5b506103806116e9565b61079e600480360360808110156109f457600080fd5b5080356001600160a01b03908116916020810135909116906040810135906060013567ffffffffffffffff166116ee565b348015610a3157600080fd5b506103ab6116c9565b348015610a4657600080fd5b5061036460048036036040811015610a5d57600080fd5b810190602081018135600160201b811115610a7757600080fd5b820183602082011115610a8957600080fd5b803590602001918460018302840111600160201b83111715610aaa57600080fd5b919390929091602081019035600160201b811115610ac757600080fd5b820183602082011115610ad957600080fd5b803590602001918460018302840111600160201b83111715610afa57600080fd5b509092509050611daf565b348015610b1157600080fd5b506104d361201e565b348015610b2657600080fd5b5061036460048036036040811015610b3d57600080fd5b50803590602001356001600160a01b0316612024565b348015610b5f57600080fd5b506104d361209a565b348015610b7457600080fd5b506104d360048036036020811015610b8b57600080fd5b50356001600160a01b03166120a4565b348015610ba757600080fd5b506105966120bf565b348015610bbc57600080fd5b5061036460048036036040811015610bd357600080fd5b60ff8235169190810190604081016020820135600160201b811115610bf757600080fd5b820183602082011115610c0957600080fd5b803590602001918460018302840111600160201b83111715610c2a57600080fd5b5090925090506120c5565b348015610c4157600080fd5b50610596612195565b348015610c5657600080fd5b5061036461219b565b348015610c6b57600080fd5b5061038061223b565b348015610c8057600080fd5b50610380612240565b348015610c9557600080fd5b50610596612245565b348015610caa57600080fd5b506104d361224b565b348015610cbf57600080fd5b5061044960048036036020811015610cd657600080fd5b50356001600160a01b0316612251565b348015610cf257600080fd5b50610596612378565b600881565b606481565b60005460609060ff16610d4d576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b3361200014610d8d5760405162461bcd60e51b815260040180806020018281038252602f81526020018061476d602f913960400191505060405180910390fd5b60ff841660021415610ddf57610dd883838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237e92505050565b9050610e2c565b6040805162461bcd60e51b815260206004820152601860248201527f756e7265636f676e697a65642073796e207061636b6167650000000000000000604482015290519081900360640190fd5b9392505050565b60015490565b6020818101516000908152600490915260409020546001600160a01b03165b919050565b600181565b61100181565b670de0b6b3a764000081565b606081565b66038d7ea4c6800081565b61200081565b6000908152600460205260409020546001600160a01b031690565b6402540be40081565b6000805460ff16610ef4576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b868514610f325760405162461bcd60e51b815260040180806020018281038252603b815260200180614732603b913960400191505060405180910390fd5b868314610f705760405162461bcd60e51b815260040180806020018281038252603f815260200180614605603f913960400191505060405180910390fd5b426078018267ffffffffffffffff161015610fbc5760405162461bcd60e51b81526004018080602001828103825260248152602001806144f56024913960400191505060405180910390fd5b6402540be4003406156110005760405162461bcd60e51b81526004018080602001828103825260408152602001806148356040913960400191505060405180910390fd5b60408051868152602080880282010190915285906000908190606090848015611033578160200160208202803683370190505b50905060005b8481101561110e576402540be4008b8b8381811061105357fe5b905060200201358161106157fe5b061561109e5760405162461bcd60e51b815260040180806020018281038252603c815260200180614644603c913960400191505060405180910390fd5b6110c38b8b838181106110ad57fe5b90506020020135856124a290919063ffffffff16565b93506110ef6402540be4008c8c848181106110da57fe5b905060200201356124fc90919063ffffffff16565b8282815181106110fb57fe5b6020908102919091010152600101611039565b5060015461113390611126908663ffffffff61253e16565b849063ffffffff6124a216565b3410156111715760405162461bcd60e51b81526004018080602001828103825260568152602001806147df6056913960600191505060405180910390fd5b611181348463ffffffff61259716565b915061118b61434e565b6040518060c001604052806221272160e91b60001b815260200160006001600160a01b031681526020018381526020018e8e808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208c810282810182019093528c82529283019290918d918d91829185019084908082843760009201919091525050509082525067ffffffffffffffff8916602090910152905061200063f7a251d7600361124f846125d9565b611264876402540be40063ffffffff6124fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156112c25781810151838201526020016112aa565b50505050905090810190601f1680156112ef5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561131057600080fd5b505af1158015611324573d6000803e3d6000fd5b505060408051600081523360208201528082018890526060810187905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a15060019c9b505050505050505050505050565b61100581565b600281565b60015481565b61100881565b600b81565b60005460ff166113e4576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b33612000146114245760405162461bcd60e51b815260040180806020018281038252602f81526020018061476d602f913960400191505060405180910390fd5b60ff8316600314156114745761146f82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061289492505050565b6114e3565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a15b505050565b33611008146115285760405162461bcd60e51b815260040180806020018281038252602381526020018061479c6023913960400191505060405180910390fd5b600083815260046020908152604080832080546001600160a01b039096166001600160a01b03199096168617905593825260038152838220949094556002909352912055565b600981565b677ce66c50e284000081565b6000805460ff166115c5576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b33611005146116055760405162461bcd60e51b815260040180806020018281038252602f815260200180614468602f913960400191505060405180910390fd5b60004783106116145747611616565b825b9050670de0b6b3a76400008111156116325760009150506116b7565b80156116b4576040516001600160a01b0385169082156108fc029083906000818181858888f1935050505015801561166e573d6000803e3d6000fd5b50604080516001600160a01b03861681526020810183905281517ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0929181900390910190a15b90505b92915050565b61100781565b61100681565b600081565b60026020526000908152604090205481565b60005460ff1681565b600381565b6000805460ff16611734576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b426078018267ffffffffffffffff1610156117805760405162461bcd60e51b81526004018080602001828103825260248152602001806144f56024913960400191505060405180910390fd5b6402540be4003406156117c45760405162461bcd60e51b81526004018080602001828103825260408152602001806148356040913960400191505060405180910390fd5b600080806001600160a01b0388166118a3576001546117ea90879063ffffffff6124a216565b3410156118285760405162461bcd60e51b815260040180806020018281038252606181526020018061457f6061913960800191505060405180910390fd5b6402540be40086061561186c5760405162461bcd60e51b815260040180806020018281038252603c815260200180614644603c913960400191505060405180910390fd5b61187c348763ffffffff61259716565b9050611893866402540be40063ffffffff6124fc16565b6221272160e91b93509150611b46565b6001600160a01b0388166000908152600360205260409020549250826118fa5760405162461bcd60e51b815260040180806020018281038252603181526020018061454e6031913960400191505060405180910390fd5b60015434101561193b5760405162461bcd60e51b815260040180806020018281038252603f8152602001806146a1603f913960400191505060405180910390fd5b506001600160a01b038716600090815260026020526040902054349060088111158061198657506008811180156119865750611984876007198301600a0a63ffffffff6128f016565b155b6119c15760405162461bcd60e51b815260040180806020018281038252603c815260200180614644603c913960400191505060405180910390fd5b6119cb8782612932565b92506119d684612972565b15611a1e576305f5e100831015611a1e5760405162461bcd60e51b815260040180806020018281038252603a815260200180614497603a913960400191505060405180910390fd5b600881101580611a385750600881108015611a3857508683115b611a735760405162461bcd60e51b81526004018080602001828103825260258152602001806145e06025913960400191505060405180910390fd5b677ce66c50e2840000831115611aba5760405162461bcd60e51b81526004018080602001828103825260358152602001806145196035913960400191505060405180910390fd5b604080516323b872dd60e01b81523360048201523060248201526044810189905290516001600160a01b038b16916323b872dd9160648083019260209291908290030181600087803b158015611b0f57600080fd5b505af1158015611b23573d6000803e3d6000fd5b505050506040513d6020811015611b3957600080fd5b5051611b4457600080fd5b505b611b4e61434e565b6040805160c0810182528581526001600160a01b038b166020820152815160018082528184018452919283019181602001602082028036833750505081526040805160018082528183019092526020928301929091908083019080368337505050815260408051600180825281830190925260209283019290919080830190803683370190505081526020018767ffffffffffffffff168152509050828160400151600081518110611bfc57fe5b602002602001018181525050878160600151600081518110611c1a57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050338160800151600081518110611c4c57fe5b6001600160a01b039092166020928302919091019091015261200063f7a251d76003611c77846125d9565b611c8c866402540be40063ffffffff6124fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611cea578181015183820152602001611cd2565b50505050905090810190601f168015611d175780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015611d3857600080fd5b505af1158015611d4c573d6000803e3d6000fd5b5050604080516001600160a01b038d1681523360208201528082018b90526060810186905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a150600198975050505050505050565b3361100714611def5760405162461bcd60e51b815260040180806020018281038252602e8152602001806146e0602e913960400191505060405180910390fd5b60208114611e44576040805162461bcd60e51b815260206004820152601b60248201527f65787065637465642076616c7565206c656e6774682069732033320000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152939450606093925086915085908190840183828082843760009201919091525050505060208301519091506772656c617946656560c01b811415611f4c576020820151670de0b6b3a76400008111801590611ef357506402540be4008106155b611f44576040805162461bcd60e51b815260206004820152601960248201527f7468652072656c6179466565206f7574206f662072616e676500000000000000604482015290519081900360640190fd5b600155611f89565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b61c35081565b33611008146120645760405162461bcd60e51b815260040180806020018281038252602381526020018061479c6023913960400191505060405180910390fd5b600091825260046020908152604080842080546001600160a01b03191690556001600160a01b0392909216835260039052812055565b6221272160e91b81565b6001600160a01b031660009081526003602052604090205490565b61100281565b60005460ff1661210a576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b336120001461214a5760405162461bcd60e51b815260040180806020018281038252602f81526020018061476d602f913960400191505060405180910390fd5b60ff8316600314156114745761146f82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a7892505050565b61100381565b60005460ff16156121f3576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b66038d7ea4c6800060019081556000808052600260205260127fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b55805460ff19169091179055565b600481565b600581565b61100081565b61271081565b6001600160a01b03811660009081526003602090815260409182902054825182815280840190935260609290918391906020820181803683375050506020810183905290506000805b60208160ff1610156122e157828160ff16815181106122b557fe5b01602001516001600160f81b031916156122d4576001909101906122d9565b6122e1565b60010161229a565b5060608160ff166040519080825280601f01601f191660200182016040528015612312576020820181803683370190505b50905060005b8260ff168160ff16101561236e57838160ff168151811061233557fe5b602001015160f81c60f81b828260ff168151811061234f57fe5b60200101906001600160f81b031916908160001a905350600101612318565b5095945050505050565b61100481565b606061238861439a565b600061239384612b76565b91509150806123e9576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b60006123f483612cb5565b905063ffffffff811615612488576040808401516020808601516001600160a01b0316600090815260029091529182205461242f9190612932565b90506124396143cf565b60405180608001604052808660000151815260200183815260200186608001516001600160a01b031681526020018463ffffffff16815250905061247c81613002565b95505050505050610e58565b50506040805160008152602081019091529150610e589050565b6000828201838110156116b4576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006116b483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506130de565b60008261254d575060006116b7565b8282028284828161255a57fe5b04146116b45760405162461bcd60e51b81526004018080602001828103825260218152602001806146806021913960400191505060405180910390fd5b60006116b483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613180565b60408051600680825260e08201909252606091829190816020015b60608152602001906001900390816125f45750508351909150612616906131da565b8160008151811061262357fe5b602002602001018190525061264483602001516001600160a01b03166131ed565b8160018151811061265157fe5b60200260200101819052506000836040015151905060608160405190808252806020026020018201604052801561269c57816020015b60608152602001906001900390816126875790505b50905060005b828110156126e9576126ca866040015182815181106126bd57fe5b60200260200101516131da565b8282815181106126d657fe5b60209081029190910101526001016126a2565b506126f381613210565b8360028151811061270057fe5b602002602001018190525060608260405190808252806020026020018201604052801561274157816020015b606081526020019060019003908161272c5790505b50905060005b83811015612797576127788760600151828151811061276257fe5b60200260200101516001600160a01b03166131ed565b82828151811061278457fe5b6020908102919091010152600101612747565b506127a181613210565b846003815181106127ae57fe5b60200260200101819052506060836040519080825280602002602001820160405280156127ef57816020015b60608152602001906001900390816127da5790505b50905060005b8481101561282f576128108860800151828151811061276257fe5b82828151811061281c57fe5b60209081029190910101526001016127f5565b5061283981613210565b8560048151811061284657fe5b60200260200101819052506128688760a0015167ffffffffffffffff166131da565b8560058151811061287557fe5b602002602001018190525061288985613210565b979650505050505050565b61289c6143f6565b60006128a78361329a565b91509150806128e75760405162461bcd60e51b815260040180806020018281038252602481526020018061470e6024913960400191505060405180910390fd5b6114e382613465565b60006116b483836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f00000000000000008152506138e9565b6000600882111561295b57612954836007198401600a0a63ffffffff6124fc16565b90506116b7565b6116b4836008849003600a0a63ffffffff61253e16565b604080516020808252818301909252600091606091906020820181803683375050506020810184905290506000805b60208160ff1610156129e857828160ff16815181106129bc57fe5b01602001516001600160f81b031916156129db576001909101906129e0565b6129e8565b6001016129a1565b50600860ff82161015612a0057600092505050610e58565b816005820360ff1681518110612a1257fe5b6020910101516001600160f81b031916602d60f81b14612a3757600092505050610e58565b816001820360ff1681518110612a4957fe5b6020910101516001600160f81b031916604d60f81b14612a6e57600092505050610e58565b5060019392505050565b612a8061434e565b6000612a8b8361394b565b9150915080612acb5760405162461bcd60e51b81526004018080602001828103825260248152602001806144d16024913960400191505060405180910390fd5b612ad36143f6565b602080840180516001600160a01b0390811684526040808701518585015291511660009081526002909252812054905b846040015151811015612b5457612b3185604001518281518110612b2357fe5b602002602001015183613bc6565b85604001518281518110612b4157fe5b6020908102919091010152600101612b03565b506080840151604083015260056060830152612b6f82613465565b5050505050565b612b7e61439a565b6000612b8861439a565b612b9061442d565b612ba1612b9c86613bff565b613c24565b90506000805b612bb083613c6e565b15612ca85780612bd257612bcb612bc684613c8f565b613cdd565b8452612ca0565b8060011415612bff57612bec612be784613c8f565b613d94565b6001600160a01b03166020850152612ca0565b8060021415612c1e57612c14612bc684613c8f565b6040850152612ca0565b8060031415612c4657612c33612be784613c8f565b6001600160a01b03166060850152612ca0565b8060041415612c6e57612c5b612be784613c8f565b6001600160a01b03166080850152612ca0565b8060051415612c9b57612c83612bc684613c8f565b67ffffffffffffffff1660a085015260019150612ca0565b612ca8565b600101612ba7565b5091935090915050915091565b60208101516000906001600160a01b0316612dec578160a0015167ffffffffffffffff16421115612ce857506001610e58565b8160400151471015612cfc57506003610e58565b606082015160408084015190516000926001600160a01b0316916127109184818181858888f193505050503d8060008114612d53576040519150601f19603f3d011682016040523d82523d6000602084013e612d58565b606091505b5050905080612d6b575060049050610e58565b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5983602001518460600151856040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060009050610e58565b8160a0015167ffffffffffffffff16421115612e0a57506001610e58565b81516020808401516001600160a01b031660009081526003909152604090205414612e3757506002610e58565b602080830151604080516370a0823160e01b815230600482015290516000936001600160a01b03909316926370a082319261c3509260248083019392829003018187803b158015612e8757600080fd5b5086fa158015612e9b573d6000803e3d6000fd5b50505050506040513d6020811015612eb257600080fd5b50516040840151909150811015612ecd575060039050610e58565b600083602001516001600160a01b031663a9059cbb61c350866060015187604001516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015612f3e57600080fd5b5087f1158015612f52573d6000803e3d6000fd5b50505050506040513d6020811015612f6957600080fd5b505190508015612ff6577f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5984602001518560600151866040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060009150610e589050565b5060059150610e589050565b60408051600480825260a08201909252606091829190816020015b606081526020019060019003908161301d575050835190915061303f906131da565b8160008151811061304c57fe5b602002602001018190525061306483602001516131da565b8160018151811061307157fe5b602002602001018190525061309283604001516001600160a01b03166131ed565b8160028151811061309f57fe5b60200260200101819052506130bd836060015163ffffffff166131da565b816003815181106130ca57fe5b6020026020010181905250610e2c81613210565b6000818361316a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561312f578181015183820152602001613117565b50505050905090810190601f16801561315c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161317657fe5b0495945050505050565b600081848411156131d25760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561312f578181015183820152602001613117565b505050900390565b60606116b76131e883613dae565b613e94565b60408051600560a21b8318601482015260348101909152606090610e2c81613e94565b60608151600014156132315750604080516000815260208101909152610e58565b60608260008151811061324057fe5b602002602001015190506000600190505b8351811015613281576132778285838151811061326a57fe5b6020026020010151613ee6565b9150600101613251565b50610e2c613294825160c060ff16613f63565b82613ee6565b6132a26143f6565b60006132ac6143f6565b6132b461442d565b6132c0612b9c86613bff565b90506000805b6132cf83613c6e565b15612ca857806132f5576132e5612be784613c8f565b6001600160a01b0316845261345d565b806001141561339657606061331161330c85613c8f565b61405b565b9050805160405190808252806020026020018201604052801561333e578160200160208202803683370190505b50602086015260005b815181101561338f5761336c82828151811061335f57fe5b6020026020010151613cdd565b8660200151828151811061337c57fe5b6020908102919091010152600101613347565b505061345d565b80600214156134385760606133ad61330c85613c8f565b905080516040519080825280602002602001820160405280156133da578160200160208202803683370190505b50604086015260005b815181101561338f576134088282815181106133fb57fe5b6020026020010151613d94565b8660400151828151811061341857fe5b6001600160a01b03909216602092830291909101909101526001016133e3565b8060031415612c9b5761344d612bc684613c8f565b63ffffffff166060850152600191505b6001016132c6565b80516001600160a01b031661368f5760005b8160200151518110156136895760008260400151828151811061349657fe5b60200260200101516001600160a01b0316612710846020015184815181106134ba57fe5b60209081029190910101516040516000818181858888f193505050503d8060008114613502576040519150601f19603f3d011682016040523d82523d6000602084013e613507565b606091505b50509050806135ca577f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061354657fe5b60200260200101518560200151858151811061355e57fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a1613680565b7fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a83600001518460400151848151811061360057fe5b60200260200101518560200151858151811061361857fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101613477565b506138e6565b60005b8160200151518110156138e457600082600001516001600160a01b031663a9059cbb61c350856040015185815181106136c757fe5b6020026020010151866020015186815181106136df57fe5b60200260200101516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b15801561373657600080fd5b5087f115801561374a573d6000803e3d6000fd5b50505050506040513d602081101561376157600080fd5b505190508015613825577fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a8360000151846040015184815181106137a157fe5b6020026020010151856020015185815181106137b957fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a16138db565b7f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061385b57fe5b60200260200101518560200151858151811061387357fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101613692565b505b50565b600081836139385760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561312f578181015183820152602001613117565b5082848161394257fe5b06949350505050565b61395361434e565b600061395d61434e565b61396561442d565b613971612b9c86613bff565b90506000805b61398083613c6e565b15613bb8578061399d57613996612bc684613c8f565b8452613bb0565b80600114156139c5576139b2612be784613c8f565b6001600160a01b03166020850152613bb0565b8060021415613a545760606139dc61330c85613c8f565b90508051604051908082528060200260200182016040528015613a09578160200160208202803683370190505b50604086015260005b8151811015613a4d57613a2a82828151811061335f57fe5b86604001518281518110613a3a57fe5b6020908102919091010152600101613a12565b5050613bb0565b8060031415613ae9576060613a6b61330c85613c8f565b90508051604051908082528060200260200182016040528015613a98578160200160208202803683370190505b50606086015260005b8151811015613a4d57613ab98282815181106133fb57fe5b86606001518281518110613ac957fe5b6001600160a01b0390921660209283029190910190910152600101613aa1565b8060041415613b7e576060613b0061330c85613c8f565b90508051604051908082528060200260200182016040528015613b2d578160200160208202803683370190505b50608086015260005b8151811015613a4d57613b4e8282815181106133fb57fe5b86608001518281518110613b5e57fe5b6001600160a01b0390921660209283029190910190910152600101613b36565b8060051415613bab57613b93612bc684613c8f565b67ffffffffffffffff1660a085015260019150613bb0565b613bb8565b600101613977565b509195600195509350505050565b60006008821115613be857612954836007198401600a0a63ffffffff61253e16565b6116b4836008849003600a0a63ffffffff6124fc16565b613c0761444d565b506040805180820190915281518152602082810190820152919050565b613c2c61442d565b613c358261412c565b613c3e57600080fd5b6000613c4d836020015161415c565b60208085015160408051808201909152868152920190820152915050919050565b6000613c7861444d565b505080518051602091820151919092015191011190565b613c9761444d565b613ca082613c6e565b613ca957600080fd5b60208201516000613cb9826141bf565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590613cf257508151602110155b613cfb57600080fd5b6000613d0a836020015161415c565b90508083600001511015613d65576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015613d8b57826020036101000a820491505b50949350505050565b8051600090601514613da557600080fd5b6116b782613cdd565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416613df257506018613e16565b6fffffffffffffffffffffffffffffffff198416613e1257506010613e16565b5060005b6020811015613e4c57818181518110613e2b57fe5b01602001516001600160f81b03191615613e4457613e4c565b600101613e16565b60008160200390506060816040519080825280601f01601f191660200182016040528015613e81576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015613ec65750607f60f81b82600081518110613eb457fe5b01602001516001600160f81b03191611155b15613ed2575080610e58565b6116b7613ee48351608060ff16613f63565b835b6060806040519050835180825260208201818101602087015b81831015613f17578051835260209283019201613eff565b50855184518101855292509050808201602086015b81831015613f44578051835260209283019201613f2c565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310613fb3576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b6040805160018082528183019092526060916020820181803683370190505090506037841161400d5782840160f81b81600081518110613fef57fe5b60200101906001600160f81b031916908160001a90535090506116b7565b606061401885613dae565b90508381510160370160f81b8260008151811061403157fe5b60200101906001600160f81b031916908160001a9053506140528282613ee6565b95945050505050565b60606140668261412c565b61406f57600080fd5b600061407a836142f2565b90506060816040519080825280602002602001820160405280156140b857816020015b6140a561444d565b81526020019060019003908161409d5790505b50905060006140ca856020015161415c565b60208601510190506000805b84811015614121576140e7836141bf565b915060405180604001604052808381526020018481525084828151811061410a57fe5b6020908102919091010152918101916001016140d6565b509195945050505050565b805160009061413d57506000610e58565b6020820151805160001a9060c0821015612a6e57600092505050610e58565b8051600090811a6080811015614176576000915050610e58565b60b8811080614191575060c08110801590614191575060f881105b156141a0576001915050610e58565b60c08110156141b45760b519019050610e58565b60f519019050610e58565b80516000908190811a60808110156141da57600191506142eb565b60b88110156141ef57607e19810191506142eb565b60c081101561426957600060b78203600186019550806020036101000a865104915060018101820193505080831015614263576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b506142eb565b60f881101561427e5760be19810191506142eb565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156142e9576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b805160009061430357506000610e58565b60008090506000614317846020015161415c565b602085015185519181019250015b8082101561434557614336826141bf565b60019093019290910190614325565b50909392505050565b6040518060c001604052806000801916815260200160006001600160a01b03168152602001606081526020016060815260200160608152602001600067ffffffffffffffff1681525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806080016040528060006001600160a01b031681526020016060815260200160608152602001600063ffffffff1681525090565b604051806040016040528061444061444d565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d75737420626520696e63656e746976697a6520636f6e7472616374466f72206d696e69546f6b656e2c20746865207472616e7366657220616d6f756e74206d757374206e6f74206265206c657373207468616e2031756e7265636f676e697a6564207472616e736665724f75742073796e207061636b61676565787069726554696d65206d7573742062652074776f206d696e75746573206c61746572616d6f756e7420697320746f6f206c617267652c20657863656564206d6178696d756d206265703220746f6b656e20616d6f756e7474686520636f6e747261637420686173206e6f74206265656e20626f756e6420746f20616e79206265703220746f6b656e726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e736665724f757420424e4220616d6f756e7420616e64206d696e696d756d2072656c6179466565616d6f756e7420697320746f6f206c617267652c2075696e74323536206f766572666c6f774c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620726566756e644164647273696e76616c6964207472616e7366657220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e20746865206d696e696d756d2072656c6179466565746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374756e7265636f676e697a6564207472616e736665724f75742061636b207061636b6167654c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620616d6f756e7473746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d73672073656e646572206d75737420626520746f6b656e4d616e6167657274686520636f6e7472616374206e6f7420696e69742079657400000000000000726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e7366657220424e4220616d6f756e7420616e642072656c6179466565696e76616c696420726563656976656420424e4220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6ea2646970667358221220f7e6a34f0951e5ab20f9f010d95358c941f0349c9af1e8155517823dc73634ff64736f6c63430006040033" + "code": "0x60806040526004361061031e5760003560e01c80639a99b4f0116101ab578063bd466461116100f7578063f014847211610095578063fc1a598f1161006f578063fc1a598f14610cb3578063fc3e590814610686578063fd6a687914610ce6578063ff9c0027146107dc57610366565b8063f014847214610c74578063f9a2bbc714610c89578063fa9e915914610c9e57610366565b8063d9e6dae9116100d1578063d9e6dae914610608578063dc927faf14610c35578063e1c7392a14610c4a578063ebf71d5314610c5f57610366565b8063bd46646114610b68578063c81b166214610b9b578063c8509d8114610bb057610366565b8063aa7415f511610164578063b99328c51161013e578063b99328c514610ad2578063b9fd21e314610b0b578063ba35ead614610b20578063bbface1f14610b3557610366565b8063aa7415f5146109ab578063ab51bb96146109f2578063ac43175114610a0757610366565b80639a99b4f01461091e5780639dc0926214610957578063a1a11bf51461096c578063a496fba214610981578063a78abc1614610996578063a7c9f02d1461068657610366565b8063613684751161026a57806375d47a0a116102235780638b87b21f116101fd5780638b87b21f146105875780638eff336c146108b557806396713da9146108f45780639a854bbd1461090957610366565b806375d47a0a146108065780637942fd051461081b578063831d65d11461083057610366565b8063613684751461060857806366dea52a146106865780636e0565201461069b5780636e47b482146107c757806370fd5bad146107dc57806371d30863146107f157610366565b806343a368b9116102d757806350432d32116102b157806350432d321461061d57806351e806721461063257806359b92789146106475780635d499b1b1461067157610366565b806343a368b9146105c7578063493279b1146105dc5780634bf6c8821461060857610366565b80630bee7a671461036b5780631182b87514610399578063149d14d9146104935780633d713223146104ba5780633dffc3871461058757806343756e5c146105b257610366565b36610366573415610364576040805133815234602082015281517f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db929181900390910190a15b005b600080fd5b34801561037757600080fd5b50610380610cfb565b6040805163ffffffff9092168252519081900360200190f35b3480156103a557600080fd5b5061041e600480360360408110156103bc57600080fd5b60ff8235169190810190604081016020820135600160201b8111156103e057600080fd5b8201836020820111156103f257600080fd5b803590602001918460018302840111600160201b8311171561041357600080fd5b509092509050610d00565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610458578181015183820152602001610440565b50505050905090810190601f1680156104855780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561049f57600080fd5b506104a8610e2e565b60408051918252519081900360200190f35b3480156104c657600080fd5b5061056b600480360360208110156104dd57600080fd5b810190602081018135600160201b8111156104f757600080fd5b82018360208201111561050957600080fd5b803590602001918460018302840111600160201b8311171561052a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610e34945050505050565b604080516001600160a01b039092168252519081900360200190f35b34801561059357600080fd5b5061059c610e58565b6040805160ff9092168252519081900360200190f35b3480156105be57600080fd5b5061056b610e5d565b3480156105d357600080fd5b506104a8610e63565b3480156105e857600080fd5b506105f1610e6f565b6040805161ffff9092168252519081900360200190f35b34801561061457600080fd5b5061059c610e74565b34801561062957600080fd5b506104a8610e79565b34801561063e57600080fd5b5061056b610e84565b34801561065357600080fd5b5061056b6004803603602081101561066a57600080fd5b5035610e8a565b34801561067d57600080fd5b506104a8610ea5565b34801561069257600080fd5b5061059c610eae565b6107b3600480360360808110156106b157600080fd5b810190602081018135600160201b8111156106cb57600080fd5b8201836020820111156106dd57600080fd5b803590602001918460208302840111600160201b831117156106fe57600080fd5b919390929091602081019035600160201b81111561071b57600080fd5b82018360208201111561072d57600080fd5b803590602001918460208302840111600160201b8311171561074e57600080fd5b919390929091602081019035600160201b81111561076b57600080fd5b82018360208201111561077d57600080fd5b803590602001918460208302840111600160201b8311171561079e57600080fd5b91935091503567ffffffffffffffff16610eb3565b604080519115158252519081900360200190f35b3480156107d357600080fd5b5061056b611388565b3480156107e857600080fd5b5061059c61138e565b3480156107fd57600080fd5b506104a8611393565b34801561081257600080fd5b5061056b611399565b34801561082757600080fd5b5061059c61139f565b34801561083c57600080fd5b506103646004803603604081101561085357600080fd5b60ff8235169190810190604081016020820135600160201b81111561087757600080fd5b82018360208201111561088957600080fd5b803590602001918460018302840111600160201b831117156108aa57600080fd5b5090925090506113a4565b3480156108c157600080fd5b50610364600480360360608110156108d857600080fd5b508035906001600160a01b0360208201351690604001356114ed565b34801561090057600080fd5b5061059c611573565b34801561091557600080fd5b506104a8611578565b34801561092a57600080fd5b506104a86004803603604081101561094157600080fd5b506001600160a01b038135169060200135611584565b34801561096357600080fd5b5061056b6116c2565b34801561097857600080fd5b5061056b6116c8565b34801561098d57600080fd5b5061059c6116ce565b3480156109a257600080fd5b506107b36116d3565b6107b3600480360360808110156109c157600080fd5b5080356001600160a01b03908116916020810135909116906040810135906060013567ffffffffffffffff166116dc565b3480156109fe57600080fd5b506103806116ce565b348015610a1357600080fd5b5061036460048036036040811015610a2a57600080fd5b810190602081018135600160201b811115610a4457600080fd5b820183602082011115610a5657600080fd5b803590602001918460018302840111600160201b83111715610a7757600080fd5b919390929091602081019035600160201b811115610a9457600080fd5b820183602082011115610aa657600080fd5b803590602001918460018302840111600160201b83111715610ac757600080fd5b509092509050611d9d565b348015610ade57600080fd5b5061036460048036036040811015610af557600080fd5b50803590602001356001600160a01b031661200c565b348015610b1757600080fd5b506104a8612082565b348015610b2c57600080fd5b506104a861208c565b348015610b4157600080fd5b506104a860048036036020811015610b5857600080fd5b50356001600160a01b0316612092565b348015610b7457600080fd5b506104a860048036036020811015610b8b57600080fd5b50356001600160a01b03166120a4565b348015610ba757600080fd5b5061056b6120bf565b348015610bbc57600080fd5b5061036460048036036040811015610bd357600080fd5b60ff8235169190810190604081016020820135600160201b811115610bf757600080fd5b820183602082011115610c0957600080fd5b803590602001918460018302840111600160201b83111715610c2a57600080fd5b5090925090506120c5565b348015610c4157600080fd5b5061056b612195565b348015610c5657600080fd5b5061036461219b565b348015610c6b57600080fd5b5061059c61223b565b348015610c8057600080fd5b5061059c612240565b348015610c9557600080fd5b5061056b612245565b348015610caa57600080fd5b506104a861224b565b348015610cbf57600080fd5b5061041e60048036036020811015610cd657600080fd5b50356001600160a01b0316612251565b348015610cf257600080fd5b5061056b612378565b606481565b60005460609060ff16610d48576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b3361200014610d885760405162461bcd60e51b815260040180806020018281038252602f81526020018061476d602f913960400191505060405180910390fd5b60ff841660021415610dda57610dd383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237e92505050565b9050610e27565b6040805162461bcd60e51b815260206004820152601860248201527f756e7265636f676e697a65642073796e207061636b6167650000000000000000604482015290519081900360640190fd5b9392505050565b60015490565b6020818101516000908152600490915260409020546001600160a01b03165b919050565b600181565b61100181565b670de0b6b3a764000081565b606081565b600881565b66071afd498d000081565b61200081565b6000908152600460205260409020546001600160a01b031690565b6402540be40081565b600381565b6000805460ff16610ef9576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b868514610f375760405162461bcd60e51b815260040180806020018281038252603b815260200180614732603b913960400191505060405180910390fd5b868314610f755760405162461bcd60e51b815260040180806020018281038252603f815260200180614605603f913960400191505060405180910390fd5b426078018267ffffffffffffffff161015610fc15760405162461bcd60e51b81526004018080602001828103825260248152602001806144f56024913960400191505060405180910390fd5b6402540be4003406156110055760405162461bcd60e51b81526004018080602001828103825260408152602001806148356040913960400191505060405180910390fd5b60408051868152602080880282010190915285906000908190606090848015611038578160200160208202803683370190505b50905060005b84811015611113576402540be4008b8b8381811061105857fe5b905060200201358161106657fe5b06156110a35760405162461bcd60e51b815260040180806020018281038252603c815260200180614644603c913960400191505060405180910390fd5b6110c88b8b838181106110b257fe5b90506020020135856124a290919063ffffffff16565b93506110f46402540be4008c8c848181106110df57fe5b905060200201356124fc90919063ffffffff16565b82828151811061110057fe5b602090810291909101015260010161103e565b506001546111389061112b908663ffffffff61253e16565b849063ffffffff6124a216565b3410156111765760405162461bcd60e51b81526004018080602001828103825260568152602001806147df6056913960600191505060405180910390fd5b611186348463ffffffff61259716565b915061119061434e565b6040518060c001604052806221272160e91b60001b815260200160006001600160a01b031681526020018381526020018e8e808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208c810282810182019093528c82529283019290918d918d91829185019084908082843760009201919091525050509082525067ffffffffffffffff8916602090910152905061200063f7a251d76003611254846125d9565b611269876402540be40063ffffffff6124fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156112c75781810151838201526020016112af565b50505050905090810190601f1680156112f45780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561131557600080fd5b505af1158015611329573d6000803e3d6000fd5b505060408051600081523360208201528082018890526060810187905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a15060019c9b505050505050505050505050565b61100581565b600281565b60015481565b61100881565b600b81565b60005460ff166113e9576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b33612000146114295760405162461bcd60e51b815260040180806020018281038252602f81526020018061476d602f913960400191505060405180910390fd5b60ff8316600314156114795761147482828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061289492505050565b6114e8565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a15b505050565b336110081461152d5760405162461bcd60e51b815260040180806020018281038252602381526020018061479c6023913960400191505060405180910390fd5b600083815260046020908152604080832080546001600160a01b039096166001600160a01b03199096168617905593825260038152838220949094556002909352912055565b600981565b677ce66c50e284000081565b6000805460ff166115ca576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b336110051461160a5760405162461bcd60e51b815260040180806020018281038252602f815260200180614468602f913960400191505060405180910390fd5b6000478310611619574761161b565b825b9050670de0b6b3a76400008111156116375760009150506116bc565b80156116b9576040516001600160a01b0385169082156108fc029083906000818181858888f19350505050158015611673573d6000803e3d6000fd5b50604080516001600160a01b03861681526020810183905281517ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0929181900390910190a15b90505b92915050565b61100781565b61100681565b600081565b60005460ff1681565b6000805460ff16611722576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b426078018267ffffffffffffffff16101561176e5760405162461bcd60e51b81526004018080602001828103825260248152602001806144f56024913960400191505060405180910390fd5b6402540be4003406156117b25760405162461bcd60e51b81526004018080602001828103825260408152602001806148356040913960400191505060405180910390fd5b600080806001600160a01b038816611891576001546117d890879063ffffffff6124a216565b3410156118165760405162461bcd60e51b815260040180806020018281038252606181526020018061457f6061913960800191505060405180910390fd5b6402540be40086061561185a5760405162461bcd60e51b815260040180806020018281038252603c815260200180614644603c913960400191505060405180910390fd5b61186a348763ffffffff61259716565b9050611881866402540be40063ffffffff6124fc16565b6221272160e91b93509150611b34565b6001600160a01b0388166000908152600360205260409020549250826118e85760405162461bcd60e51b815260040180806020018281038252603181526020018061454e6031913960400191505060405180910390fd5b6001543410156119295760405162461bcd60e51b815260040180806020018281038252603f8152602001806146a1603f913960400191505060405180910390fd5b506001600160a01b038716600090815260026020526040902054349060088111158061197457506008811180156119745750611972876007198301600a0a63ffffffff6128f016565b155b6119af5760405162461bcd60e51b815260040180806020018281038252603c815260200180614644603c913960400191505060405180910390fd5b6119b98782612932565b92506119c484612972565b15611a0c576305f5e100831015611a0c5760405162461bcd60e51b815260040180806020018281038252603a815260200180614497603a913960400191505060405180910390fd5b600881101580611a265750600881108015611a2657508683115b611a615760405162461bcd60e51b81526004018080602001828103825260258152602001806145e06025913960400191505060405180910390fd5b677ce66c50e2840000831115611aa85760405162461bcd60e51b81526004018080602001828103825260358152602001806145196035913960400191505060405180910390fd5b604080516323b872dd60e01b81523360048201523060248201526044810189905290516001600160a01b038b16916323b872dd9160648083019260209291908290030181600087803b158015611afd57600080fd5b505af1158015611b11573d6000803e3d6000fd5b505050506040513d6020811015611b2757600080fd5b5051611b3257600080fd5b505b611b3c61434e565b6040805160c0810182528581526001600160a01b038b166020820152815160018082528184018452919283019181602001602082028036833750505081526040805160018082528183019092526020928301929091908083019080368337505050815260408051600180825281830190925260209283019290919080830190803683370190505081526020018767ffffffffffffffff168152509050828160400151600081518110611bea57fe5b602002602001018181525050878160600151600081518110611c0857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050338160800151600081518110611c3a57fe5b6001600160a01b039092166020928302919091019091015261200063f7a251d76003611c65846125d9565b611c7a866402540be40063ffffffff6124fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611cd8578181015183820152602001611cc0565b50505050905090810190601f168015611d055780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015611d2657600080fd5b505af1158015611d3a573d6000803e3d6000fd5b5050604080516001600160a01b038d1681523360208201528082018b90526060810186905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a150600198975050505050505050565b3361100714611ddd5760405162461bcd60e51b815260040180806020018281038252602e8152602001806146e0602e913960400191505060405180910390fd5b60208114611e32576040805162461bcd60e51b815260206004820152601b60248201527f65787065637465642076616c7565206c656e6774682069732033320000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152939450606093925086915085908190840183828082843760009201919091525050505060208301519091506772656c617946656560c01b811415611f3a576020820151670de0b6b3a76400008111801590611ee157506402540be4008106155b611f32576040805162461bcd60e51b815260206004820152601960248201527f7468652072656c6179466565206f7574206f662072616e676500000000000000604482015290519081900360640190fd5b600155611f77565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b336110081461204c5760405162461bcd60e51b815260040180806020018281038252602381526020018061479c6023913960400191505060405180910390fd5b600091825260046020908152604080842080546001600160a01b03191690556001600160a01b0392909216835260039052812055565b6221272160e91b81565b61c35081565b60026020526000908152604090205481565b6001600160a01b031660009081526003602052604090205490565b61100281565b60005460ff1661210a576040805162461bcd60e51b815260206004820152601960248201526000805160206147bf833981519152604482015290519081900360640190fd5b336120001461214a5760405162461bcd60e51b815260040180806020018281038252602f81526020018061476d602f913960400191505060405180910390fd5b60ff8316600314156114795761147482828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a7892505050565b61100381565b60005460ff16156121f3576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b66071afd498d000060019081556000808052600260205260127fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b55805460ff19169091179055565b600481565b600581565b61100081565b61271081565b6001600160a01b03811660009081526003602090815260409182902054825182815280840190935260609290918391906020820181803683375050506020810183905290506000805b60208160ff1610156122e157828160ff16815181106122b557fe5b01602001516001600160f81b031916156122d4576001909101906122d9565b6122e1565b60010161229a565b5060608160ff166040519080825280601f01601f191660200182016040528015612312576020820181803683370190505b50905060005b8260ff168160ff16101561236e57838160ff168151811061233557fe5b602001015160f81c60f81b828260ff168151811061234f57fe5b60200101906001600160f81b031916908160001a905350600101612318565b5095945050505050565b61100481565b606061238861439a565b600061239384612b76565b91509150806123e9576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b60006123f483612cb5565b905063ffffffff811615612488576040808401516020808601516001600160a01b0316600090815260029091529182205461242f9190612932565b90506124396143cf565b60405180608001604052808660000151815260200183815260200186608001516001600160a01b031681526020018463ffffffff16815250905061247c81613002565b95505050505050610e53565b50506040805160008152602081019091529150610e539050565b6000828201838110156116b9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006116b983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506130de565b60008261254d575060006116bc565b8282028284828161255a57fe5b04146116b95760405162461bcd60e51b81526004018080602001828103825260218152602001806146806021913960400191505060405180910390fd5b60006116b983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613180565b60408051600680825260e08201909252606091829190816020015b60608152602001906001900390816125f45750508351909150612616906131da565b8160008151811061262357fe5b602002602001018190525061264483602001516001600160a01b03166131ed565b8160018151811061265157fe5b60200260200101819052506000836040015151905060608160405190808252806020026020018201604052801561269c57816020015b60608152602001906001900390816126875790505b50905060005b828110156126e9576126ca866040015182815181106126bd57fe5b60200260200101516131da565b8282815181106126d657fe5b60209081029190910101526001016126a2565b506126f381613210565b8360028151811061270057fe5b602002602001018190525060608260405190808252806020026020018201604052801561274157816020015b606081526020019060019003908161272c5790505b50905060005b83811015612797576127788760600151828151811061276257fe5b60200260200101516001600160a01b03166131ed565b82828151811061278457fe5b6020908102919091010152600101612747565b506127a181613210565b846003815181106127ae57fe5b60200260200101819052506060836040519080825280602002602001820160405280156127ef57816020015b60608152602001906001900390816127da5790505b50905060005b8481101561282f576128108860800151828151811061276257fe5b82828151811061281c57fe5b60209081029190910101526001016127f5565b5061283981613210565b8560048151811061284657fe5b60200260200101819052506128688760a0015167ffffffffffffffff166131da565b8560058151811061287557fe5b602002602001018190525061288985613210565b979650505050505050565b61289c6143f6565b60006128a78361329a565b91509150806128e75760405162461bcd60e51b815260040180806020018281038252602481526020018061470e6024913960400191505060405180910390fd5b6114e882613465565b60006116b983836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f00000000000000008152506138e9565b6000600882111561295b57612954836007198401600a0a63ffffffff6124fc16565b90506116bc565b6116b9836008849003600a0a63ffffffff61253e16565b604080516020808252818301909252600091606091906020820181803683375050506020810184905290506000805b60208160ff1610156129e857828160ff16815181106129bc57fe5b01602001516001600160f81b031916156129db576001909101906129e0565b6129e8565b6001016129a1565b50600860ff82161015612a0057600092505050610e53565b816005820360ff1681518110612a1257fe5b6020910101516001600160f81b031916602d60f81b14612a3757600092505050610e53565b816001820360ff1681518110612a4957fe5b6020910101516001600160f81b031916604d60f81b14612a6e57600092505050610e53565b5060019392505050565b612a8061434e565b6000612a8b8361394b565b9150915080612acb5760405162461bcd60e51b81526004018080602001828103825260248152602001806144d16024913960400191505060405180910390fd5b612ad36143f6565b602080840180516001600160a01b0390811684526040808701518585015291511660009081526002909252812054905b846040015151811015612b5457612b3185604001518281518110612b2357fe5b602002602001015183613bc6565b85604001518281518110612b4157fe5b6020908102919091010152600101612b03565b506080840151604083015260056060830152612b6f82613465565b5050505050565b612b7e61439a565b6000612b8861439a565b612b9061442d565b612ba1612b9c86613bff565b613c24565b90506000805b612bb083613c6e565b15612ca85780612bd257612bcb612bc684613c8f565b613cdd565b8452612ca0565b8060011415612bff57612bec612be784613c8f565b613d94565b6001600160a01b03166020850152612ca0565b8060021415612c1e57612c14612bc684613c8f565b6040850152612ca0565b8060031415612c4657612c33612be784613c8f565b6001600160a01b03166060850152612ca0565b8060041415612c6e57612c5b612be784613c8f565b6001600160a01b03166080850152612ca0565b8060051415612c9b57612c83612bc684613c8f565b67ffffffffffffffff1660a085015260019150612ca0565b612ca8565b600101612ba7565b5091935090915050915091565b60208101516000906001600160a01b0316612dec578160a0015167ffffffffffffffff16421115612ce857506001610e53565b8160400151471015612cfc57506003610e53565b606082015160408084015190516000926001600160a01b0316916127109184818181858888f193505050503d8060008114612d53576040519150601f19603f3d011682016040523d82523d6000602084013e612d58565b606091505b5050905080612d6b575060049050610e53565b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5983602001518460600151856040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060009050610e53565b8160a0015167ffffffffffffffff16421115612e0a57506001610e53565b81516020808401516001600160a01b031660009081526003909152604090205414612e3757506002610e53565b602080830151604080516370a0823160e01b815230600482015290516000936001600160a01b03909316926370a082319261c3509260248083019392829003018187803b158015612e8757600080fd5b5086fa158015612e9b573d6000803e3d6000fd5b50505050506040513d6020811015612eb257600080fd5b50516040840151909150811015612ecd575060039050610e53565b600083602001516001600160a01b031663a9059cbb61c350866060015187604001516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015612f3e57600080fd5b5087f1158015612f52573d6000803e3d6000fd5b50505050506040513d6020811015612f6957600080fd5b505190508015612ff6577f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5984602001518560600151866040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060009150610e539050565b5060059150610e539050565b60408051600480825260a08201909252606091829190816020015b606081526020019060019003908161301d575050835190915061303f906131da565b8160008151811061304c57fe5b602002602001018190525061306483602001516131da565b8160018151811061307157fe5b602002602001018190525061309283604001516001600160a01b03166131ed565b8160028151811061309f57fe5b60200260200101819052506130bd836060015163ffffffff166131da565b816003815181106130ca57fe5b6020026020010181905250610e2781613210565b6000818361316a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561312f578181015183820152602001613117565b50505050905090810190601f16801561315c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161317657fe5b0495945050505050565b600081848411156131d25760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561312f578181015183820152602001613117565b505050900390565b60606116bc6131e883613dae565b613e94565b60408051600560a21b8318601482015260348101909152606090610e2781613e94565b60608151600014156132315750604080516000815260208101909152610e53565b60608260008151811061324057fe5b602002602001015190506000600190505b8351811015613281576132778285838151811061326a57fe5b6020026020010151613ee6565b9150600101613251565b50610e27613294825160c060ff16613f63565b82613ee6565b6132a26143f6565b60006132ac6143f6565b6132b461442d565b6132c0612b9c86613bff565b90506000805b6132cf83613c6e565b15612ca857806132f5576132e5612be784613c8f565b6001600160a01b0316845261345d565b806001141561339657606061331161330c85613c8f565b61405b565b9050805160405190808252806020026020018201604052801561333e578160200160208202803683370190505b50602086015260005b815181101561338f5761336c82828151811061335f57fe5b6020026020010151613cdd565b8660200151828151811061337c57fe5b6020908102919091010152600101613347565b505061345d565b80600214156134385760606133ad61330c85613c8f565b905080516040519080825280602002602001820160405280156133da578160200160208202803683370190505b50604086015260005b815181101561338f576134088282815181106133fb57fe5b6020026020010151613d94565b8660400151828151811061341857fe5b6001600160a01b03909216602092830291909101909101526001016133e3565b8060031415612c9b5761344d612bc684613c8f565b63ffffffff166060850152600191505b6001016132c6565b80516001600160a01b031661368f5760005b8160200151518110156136895760008260400151828151811061349657fe5b60200260200101516001600160a01b0316612710846020015184815181106134ba57fe5b60209081029190910101516040516000818181858888f193505050503d8060008114613502576040519150601f19603f3d011682016040523d82523d6000602084013e613507565b606091505b50509050806135ca577f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061354657fe5b60200260200101518560200151858151811061355e57fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a1613680565b7fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a83600001518460400151848151811061360057fe5b60200260200101518560200151858151811061361857fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101613477565b506138e6565b60005b8160200151518110156138e457600082600001516001600160a01b031663a9059cbb61c350856040015185815181106136c757fe5b6020026020010151866020015186815181106136df57fe5b60200260200101516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b15801561373657600080fd5b5087f115801561374a573d6000803e3d6000fd5b50505050506040513d602081101561376157600080fd5b505190508015613825577fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a8360000151846040015184815181106137a157fe5b6020026020010151856020015185815181106137b957fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a16138db565b7f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061385b57fe5b60200260200101518560200151858151811061387357fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101613692565b505b50565b600081836139385760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561312f578181015183820152602001613117565b5082848161394257fe5b06949350505050565b61395361434e565b600061395d61434e565b61396561442d565b613971612b9c86613bff565b90506000805b61398083613c6e565b15613bb8578061399d57613996612bc684613c8f565b8452613bb0565b80600114156139c5576139b2612be784613c8f565b6001600160a01b03166020850152613bb0565b8060021415613a545760606139dc61330c85613c8f565b90508051604051908082528060200260200182016040528015613a09578160200160208202803683370190505b50604086015260005b8151811015613a4d57613a2a82828151811061335f57fe5b86604001518281518110613a3a57fe5b6020908102919091010152600101613a12565b5050613bb0565b8060031415613ae9576060613a6b61330c85613c8f565b90508051604051908082528060200260200182016040528015613a98578160200160208202803683370190505b50606086015260005b8151811015613a4d57613ab98282815181106133fb57fe5b86606001518281518110613ac957fe5b6001600160a01b0390921660209283029190910190910152600101613aa1565b8060041415613b7e576060613b0061330c85613c8f565b90508051604051908082528060200260200182016040528015613b2d578160200160208202803683370190505b50608086015260005b8151811015613a4d57613b4e8282815181106133fb57fe5b86608001518281518110613b5e57fe5b6001600160a01b0390921660209283029190910190910152600101613b36565b8060051415613bab57613b93612bc684613c8f565b67ffffffffffffffff1660a085015260019150613bb0565b613bb8565b600101613977565b509195600195509350505050565b60006008821115613be857612954836007198401600a0a63ffffffff61253e16565b6116b9836008849003600a0a63ffffffff6124fc16565b613c0761444d565b506040805180820190915281518152602082810190820152919050565b613c2c61442d565b613c358261412c565b613c3e57600080fd5b6000613c4d836020015161415c565b60208085015160408051808201909152868152920190820152915050919050565b6000613c7861444d565b505080518051602091820151919092015191011190565b613c9761444d565b613ca082613c6e565b613ca957600080fd5b60208201516000613cb9826141bf565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590613cf257508151602110155b613cfb57600080fd5b6000613d0a836020015161415c565b90508083600001511015613d65576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015613d8b57826020036101000a820491505b50949350505050565b8051600090601514613da557600080fd5b6116bc82613cdd565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416613df257506018613e16565b6fffffffffffffffffffffffffffffffff198416613e1257506010613e16565b5060005b6020811015613e4c57818181518110613e2b57fe5b01602001516001600160f81b03191615613e4457613e4c565b600101613e16565b60008160200390506060816040519080825280601f01601f191660200182016040528015613e81576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015613ec65750607f60f81b82600081518110613eb457fe5b01602001516001600160f81b03191611155b15613ed2575080610e53565b6116bc613ee48351608060ff16613f63565b835b6060806040519050835180825260208201818101602087015b81831015613f17578051835260209283019201613eff565b50855184518101855292509050808201602086015b81831015613f44578051835260209283019201613f2c565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310613fb3576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b6040805160018082528183019092526060916020820181803683370190505090506037841161400d5782840160f81b81600081518110613fef57fe5b60200101906001600160f81b031916908160001a90535090506116bc565b606061401885613dae565b90508381510160370160f81b8260008151811061403157fe5b60200101906001600160f81b031916908160001a9053506140528282613ee6565b95945050505050565b60606140668261412c565b61406f57600080fd5b600061407a836142f2565b90506060816040519080825280602002602001820160405280156140b857816020015b6140a561444d565b81526020019060019003908161409d5790505b50905060006140ca856020015161415c565b60208601510190506000805b84811015614121576140e7836141bf565b915060405180604001604052808381526020018481525084828151811061410a57fe5b6020908102919091010152918101916001016140d6565b509195945050505050565b805160009061413d57506000610e53565b6020820151805160001a9060c0821015612a6e57600092505050610e53565b8051600090811a6080811015614176576000915050610e53565b60b8811080614191575060c08110801590614191575060f881105b156141a0576001915050610e53565b60c08110156141b45760b519019050610e53565b60f519019050610e53565b80516000908190811a60808110156141da57600191506142eb565b60b88110156141ef57607e19810191506142eb565b60c081101561426957600060b78203600186019550806020036101000a865104915060018101820193505080831015614263576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b506142eb565b60f881101561427e5760be19810191506142eb565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156142e9576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b805160009061430357506000610e53565b60008090506000614317846020015161415c565b602085015185519181019250015b8082101561434557614336826141bf565b60019093019290910190614325565b50909392505050565b6040518060c001604052806000801916815260200160006001600160a01b03168152602001606081526020016060815260200160608152602001600067ffffffffffffffff1681525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806080016040528060006001600160a01b031681526020016060815260200160608152602001600063ffffffff1681525090565b604051806040016040528061444061444d565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d75737420626520696e63656e746976697a6520636f6e7472616374466f72206d696e69546f6b656e2c20746865207472616e7366657220616d6f756e74206d757374206e6f74206265206c657373207468616e2031756e7265636f676e697a6564207472616e736665724f75742073796e207061636b61676565787069726554696d65206d7573742062652074776f206d696e75746573206c61746572616d6f756e7420697320746f6f206c617267652c20657863656564206d6178696d756d206265703220746f6b656e20616d6f756e7474686520636f6e747261637420686173206e6f74206265656e20626f756e6420746f20616e79206265703220746f6b656e726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e736665724f757420424e4220616d6f756e7420616e64206d696e696d756d2072656c6179466565616d6f756e7420697320746f6f206c617267652c2075696e74323536206f766572666c6f774c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620726566756e644164647273696e76616c6964207472616e7366657220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e20746865206d696e696d756d2072656c6179466565746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374756e7265636f676e697a6564207472616e736665724f75742061636b207061636b6167654c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620616d6f756e7473746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d73672073656e646572206d75737420626520746f6b656e4d616e6167657274686520636f6e7472616374206e6f7420696e69742079657400000000000000726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e7366657220424e4220616d6f756e7420616e642072656c6179466565696e76616c696420726563656976656420424e4220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6ea26469706673582212202fa743647f340cdc97fb964bb6c8a74806c9ea98dc6aef93014be6fd60b8224564736f6c63430006040033" }, "0x0000000000000000000000000000000000001005": { "balance": "0x0", @@ -63,7 +63,7 @@ }, "0x0000000000000000000000000000000000001008": { "balance": "0x0", - "code": "0x6080604052600436106102465760003560e01c806375d47a0a11610139578063ab51bb96116100b6578063dc6f5e901161007a578063dc6f5e90146108df578063dc927faf14610975578063f9a2bbc71461098a578063fc3e5908146108df578063fd6a68791461099f578063fe3a2af5146104fd57610246565b8063ab51bb96146108b5578063c81b1662146108ca578063c8509d81146107c5578063c8e704a4146108df578063d117a110146108f457610246565b806395b9ad26116100fd57806395b9ad261461084c57806396713da9146108615780639dc0926214610876578063a1a11bf51461088b578063a78abc16146108a057610246565b806375d47a0a146106e757806377d9dae8146106fc5780637942fd05146107b05780637d078e13146103c8578063831d65d1146107c557610246565b80634a688818116101c75780635f558f861161018b5780635f558f86146105515780636b3f1307146105665780636e47b4821461062e57806370fd5bad1461055157806372c4e0861461064357610246565b80634a688818146104fd5780634bc81c00146105125780634bf6c8821461024b57806351e80672146105275780635d499b1b1461053c57610246565b806323996b531161020e57806323996b53146103c85780633dffc387146103c857806343756e5c146103dd578063445fcefe1461040e578063493279b1146104d157610246565b8063077b8f351461024b5780630bee7a67146102765780630f212b1b146102a45780631182b875146102b95780631f91600b146103b3575b600080fd5b34801561025757600080fd5b506102606109b4565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b5061028b6109b9565b6040805163ffffffff9092168252519081900360200190f35b3480156102b057600080fd5b506102606109be565b3480156102c557600080fd5b5061033e600480360360408110156102dc57600080fd5b60ff8235169190810190604081016020820135600160201b81111561030057600080fd5b82018360208201111561031257600080fd5b803590602001918460018302840111600160201b8311171561033357600080fd5b5090925090506109c3565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610378578181015183820152602001610360565b50505050905090810190601f1680156103a55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103bf57600080fd5b50610260610a4c565b3480156103d457600080fd5b50610260610a51565b3480156103e957600080fd5b506103f2610a56565b604080516001600160a01b039092168252519081900360200190f35b34801561041a57600080fd5b506104bf6004803603602081101561043157600080fd5b810190602081018135600160201b81111561044b57600080fd5b82018360208201111561045d57600080fd5b803590602001918460018302840111600160201b8311171561047e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610a5c945050505050565b60408051918252519081900360200190f35b3480156104dd57600080fd5b506104e6610bbb565b6040805161ffff9092168252519081900360200190f35b34801561050957600080fd5b50610260610bc0565b34801561051e57600080fd5b50610260610bc5565b34801561053357600080fd5b506103f2610bca565b34801561054857600080fd5b506104bf610bd0565b34801561055d57600080fd5b50610260610bd9565b61061a6004803603604081101561057c57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156105a657600080fd5b8201836020820111156105b857600080fd5b803590602001918460018302840111600160201b831117156105d957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610bde945050505050565b604080519115158252519081900360200190f35b34801561063a57600080fd5b506103f2611460565b61061a6004803603602081101561065957600080fd5b810190602081018135600160201b81111561067357600080fd5b82018360208201111561068557600080fd5b803590602001918460018302840111600160201b831117156106a657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611466945050505050565b3480156106f357600080fd5b506103f26118b4565b61061a6004803603604081101561071257600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561073c57600080fd5b82018360208201111561074e57600080fd5b803590602001918460018302840111600160201b8311171561076f57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506118ba945050505050565b3480156107bc57600080fd5b50610260611dc1565b3480156107d157600080fd5b5061084a600480360360408110156107e857600080fd5b60ff8235169190810190604081016020820135600160201b81111561080c57600080fd5b82018360208201111561081e57600080fd5b803590602001918460018302840111600160201b8311171561083f57600080fd5b509092509050611dc6565b005b34801561085857600080fd5b50610260611e79565b34801561086d57600080fd5b50610260611e7e565b34801561088257600080fd5b506103f2611e83565b34801561089757600080fd5b506103f2611e89565b3480156108ac57600080fd5b5061061a611e8f565b3480156108c157600080fd5b5061028b610bc0565b3480156108d657600080fd5b506103f2611e98565b3480156108eb57600080fd5b50610260611e9e565b34801561090057600080fd5b5061091e6004803603602081101561091757600080fd5b5035611ea3565b6040805160ff988916815260208101979097526001600160a01b03909516868601526060860193909352608085019190915290931660a083015267ffffffffffffffff90921660c082015290519081900360e00190f35b34801561098157600080fd5b506103f2611efb565b34801561099657600080fd5b506103f2611f01565b3480156109ab57600080fd5b506103f2611f07565b600881565b606481565b600681565b60603361200014610a055760405162461bcd60e51b815260040180806020018281038252602f8152602001806132a0602f913960400191505060405180910390fd5b610a4483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f0d92505050565b949350505050565b600481565b600181565b61100181565b6020810151600090610a6c613168565b50600081815260016020818152604092839020835160e081018552815460ff9081168252938201549281019290925260028101546001600160a01b031693820184905260038101546060830152600481015460808301526005015491821660a082015261010090910467ffffffffffffffff1660c082015290610af457600092505050610bb6565b600081604001516001600160a01b03166370a082316110046040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015610b5257600080fd5b505afa158015610b66573d6000803e3d6000fd5b505050506040513d6020811015610b7c57600080fd5b505160808301516060840151919250600091610b9d9163ffffffff61219e16565b9050610baf818363ffffffff61219e16565b9450505050505b919050565b606081565b600081565b600581565b61200081565b6402540be40081565b600281565b600080610bea836121e7565b9050610bf4613168565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a084015261010090910467ffffffffffffffff1660c0830152610cba576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b6000610cd78260800151836060015161219e90919063ffffffff16565b905081604001516001600160a01b0316866001600160a01b031614610d2d5760405162461bcd60e51b815260040180806020018281038252604581526020018061322d6045913960600191505060405180910390fd5b336001600160a01b0316866001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7057600080fd5b505afa158015610d84573d6000803e3d6000fd5b505050506040513d6020811015610d9a57600080fd5b50516001600160a01b031614610de15760405162461bcd60e51b815260040180806020018281038252602e815260200180613272602e913960400191505060405180910390fd5b604080516370a0823160e01b8152611004600482015290516000916001600160a01b038916916370a0823191602480820192602092909190829003018186803b158015610e2d57600080fd5b505afa158015610e41573d6000803e3d6000fd5b505050506040513d6020811015610e5757600080fd5b505160408051636eb1769f60e11b815233600482015230602482015290519192508391610ee89184916001600160a01b038c169163dd62ed3e916044808301926020929190829003018186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506040513d6020811015610eda57600080fd5b50519063ffffffff6121ee16565b1015610f3b576040805162461bcd60e51b815260206004820152601760248201527f616c6c6f77616e6365206973206e6f7420656e6f756768000000000000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015610f7d57600080fd5b505afa158015610f91573d6000803e3d6000fd5b505050506040513d6020811015610fa757600080fd5b50519050808210801590610fc057506402540be4008206155b610ffb5760405162461bcd60e51b81526004018080602001828103825260378152602001806131f66037913960400191505060405180910390fd5b6000611007868b612248565b905063ffffffff8116611206576001600160a01b038a166323b872dd33611004611037898963ffffffff61219e16565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b15801561109f57600080fd5b505af11580156110b3573d6000803e3d6000fd5b505050506040513d60208110156110c957600080fd5b5050602086015160408088015160a089015182516323bfccdb60e21b815260048101949094526001600160a01b03909116602484015260ff1660448301525161100491638eff336c91606480830192600092919082900301818387803b15801561113257600080fd5b505af1158015611146573d6000803e3d6000fd5b50505050896001600160a01b03167f78e7dd9aefcdbf795c4936a66f7dc6d41bb56637b54f561a6bf7829dca3348a88a8860600151886040518080602001848152602001838152602001828103825285818151815260200191508051906020019080838360005b838110156111c55781810151838201526020016111ad565b50505050905090810190601f1680156111f25780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a26112be565b896001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a1078a8360405180806020018363ffffffff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561128257818101518382015260200161126a565b50505050905090810190601f1680156112af5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25b60008781526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556113186131a4565b5060408051808201825263ffffffff831681526020810189905290516110049085156108fc029086906000818181858888f19350505050158015611360573d6000803e3d6000fd5b5061200063f7a251d760016113748461269f565b611389886402540be40063ffffffff61272916565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156113e75781810151838201526020016113cf565b50505050905090810190601f1680156114145780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561143557600080fd5b505af1158015611449573d6000803e3d6000fd5b505050506001985050505050505050505b92915050565b61100581565b600080611472836121e7565b905061147c613168565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a084015261010090910467ffffffffffffffff1660c0830152611542576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b428160c0015167ffffffffffffffff16106115a4576040805162461bcd60e51b815260206004820152601b60248201527f62696e642072657175657374206973206e6f7420657870697265640000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b1580156115e657600080fd5b505afa1580156115fa573d6000803e3d6000fd5b505050506040513d602081101561161057600080fd5b5051905080821080159061162957506402540be4008206155b6116645760405162461bcd60e51b81526004018080602001828103825260378152602001806131f66037913960400191505060405180910390fd5b60008481526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556116be6131a4565b50604080518082018252600181526020810186905290516110049084156108fc029085906000818181858888f19350505050158015611701573d6000803e3d6000fd5b5061200063f7a251d760016117158461269f565b61172a876402540be40063ffffffff61272916565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611788578181015183820152602001611770565b50505050905090810190601f1680156117b55780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156117d657600080fd5b505af11580156117ea573d6000803e3d6000fd5b5050505083604001516001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a10788600160405180806020018360ff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561186c578181015183820152602001611854565b50505050905090810190601f1680156118995780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25060019695505050505050565b61100881565b6000806118c6836121e7565b90506118d0613168565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a084015261010090910467ffffffffffffffff1660c0830152611996576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b80604001516001600160a01b0316856001600160a01b0316146119ea5760405162461bcd60e51b815260040180806020018281038252604581526020018061322d6045913960600191505060405180910390fd5b336001600160a01b0316856001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b158015611a2d57600080fd5b505afa158015611a41573d6000803e3d6000fd5b505050506040513d6020811015611a5757600080fd5b50516001600160a01b031614611ab4576040805162461bcd60e51b815260206004820152601b60248201527f6f6e6c79206265703265206f776e65722063616e2072656a6563740000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015611af657600080fd5b505afa158015611b0a573d6000803e3d6000fd5b505050506040513d6020811015611b2057600080fd5b50519050808210801590611b3957506402540be4008206155b611b745760405162461bcd60e51b81526004018080602001828103825260378152602001806131f66037913960400191505060405180910390fd5b60008481526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff19169055611bce6131a4565b50604080518082018252600781526020810186905290516110049084156108fc029085906000818181858888f19350505050158015611c11573d6000803e3d6000fd5b5061200063f7a251d76001611c258461269f565b611c3a876402540be40063ffffffff61272916565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611c98578181015183820152602001611c80565b50505050905090810190601f168015611cc55780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015611ce657600080fd5b505af1158015611cfa573d6000803e3d6000fd5b50505050876001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a10788600760405180806020018360ff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611d78578181015183820152602001611d60565b50505050905090810190601f168015611da55780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2506001979650505050505050565b600b81565b3361200014611e065760405162461bcd60e51b815260040180806020018281038252602f8152602001806132a0602f913960400191505060405180910390fd5b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a1505050565b600781565b600981565b61100781565b61100681565b60005460ff1681565b61100281565b600381565b600160208190526000918252604090912080549181015460028201546003830154600484015460059094015460ff9586169593946001600160a01b0390931693919291811690610100900467ffffffffffffffff1687565b61100381565b61100081565b61100481565b6060611f17613168565b6000611f228461276b565b9150915080611f78576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b815160ff1661202c576020828101805160009081526001928390526040908190208551815460ff1990811660ff928316178355935194820194909455908501516002820180546001600160a01b0319166001600160a01b03909216919091179055606085015160038201556080850151600482015560a08501516005909101805460c08701519316919093161768ffffffffffffffff00191661010067ffffffffffffffff90921691909102179055612183565b815160ff16600114156121365760006110046001600160a01b03166359b9278984602001516040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561208557600080fd5b505afa158015612099573d6000803e3d6000fd5b505050506040513d60208110156120af57600080fd5b505190506001600160a01b038116156121305760208301516040805163b99328c560e01b815260048101929092526001600160a01b0383166024830152516110049163b99328c591604480830192600092919082900301818387803b15801561211757600080fd5b505af115801561212b573d6000803e3d6000fd5b505050505b50612183565b6040805162461bcd60e51b815260206004820152601960248201527f756e7265636f676e697a65642062696e64207061636b61676500000000000000604482015290519081900360640190fd5b60408051600080825260208201909252905b50949350505050565b60006121e083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506128bd565b9392505050565b6020015190565b6000828201838110156121e0576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561228457600080fd5b505afa158015612298573d6000803e3d6000fd5b505050506040513d60208110156122ae57600080fd5b5051604080516395d89b4160e01b815290519192506060916001600160a01b038616916395d89b41916004808301926000929190829003018186803b1580156122f657600080fd5b505afa15801561230a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561233357600080fd5b8101908080516040519392919084600160201b82111561235257600080fd5b90830190602082018581111561236757600080fd5b8251600160201b81118282018810171561238057600080fd5b82525081516020918201929091019080838360005b838110156123ad578181015183820152602001612395565b50505050905090810190601f1680156123da5780820380516001836020036101000a031916815260200191505b5060408181526370a0823160e01b82526110046004830152519495506000946001600160a01b038a1694506370a08231935060248083019350602092829003018186803b15801561242a57600080fd5b505afa15801561243e573d6000803e3d6000fd5b505050506040513d602081101561245457600080fd5b5051608087015160608801519192506000916124759163ffffffff61219e16565b9050428760c0015167ffffffffffffffff16101561249b57506001935061145a92505050565b6124a9838860200151612954565b6124bb57506002935061145a92505050565b808211156124d157506003935061145a92505050565b866060015187604001516001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561251357600080fd5b505afa158015612527573d6000803e3d6000fd5b505050506040513d602081101561253d57600080fd5b50511461255257506004935061145a92505050565b8660a0015160ff16841461256e57506005935061145a92505050565b602080880151604080516359b9278960e01b8152600481019290925251600092611004926359b927899260248083019392829003018186803b1580156125b357600080fd5b505afa1580156125c7573d6000803e3d6000fd5b505050506040513d60208110156125dd57600080fd5b50516001600160a01b031614158061267f57506000801b6110046001600160a01b031663bd46646189604001516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561265057600080fd5b505afa158015612664573d6000803e3d6000fd5b505050506040513d602081101561267a57600080fd5b505114155b1561269257506006935061145a92505050565b5060009695505050505050565b6040805160028082526060828101909352829190816020015b60608152602001906001900390816126b857505083519091506126e09063ffffffff16612a3c565b816000815181106126ed57fe5b6020026020010181905250612708836020015160001c612a3c565b8160018151811061271557fe5b60200260200101819052506121e081612a4f565b60006121e083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612ad9565b612773613168565b600061277d613168565b6127856131bb565b61279661279186612b3e565b612b63565b90506000805b6127a583612bad565b156128b057806127ca576127c06127bb84612bce565b612c1c565b60ff1684526128a8565b80600114156127e9576127df6127bb84612bce565b60208501526128a8565b8060021415612816576128036127fe84612bce565b612cd1565b6001600160a01b031660408501526128a8565b80600314156128355761282b6127bb84612bce565b60608501526128a8565b80600414156128545761284a6127bb84612bce565b60808501526128a8565b8060051415612876576128696127bb84612bce565b60ff1660a08501526128a8565b80600614156128a35761288b6127bb84612bce565b67ffffffffffffffff1660c0850152600191506128a8565b6128b0565b60010161279c565b5091935090915050915091565b6000818484111561294c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156129115781810151838201526020016128f9565b50505050905090810190601f16801561293e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b815160009083906008108061296a575080516003115b1561297957600091505061145a565b604080516020808252818301909252606091602082018180368337019050509050836020820152808251815181106129ad57fe5b6020910101516001600160f81b031916602d60f81b146129d25760009250505061145a565b600160005b8351811015612a32578281815181106129ec57fe5b602001015160f81c60f81b6001600160f81b031916848281518110612a0d57fe5b01602001516001600160f81b03191614612a2a5760009150612a32565b6001016129d7565b5095945050505050565b606061145a612a4a83612ceb565b612dd1565b6060815160001415612a705750604080516000815260208101909152610bb6565b606082600081518110612a7f57fe5b602002602001015190506000600190505b8351811015612ac057612ab682858381518110612aa957fe5b6020026020010151612e23565b9150600101612a90565b506121e0612ad3825160c060ff16612ea0565b82612e23565b60008183612b285760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156129115781810151838201526020016128f9565b506000838581612b3457fe5b0495945050505050565b612b466131db565b506040805180820190915281518152602082810190820152919050565b612b6b6131bb565b612b7482612f98565b612b7d57600080fd5b6000612b8c8360200151612fd2565b60208085015160408051808201909152868152920190820152915050919050565b6000612bb76131db565b505080518051602091820151919092015191011190565b612bd66131db565b612bdf82612bad565b612be857600080fd5b60208201516000612bf882613035565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590612c3157508151602110155b612c3a57600080fd5b6000612c498360200151612fd2565b90508083600001511015612ca4576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b82516020808501518301805192849003929183101561219557506020919091036101000a90049392505050565b8051600090601514612ce257600080fd5b61145a82612c1c565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416612d2f57506018612d53565b6fffffffffffffffffffffffffffffffff198416612d4f57506010612d53565b5060005b6020811015612d8957818181518110612d6857fe5b01602001516001600160f81b03191615612d8157612d89565b600101612d53565b60008160200390506060816040519080825280601f01601f191660200182016040528015612dbe576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015612e035750607f60f81b82600081518110612df157fe5b01602001516001600160f81b03191611155b15612e0f575080610bb6565b61145a612e218351608060ff16612ea0565b835b6060806040519050835180825260208201818101602087015b81831015612e54578051835260209283019201612e3c565b50855184518101855292509050808201602086015b81831015612e81578051835260209283019201612e69565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310612ef0576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b60408051600180825281830190925260609160208201818036833701905050905060378411612f4a5782840160f81b81600081518110612f2c57fe5b60200101906001600160f81b031916908160001a905350905061145a565b6060612f5585612ceb565b90508381510160370160f81b82600081518110612f6e57fe5b60200101906001600160f81b031916908160001a905350612f8f8282612e23565b95945050505050565b8051600090612fa957506000610bb6565b6020820151805160001a9060c0821015612fc857600092505050610bb6565b5060019392505050565b8051600090811a6080811015612fec576000915050610bb6565b60b8811080613007575060c08110801590613007575060f881105b15613016576001915050610bb6565b60c081101561302a5760b519019050610bb6565b60f519019050610bb6565b80516000908190811a60808110156130505760019150613161565b60b881101561306557607e1981019150613161565b60c08110156130df57600060b78203600186019550806020036101000a8651049150600181018201935050808310156130d9576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50613161565b60f88110156130f45760be1981019150613161565b600060f78203600186019550806020036101000a86510491506001810182019350508083101561315f576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080518082019091526000808252602082015290565b60405180604001604052806131ce6131db565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe72656c6179466565206d757374206265204e202a203165313020616e642067726561746572207468616e206d696e6952656c6179466565636f6e74616374206164647265737320646f65736e277420657175616c20746f2074686520636f6e7472616374206164647265737320696e2062696e6420726571756573746f6e6c79206265703265206f776e65722063616e20617070726f766520746869732062696e642072657175657374746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374a26469706673582212207f9f38df356aa0753e650ec7a94ae69c6a48fb2c7010e7ba313c73c8055aa86a64736f6c63430006040033" + "code": "0x6080604052600436106103975760003560e01c80637942fd05116101dc578063b795031711610102578063dc927faf116100a0578063fa9e91591161006f578063fa9e915914610d4e578063fc3e5908146105dd578063fd6a687914610d63578063fe3a2af51461056257610397565b8063dc927faf14610d0f578063e605bca014610d24578063e80561fa14610562578063f9a2bbc714610d3957610397565b8063c8509d81116100dc578063c8509d8114610c0a578063c8e704a4146105dd578063d117a11014610c8f578063d9e6dae91461072757610397565b8063b795031714610766578063bd32d3f9146104ef578063c81b166214610bf557610397565b806396713da91161017a578063a78abc1611610149578063a78abc1614610b00578063ab51bb9614610b15578063ab67a48514610766578063ac43175114610b2a57610397565b806396713da914610aac5780639a854bbd14610ac15780639dc0926214610ad6578063a1a11bf514610aeb57610397565b8063831d65d1116101b6578063831d65d1146109db578063859180fb1461071257806394553a4e14610a6257806395b9ad2614610a9757610397565b80637942fd05146109b15780637d078e13146105045780637ec816dd146109c657610397565b8063493279b1116102c1578063613684751161025f57806370fd5bad1161022e57806370fd5bad1461076657806372c4e0861461084457806375d47a0a146108e857806377d9dae8146108fd57610397565b8063613684751461072757806366dea52a146105dd5780636b3f13071461077b5780636e47b4821461082f57610397565b80634bf6c8821161029b5780634bf6c8821461072757806351e806721461073c5780635d499b1b146107515780635f558f861461076657610397565b8063493279b1146106e65780634a688818146105625780634bc81c001461071257610397565b80632d89ac3211610339578063401809f911610308578063401809f9146105dd57806343756e5c146105f2578063445fcefe14610623578063487c88ac1461050457610397565b80632d89ac32146105045780632e02d7761461057757806337e6ecda146105aa5780633dffc3871461050457610397565b80631f91600b116103755780631f91600b146104ef57806323996b531461050457806325c751b71461051957806328ae48621461056257610397565b80630bee7a671461039c5780630f212b1b146103ca5780631182b875146103f5575b600080fd5b3480156103a857600080fd5b506103b1610d78565b6040805163ffffffff9092168252519081900360200190f35b3480156103d657600080fd5b506103df610d7d565b6040805160ff9092168252519081900360200190f35b34801561040157600080fd5b5061047a6004803603604081101561041857600080fd5b60ff8235169190810190604081016020820135600160201b81111561043c57600080fd5b82018360208201111561044e57600080fd5b803590602001918460018302840111600160201b8311171561046f57600080fd5b509092509050610d82565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104b457818101518382015260200161049c565b50505050905090810190601f1680156104e15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104fb57600080fd5b506103df610e9c565b34801561051057600080fd5b506103df610ea1565b61054e6004803603604081101561052f57600080fd5b5080356001600160a01b031690602001356001600160401b0316610ea6565b604080519115158252519081900360200190f35b34801561056e57600080fd5b506103df6113e9565b34801561058357600080fd5b5061054e6004803603602081101561059a57600080fd5b50356001600160a01b03166113ee565b3480156105b657600080fd5b5061054e600480360360208110156105cd57600080fd5b50356001600160a01b0316611403565b3480156105e957600080fd5b506103df611418565b3480156105fe57600080fd5b5061060761141d565b604080516001600160a01b039092168252519081900360200190f35b34801561062f57600080fd5b506106d46004803603602081101561064657600080fd5b810190602081018135600160201b81111561066057600080fd5b82018360208201111561067257600080fd5b803590602001918460018302840111600160201b8311171561069357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611423945050505050565b60408051918252519081900360200190f35b3480156106f257600080fd5b506106fb611581565b6040805161ffff9092168252519081900360200190f35b34801561071e57600080fd5b506103df611586565b34801561073357600080fd5b506103df61158b565b34801561074857600080fd5b50610607611590565b34801561075d57600080fd5b506106d4611596565b34801561077257600080fd5b506103df61159f565b61054e6004803603604081101561079157600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156107bb57600080fd5b8201836020820111156107cd57600080fd5b803590602001918460018302840111600160201b831117156107ee57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506115a4945050505050565b34801561083b57600080fd5b50610607611e7a565b61054e6004803603602081101561085a57600080fd5b810190602081018135600160201b81111561087457600080fd5b82018360208201111561088657600080fd5b803590602001918460018302840111600160201b831117156108a757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611e80945050505050565b3480156108f457600080fd5b506106076122cc565b61054e6004803603604081101561091357600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561093d57600080fd5b82018360208201111561094f57600080fd5b803590602001918460018302840111600160201b8311171561097057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122d2945050505050565b3480156109bd57600080fd5b506103df6127d8565b3480156109d257600080fd5b506106d46127dd565b3480156109e757600080fd5b50610a60600480360360408110156109fe57600080fd5b60ff8235169190810190604081016020820135600160201b811115610a2257600080fd5b820183602082011115610a3457600080fd5b803590602001918460018302840111600160201b83111715610a5557600080fd5b5090925090506127e3565b005b61054e60048036036040811015610a7857600080fd5b5080356001600160a01b031690602001356001600160401b0316612932565b348015610aa357600080fd5b506103df6132c8565b348015610ab857600080fd5b506103df6132cd565b348015610acd57600080fd5b506106d46132d2565b348015610ae257600080fd5b506106076132de565b348015610af757600080fd5b506106076132e4565b348015610b0c57600080fd5b5061054e6132ea565b348015610b2157600080fd5b506103b16113e9565b348015610b3657600080fd5b50610a6060048036036040811015610b4d57600080fd5b810190602081018135600160201b811115610b6757600080fd5b820183602082011115610b7957600080fd5b803590602001918460018302840111600160201b83111715610b9a57600080fd5b919390929091602081019035600160201b811115610bb757600080fd5b820183602082011115610bc957600080fd5b803590602001918460018302840111600160201b83111715610bea57600080fd5b5090925090506132f3565b348015610c0157600080fd5b506106076135c8565b348015610c1657600080fd5b50610a6060048036036040811015610c2d57600080fd5b60ff8235169190810190604081016020820135600160201b811115610c5157600080fd5b820183602082011115610c6357600080fd5b803590602001918460018302840111600160201b83111715610c8457600080fd5b5090925090506135ce565b348015610c9b57600080fd5b50610cb960048036036020811015610cb257600080fd5b50356136a4565b6040805160ff988916815260208101979097526001600160a01b03909516868601526060860193909352608085019190915290931660a08301526001600160401b0390921660c082015290519081900360e00190f35b348015610d1b57600080fd5b506106076136fb565b348015610d3057600080fd5b506106d4613701565b348015610d4557600080fd5b50610607613707565b348015610d5a57600080fd5b506106d461370d565b348015610d6f57600080fd5b50610607613713565b606481565b600681565b60603361200014610dc45760405162461bcd60e51b815260040180806020018281038252602f815260200180615a82602f913960400191505060405180910390fd5b60ff841660011415610e1657610e0f83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061371992505050565b9050610e95565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605848484604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a1506040805160008152602081019091525b9392505050565b600481565b600181565b6040805163bd46646160e01b81526001600160a01b0384166004820152905160009182916110049163bd466461916024808301926020929190829003018186803b158015610ef357600080fd5b505afa158015610f07573d6000803e3d6000fd5b505050506040513d6020811015610f1d57600080fd5b5051905080610f5f576040805162461bcd60e51b81526020600482015260096024820152681b9bdd08189bdd5b9960ba1b604482015290519081900360640190fd5b6001600160a01b03841660009081526003602052604090205460ff16610fc2576040805162461bcd60e51b81526020600482015260136024820152723737ba103137bab73210313c9036b4b93937b960691b604482015290519081900360640190fd5b60006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015610fff57600080fd5b505afa158015611013573d6000803e3d6000fd5b505050506040513d602081101561102957600080fd5b505190506402540be40034061580156110545750600554611050908263ffffffff6139a916565b3410155b61108f5760405162461bcd60e51b8152600401808060200182810382526046815260200180615a0e6046913960600191505060405180910390fd5b42607801846001600160401b0316101580156110b95750426201518001846001600160401b031611155b6110f45760405162461bcd60e51b81526004018080602001828103825260388152602001806159396038913960400191505060405180910390fd5b6000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561112f57600080fd5b505afa158015611143573d6000803e3d6000fd5b505050506040513d602081101561115957600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0389169163313ce567916004808301926020929190829003018186803b1580156111a157600080fd5b505afa1580156111b5573d6000803e3d6000fd5b505050506040513d60208110156111cb57600080fd5b50519050677ce66c50e28400006111e58360ff8416613a03565b1115611231576040805162461bcd60e51b8152602060048201526016602482015275746f6f206c6172676520746f74616c20737570706c7960501b604482015290519081900360640190fd5b600554611004906108fc9061124d90349063ffffffff613a4316565b6040518115909202916000818181858888f19350505050158015611275573d6000803e3d6000fd5b5061127e615790565b6040518060c00160405280336001600160a01b03168152602001896001600160a01b031681526020018681526020018481526020016402540be400600554816112c357fe5b0481526001600160401b038916602090910152905061200063f7a251d760056112eb84613a85565b6113156402540be40061130960055434613a4390919063ffffffff16565b9063ffffffff613bba16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561137357818101518382015260200161135b565b50505050905090810190601f1680156113a05780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156113c157600080fd5b505af11580156113d5573d6000803e3d6000fd5b505050506001955050505050505b92915050565b600081565b60036020526000908152604090205460ff1681565b60026020526000908152604090205460ff1681565b600381565b61100181565b60208101516000906114336157c5565b50600081815260016020818152604092839020835160e081018552815460ff9081168252938201549281019290925260028101546001600160a01b031693820184905260038101546060830152600481015460808301526005015491821660a08201526101009091046001600160401b031660c0820152906114ba5760009250505061157c565b600081604001516001600160a01b03166370a082316110046040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561151857600080fd5b505afa15801561152c573d6000803e3d6000fd5b505050506040513d602081101561154257600080fd5b5051608083015160608401519192506000916115639163ffffffff613a4316565b9050611575818363ffffffff613a4316565b9450505050505b919050565b606081565b600581565b600881565b61200081565b6402540be40081565b600281565b6001600160a01b03821660009081526002602052604081205460ff16156115fc5760405162461bcd60e51b815260040180806020018281038252602b815260200180615ab1602b913960400191505060405180910390fd5b600061160783613bfc565b90506116116157c5565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526116d6576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b60006116f382608001518360600151613a4390919063ffffffff16565b905081604001516001600160a01b0316866001600160a01b0316146117495760405162461bcd60e51b81526004018080602001828103825260458152602001806159a86045913960600191505060405180910390fd5b336001600160a01b0316866001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b15801561178c57600080fd5b505afa1580156117a0573d6000803e3d6000fd5b505050506040513d60208110156117b657600080fd5b50516001600160a01b0316146117fd5760405162461bcd60e51b815260040180806020018281038252602e81526020018061590b602e913960400191505060405180910390fd5b604080516370a0823160e01b8152611004600482015290516000916001600160a01b038916916370a0823191602480820192602092909190829003018186803b15801561184957600080fd5b505afa15801561185d573d6000803e3d6000fd5b505050506040513d602081101561187357600080fd5b505160408051636eb1769f60e11b8152336004820152306024820152905191925083916119049184916001600160a01b038c169163dd62ed3e916044808301926020929190829003018186803b1580156118cc57600080fd5b505afa1580156118e0573d6000803e3d6000fd5b505050506040513d60208110156118f657600080fd5b50519063ffffffff6139a916565b1015611957576040805162461bcd60e51b815260206004820152601760248201527f616c6c6f77616e6365206973206e6f7420656e6f756768000000000000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561199957600080fd5b505afa1580156119ad573d6000803e3d6000fd5b505050506040513d60208110156119c357600080fd5b505190508082108015906119dc57506402540be4008206155b611a175760405162461bcd60e51b81526004018080602001828103825260378152602001806159716037913960400191505060405180910390fd5b6000611a23868b613c03565b905063ffffffff8116611c22576001600160a01b038a166323b872dd33611004611a53898963ffffffff613a4316565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015611abb57600080fd5b505af1158015611acf573d6000803e3d6000fd5b505050506040513d6020811015611ae557600080fd5b5050602086015160408088015160a089015182516323bfccdb60e21b815260048101949094526001600160a01b03909116602484015260ff1660448301525161100491638eff336c91606480830192600092919082900301818387803b158015611b4e57600080fd5b505af1158015611b62573d6000803e3d6000fd5b50505050896001600160a01b03167f78e7dd9aefcdbf795c4936a66f7dc6d41bb56637b54f561a6bf7829dca3348a88a8860600151886040518080602001848152602001838152602001828103825285818151815260200191508051906020019080838360005b83811015611be1578181015183820152602001611bc9565b50505050905090810190601f168015611c0e5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2611cda565b896001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a1078a8360405180806020018363ffffffff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611c9e578181015183820152602001611c86565b50505050905090810190601f168015611ccb5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25b60008781526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff19169055611d34615801565b5060408051808201825263ffffffff831681526020810189905290516110049085156108fc029086906000818181858888f19350505050158015611d7c573d6000803e3d6000fd5b5061200063f7a251d76001611d908461405d565b611da5886402540be40063ffffffff613bba16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611e03578181015183820152602001611deb565b50505050905090810190601f168015611e305780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015611e5157600080fd5b505af1158015611e65573d6000803e3d6000fd5b5060019e9d5050505050505050505050505050565b61100581565b600080611e8c83613bfc565b9050611e966157c5565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c0830152611f5b576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b428160c001516001600160401b031610611fbc576040805162461bcd60e51b815260206004820152601b60248201527f62696e642072657175657374206973206e6f7420657870697265640000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015611ffe57600080fd5b505afa158015612012573d6000803e3d6000fd5b505050506040513d602081101561202857600080fd5b5051905080821080159061204157506402540be4008206155b61207c5760405162461bcd60e51b81526004018080602001828103825260378152602001806159716037913960400191505060405180910390fd5b60008481526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556120d6615801565b50604080518082018252600181526020810186905290516110049084156108fc029085906000818181858888f19350505050158015612119573d6000803e3d6000fd5b5061200063f7a251d7600161212d8461405d565b612142876402540be40063ffffffff613bba16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156121a0578181015183820152602001612188565b50505050905090810190601f1680156121cd5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156121ee57600080fd5b505af1158015612202573d6000803e3d6000fd5b5050505083604001516001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a10788600160405180806020018360ff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561228457818101518382015260200161226c565b50505050905090810190601f1680156122b15780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25060019695505050505050565b61100881565b6000806122de83613bfc565b90506122e86157c5565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526123ad576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b80604001516001600160a01b0316856001600160a01b0316146124015760405162461bcd60e51b81526004018080602001828103825260458152602001806159a86045913960600191505060405180910390fd5b336001600160a01b0316856001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b15801561244457600080fd5b505afa158015612458573d6000803e3d6000fd5b505050506040513d602081101561246e57600080fd5b50516001600160a01b0316146124cb576040805162461bcd60e51b815260206004820152601b60248201527f6f6e6c79206265703230206f776e65722063616e2072656a6563740000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561250d57600080fd5b505afa158015612521573d6000803e3d6000fd5b505050506040513d602081101561253757600080fd5b5051905080821080159061255057506402540be4008206155b61258b5760405162461bcd60e51b81526004018080602001828103825260378152602001806159716037913960400191505060405180910390fd5b60008481526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556125e5615801565b50604080518082018252600781526020810186905290516110049084156108fc029085906000818181858888f19350505050158015612628573d6000803e3d6000fd5b5061200063f7a251d7600161263c8461405d565b612651876402540be40063ffffffff613bba16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156126af578181015183820152602001612697565b50505050905090810190601f1680156126dc5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156126fd57600080fd5b505af1158015612711573d6000803e3d6000fd5b50505050876001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a10788600760405180806020018360ff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561278f578181015183820152602001612777565b50505050905090810190601f1680156127bc5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2506001979650505050505050565b600b81565b60045481565b33612000146128235760405162461bcd60e51b815260040180806020018281038252602f815260200180615a82602f913960400191505060405180910390fd5b60ff8316600414156128735761286e82828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506140d392505050565b61292d565b60ff8316600514156128be5761286e82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061438092505050565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a15b505050565b6040805163bd46646160e01b81526001600160a01b0384166004820152905160009182916110049163bd466461916024808301926020929190829003018186803b15801561297f57600080fd5b505afa158015612993573d6000803e3d6000fd5b505050506040513d60208110156129a957600080fd5b5051146129ed576040805162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e48189bdd5b99609a1b604482015290519081900360640190fd5b6001600160a01b03831660009081526002602052604090205460ff1615612a4c576040805162461bcd60e51b815260206004820152600e60248201526d6d6972726f722070656e64696e6760901b604482015290519081900360640190fd5b60006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015612a8957600080fd5b505afa158015612a9d573d6000803e3d6000fd5b505050506040513d6020811015612ab357600080fd5b505190506402540be4003406158015612ade5750600454612ada908263ffffffff6139a916565b3410155b612b195760405162461bcd60e51b815260040180806020018281038252604d8152602001806158be604d913960600191505060405180910390fd5b42607801836001600160401b031610158015612b435750426201518001836001600160401b031611155b612b7e5760405162461bcd60e51b81526004018080602001828103825260388152602001806159396038913960400191505060405180910390fd5b6000846001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612bb957600080fd5b505afa158015612bcd573d6000803e3d6000fd5b505050506040513d6020811015612be357600080fd5b5051604080516318160ddd60e01b815290519192506000916001600160a01b038816916318160ddd916004808301926020929190829003018186803b158015612c2b57600080fd5b505afa158015612c3f573d6000803e3d6000fd5b505050506040513d6020811015612c5557600080fd5b50519050677ce66c50e2840000612c6f8260ff8516613a03565b1115612cbb576040805162461bcd60e51b8152602060048201526016602482015275746f6f206c6172676520746f74616c20737570706c7960501b604482015290519081900360640190fd5b6060866001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b158015612cf657600080fd5b505afa158015612d0a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612d3357600080fd5b8101908080516040519392919084600160201b821115612d5257600080fd5b908301906020820185811115612d6757600080fd5b8251600160201b811182820188101715612d8057600080fd5b82525081516020918201929091019080838360005b83811015612dad578181015183820152602001612d95565b50505050905090810190601f168015612dda5780820380516001836020036101000a031916815260200191505b50604052505050905060608190506001815110158015612dfc57506020815111155b612e4d576040805162461bcd60e51b815260206004820152601d60248201527f6e616d65206c656e677468206d75737420626520696e205b312c33325d000000604482015290519081900360640190fd5b6060886001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015612e8857600080fd5b505afa158015612e9c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612ec557600080fd5b8101908080516040519392919084600160201b821115612ee457600080fd5b908301906020820185811115612ef957600080fd5b8251600160201b811182820188101715612f1257600080fd5b82525081516020918201929091019080838360005b83811015612f3f578181015183820152602001612f27565b50505050905090810190601f168015612f6c5780820380516001836020036101000a031916815260200191505b5060405250508151919250829160031180159150612f8c57508051600810155b612fdd576040805162461bcd60e51b815260206004820152601e60248201527f73796d626f6c206c656e677468206d75737420626520696e205b332c385d0000604482015290519081900360640190fd5b60005b81518160ff1610156130d957606160f81b828260ff168151811061300057fe5b01602001516001600160f81b0319161080159061303e5750606160f81b828260ff168151811061302c57fe5b01602001516001600160f81b03191611155b806130965750604160f81b828260ff168151811061305857fe5b01602001516001600160f81b031916108015906130965750602d60f91b828260ff168151811061308457fe5b01602001516001600160f81b03191611155b6130d15760405162461bcd60e51b8152600401808060200182810382526024815260200180615adc6024913960400191505060405180910390fd5b600101612fe0565b50600454611004906108fc906130f690349063ffffffff613a4316565b6040518115909202916000818181858888f1935050505015801561311e573d6000803e3d6000fd5b506001600160a01b038a166000908152600260209081526040909120805460ff191660011790558481015190830151613155615818565b604051806101000160405280336001600160a01b031681526020018e6001600160a01b031681526020018481526020018381526020018981526020018a60ff1681526020016402540be400600454816131aa57fe5b0481526001600160401b038e16602090910152905061200063f7a251d760046131d284614543565b6131f06402540be40061130960045434613a4390919063ffffffff16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561324e578181015183820152602001613236565b50505050905090810190601f16801561327b5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561329c57600080fd5b505af11580156132b0573d6000803e3d6000fd5b5050505060019a505050505050505050505092915050565b600781565b600981565b677ce66c50e284000081565b61100781565b61100681565b60005460ff1681565b33611007146133335760405162461bcd60e51b815260040180806020018281038252602e815260200180615a54602e913960400191505060405180910390fd5b60208114613388576040805162461bcd60e51b815260206004820152601860248201527f65787065637465642076616c7565206c656e6774682033320000000000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f880181900481028201810190925286815293945060609392508691508590819084018382808284376000920191909152505050506020830151909150686d6972726f7246656560b81b81141561347d5760208201516402540be400810615613475576040805162461bcd60e51b815260206004820152601a60248201527f6d6972726f72466565206d757374206265204e202a2031653130000000000000604482015290519081900360640190fd5b600455613533565b6673796e6346656560c81b8114156134f65760208201516402540be4008106156134ee576040805162461bcd60e51b815260206004820152601860248201527f73796e63466565206d757374206265204e202a20316531300000000000000000604482015290519081900360640190fd5b600555613533565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b61100281565b336120001461360e5760405162461bcd60e51b815260040180806020018281038252602f815260200180615a82602f913960400191505060405180910390fd5b60ff8316600414156136595761286e82828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506146b592505050565b60ff8316600514156128be5761286e82828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506147d592505050565b600160208190526000918252604090912080549181015460028201546003830154600484015460059094015460ff9586169593946001600160a01b039093169391929181169061010090046001600160401b031687565b61100381565b60055481565b61100081565b61271081565b61100481565b60606137236157c5565b600061372e846148da565b9150915080613784576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b815160ff16613837576020828101805160009081526001928390526040908190208551815460ff1990811660ff928316178355935194820194909455908501516002820180546001600160a01b0319166001600160a01b03909216919091179055606085015160038201556080850151600482015560a08501516005909101805460c08701519316919093161768ffffffffffffffff0019166101006001600160401b039092169190910217905561398e565b815160ff16600114156139415760006110046001600160a01b03166359b9278984602001516040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561389057600080fd5b505afa1580156138a4573d6000803e3d6000fd5b505050506040513d60208110156138ba57600080fd5b505190506001600160a01b0381161561393b5760208301516040805163b99328c560e01b815260048101929092526001600160a01b0383166024830152516110049163b99328c591604480830192600092919082900301818387803b15801561392257600080fd5b505af1158015613936573d6000803e3d6000fd5b505050505b5061398e565b6040805162461bcd60e51b815260206004820152601960248201527f756e7265636f676e697a65642062696e64207061636b61676500000000000000604482015290519081900360640190fd5b60408051600080825260208201909252905b50949350505050565b600082820183811015610e95576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006008821115613a2c57613a25836007198401600a0a63ffffffff613bba16565b90506113e3565b610e95836008849003600a0a63ffffffff614a2b16565b6000610e9583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614a84565b60408051600680825260e08201909252606091829190816020015b6060815260200190600190039081613aa05750508351909150613acb906001600160a01b0316614b1b565b81600081518110613ad857fe5b6020026020010181905250613af983602001516001600160a01b0316614b1b565b81600181518110613b0657fe5b6020026020010181905250613b21836040015160001c614b3e565b81600281518110613b2e57fe5b6020026020010181905250613b468360600151614b3e565b81600381518110613b5357fe5b6020026020010181905250613b6b8360800151614b3e565b81600481518110613b7857fe5b6020026020010181905250613b998360a001516001600160401b0316614b3e565b81600581518110613ba657fe5b6020026020010181905250610e9581614b51565b6000610e9583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614bdb565b6020015190565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015613c3f57600080fd5b505afa158015613c53573d6000803e3d6000fd5b505050506040513d6020811015613c6957600080fd5b5051604080516395d89b4160e01b8152905160ff90921692506060916001600160a01b038616916395d89b41916004808301926000929190829003018186803b158015613cb557600080fd5b505afa158015613cc9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613cf257600080fd5b8101908080516040519392919084600160201b821115613d1157600080fd5b908301906020820185811115613d2657600080fd5b8251600160201b811182820188101715613d3f57600080fd5b82525081516020918201929091019080838360005b83811015613d6c578181015183820152602001613d54565b50505050905090810190601f168015613d995780820380516001836020036101000a031916815260200191505b5060408181526370a0823160e01b82526110046004830152519495506000946001600160a01b038a1694506370a08231935060248083019350602092829003018186803b158015613de957600080fd5b505afa158015613dfd573d6000803e3d6000fd5b505050506040513d6020811015613e1357600080fd5b505160808701516060880151919250600091613e349163ffffffff613a4316565b9050428760c001516001600160401b03161015613e595750600193506113e392505050565b613e67838860200151614c40565b613e795750600293506113e392505050565b80821115613e8f5750600393506113e392505050565b866060015187604001516001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613ed157600080fd5b505afa158015613ee5573d6000803e3d6000fd5b505050506040513d6020811015613efb57600080fd5b505114613f105750600493506113e392505050565b8660a0015160ff168414613f2c5750600593506113e392505050565b602080880151604080516359b9278960e01b8152600481019290925251600092611004926359b927899260248083019392829003018186803b158015613f7157600080fd5b505afa158015613f85573d6000803e3d6000fd5b505050506040513d6020811015613f9b57600080fd5b50516001600160a01b031614158061403d57506000801b6110046001600160a01b031663bd46646189604001516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561400e57600080fd5b505afa158015614022573d6000803e3d6000fd5b505050506040513d602081101561403857600080fd5b505114155b156140505750600693506113e392505050565b5060009695505050505050565b6040805160028082526060828101909352829190816020015b6060815260200190600190039081614076575050835190915061409e9063ffffffff16614b3e565b816000815181106140ab57fe5b60200260200101819052506140c6836020015160001c614b3e565b81600181518110613ba657fe5b6140db615790565b60006140e683614d28565b9150915080614133576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b6020808301516001600160a01b03166000908152600290915260409020805460ff1916905560a082015160ff166142945760808201516040516110049180156108fc02916000818181858888f19350505050158015614196573d6000803e3d6000fd5b506110046001600160a01b0316638eff336c8360600151846020015185604001516040518463ffffffff1660e01b815260040180848152602001836001600160a01b03166001600160a01b031681526020018260ff1681526020019350505050600060405180830381600087803b15801561421057600080fd5b505af1158015614224573d6000803e3d6000fd5b50505050602082810180516001600160a01b03908116600090815260038452604090819020805460ff1916600117905591516060860151835190815292519116927f41787d7db08fc5907641ee8343379f28215727eb123d4b462099afab4300b036928290030190a2505061437d565b81602001516001600160a01b03167fefe400ad0042ebf81a245de9ae669616105e0ca9fc946352c085da0c2bc524e58360a00151604051808260ff1660ff16815260200191505060405180910390a2815160808301516040516000926001600160a01b0316916127109184818181858888f193505050503d8060008114614337576040519150601f19603f3d011682016040523d82523d6000602084013e61433c565b606091505b50509050806143795760808301516040516110029180156108fc02916000818181858888f19350505050158015614377573d6000803e3d6000fd5b505b5050505b50565b61438861585c565b600061439383614e35565b91509150806143e0576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b606082015160ff166144605760408083015190516110049180156108fc02916000818181858888f1935050505015801561441e573d6000803e3d6000fd5b5081602001516001600160a01b03167fbb7d3a9a559080d8281b0e4fb39dacbe2fdcafd5ef765e9a6ed871c9167dc60f60405160405180910390a2505061437d565b81602001516001600160a01b03167ff1e25fa536da84053644fd788b1d6a27ea6edd1f3af80c7d36ca253c4c82c9c38360600151604051808260ff1660ff16815260200191505060405180910390a2815160408084015190516000926001600160a01b0316916127109184818181858888f193505050503d8060008114614503576040519150601f19603f3d011682016040523d82523d6000602084013e614508565b606091505b50509050806143795760408084015190516110029180156108fc02916000818181858888f19350505050158015614377573d6000803e3d6000fd5b6040805160088082526101208201909252606091829190816020015b606081526020019060019003908161455f575050835190915061458a906001600160a01b0316614b1b565b8160008151811061459757fe5b60200260200101819052506145b883602001516001600160a01b0316614b1b565b816001815181106145c557fe5b60200260200101819052506145e0836040015160001c614b3e565b816002815181106145ed57fe5b6020026020010181905250614608836060015160001c614b3e565b8160038151811061461557fe5b602002602001018190525061462d8360800151614b3e565b8160048151811061463a57fe5b60200260200101819052506146558360a0015160ff16614b3e565b8160058151811061466257fe5b602002602001018190525061467a8360c00151614b3e565b8160068151811061468757fe5b60200260200101819052506146a88360e001516001600160401b0316614b3e565b81600781518110613ba657fe5b6146bd615818565b60006146c883614f01565b9150915080614715576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b6020808301516001600160a01b03908116600090815260029092526040808320805460ff19169055845160c08601519151921691612710916402540be400029084818181858888f193505050503d806000811461478e576040519150601f19603f3d011682016040523d82523d6000602084013e614793565b606091505b50509050806143795760c0830151604051611002916402540be4000280156108fc02916000818181858888f19350505050158015614377573d6000803e3d6000fd5b6147dd615790565b60006147e883615052565b9150915080614835576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b815160808301516040516000926001600160a01b031691612710916402540be4009091029084818181858888f193505050503d8060008114614893576040519150601f19603f3d011682016040523d82523d6000602084013e614898565b606091505b5050905080614379576080830151604051611002916402540be4000280156108fc02916000818181858888f19350505050158015614377573d6000803e3d6000fd5b6148e26157c5565b60006148ec6157c5565b6148f4615883565b61490561490086615162565b615187565b90506000805b614914836151d1565b15614a1e57806149395761492f61492a846151f2565b615240565b60ff168452614a16565b80600114156149585761494e61492a846151f2565b6020850152614a16565b80600214156149855761497261496d846151f2565b6152f5565b6001600160a01b03166040850152614a16565b80600314156149a45761499a61492a846151f2565b6060850152614a16565b80600414156149c3576149b961492a846151f2565b6080850152614a16565b80600514156149e5576149d861492a846151f2565b60ff1660a0850152614a16565b8060061415614a11576149fa61492a846151f2565b6001600160401b031660c085015260019150614a16565b614a1e565b60010161490b565b5091935090915050915091565b600082614a3a575060006113e3565b82820282848281614a4757fe5b0414610e955760405162461bcd60e51b81526004018080602001828103825260218152602001806159ed6021913960400191505060405180910390fd5b60008184841115614b135760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614ad8578181015183820152602001614ac0565b50505050905090810190601f168015614b055780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60408051600560a21b8318601482015260348101909152606090610e958161530f565b60606113e3614b4c83615365565b61530f565b6060815160001415614b72575060408051600081526020810190915261157c565b606082600081518110614b8157fe5b602002602001015190506000600190505b8351811015614bc257614bb882858381518110614bab57fe5b602002602001015161544b565b9150600101614b92565b50610e95614bd5825160c060ff166154c8565b8261544b565b60008183614c2a5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614ad8578181015183820152602001614ac0565b506000838581614c3657fe5b0495945050505050565b8151600090839060081080614c56575080516003115b15614c655760009150506113e3565b60408051602080825281830190925260609160208201818036833701905050905083602082015280825181518110614c9957fe5b6020910101516001600160f81b031916602d60f81b14614cbe576000925050506113e3565b600160005b8351811015614d1e57828181518110614cd857fe5b602001015160f81c60f81b6001600160f81b031916848281518110614cf957fe5b01602001516001600160f81b03191614614d165760009150614d1e565b600101614cc3565b5095945050505050565b614d30615790565b6000614d3a615790565b614d42615883565b614d4e61490086615162565b90506000805b614d5d836151d1565b15614a1e5780614d8357614d7361496d846151f2565b6001600160a01b03168452614e2d565b8060011415614dab57614d9861496d846151f2565b6001600160a01b03166020850152614e2d565b8060021415614dcd57614dc061492a846151f2565b60ff166040850152614e2d565b8060031415614dec57614de261492a846151f2565b6060850152614e2d565b8060041415614e0b57614e0161492a846151f2565b6080850152614e2d565b8060051415614a1157614e2061492a846151f2565b60ff1660a0850152600191505b600101614d54565b614e3d61585c565b6000614e4761585c565b614e4f615883565b614e5b61490086615162565b90506000805b614e6a836151d1565b15614a1e5780614e9057614e8061496d846151f2565b6001600160a01b03168452614ef9565b8060011415614eb857614ea561496d846151f2565b6001600160a01b03166020850152614ef9565b8060021415614ed757614ecd61492a846151f2565b6040850152614ef9565b8060031415614a1157614eec61492a846151f2565b60ff166060850152600191505b600101614e61565b614f09615818565b6000614f13615818565b614f1b615883565b614f2761490086615162565b90506000805b614f36836151d1565b15614a1e5780614f5c57614f4c61496d846151f2565b6001600160a01b0316845261504a565b8060011415614f8457614f7161496d846151f2565b6001600160a01b0316602085015261504a565b8060021415614fa357614f9961492a846151f2565b604085015261504a565b8060031415614fc257614fb861492a846151f2565b606085015261504a565b8060041415614fe157614fd761492a846151f2565b608085015261504a565b806005141561500357614ff661492a846151f2565b60ff1660a085015261504a565b80600614156150225761501861492a846151f2565b60c085015261504a565b8060071415614a115761503761492a846151f2565b6001600160401b031660e0850152600191505b600101614f2d565b61505a615790565b6000615064615790565b61506c615883565b61507861490086615162565b90506000805b615087836151d1565b15614a1e57806150ad5761509d61496d846151f2565b6001600160a01b0316845261515a565b80600114156150d5576150c261496d846151f2565b6001600160a01b0316602085015261515a565b80600214156150f4576150ea61492a846151f2565b604085015261515a565b80600314156151135761510961492a846151f2565b606085015261515a565b80600414156151325761512861492a846151f2565b608085015261515a565b8060051415614a115761514761492a846151f2565b6001600160401b031660a0850152600191505b60010161507e565b61516a6158a3565b506040805180820190915281518152602082810190820152919050565b61518f615883565b615198826155c0565b6151a157600080fd5b60006151b083602001516155fa565b60208085015160408051808201909152868152920190820152915050919050565b60006151db6158a3565b505080518051602091820151919092015191011190565b6151fa6158a3565b615203826151d1565b61520c57600080fd5b6020820151600061521c8261565d565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061525557508151602110155b61525e57600080fd5b600061526d83602001516155fa565b905080836000015110156152c8576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b8251602080850151830180519284900392918310156139a057506020919091036101000a90049392505050565b805160009060151461530657600080fd5b6113e382615240565b6060815160011480156153415750607f60f81b8260008151811061532f57fe5b01602001516001600160f81b03191611155b1561534d57508061157c565b6113e361535f8351608060ff166154c8565b8361544b565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166153a9575060186153cd565b6fffffffffffffffffffffffffffffffff1984166153c9575060106153cd565b5060005b6020811015615403578181815181106153e257fe5b01602001516001600160f81b031916156153fb57615403565b6001016153cd565b60008160200390506060816040519080825280601f01601f191660200182016040528015615438576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b8183101561547c578051835260209283019201615464565b50855184518101855292509050808201602086015b818310156154a9578051835260209283019201615491565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310615518576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116155725782840160f81b8160008151811061555457fe5b60200101906001600160f81b031916908160001a90535090506113e3565b606061557d85615365565b90508381510160370160f81b8260008151811061559657fe5b60200101906001600160f81b031916908160001a9053506155b7828261544b565b95945050505050565b80516000906155d15750600061157c565b6020820151805160001a9060c08210156155f05760009250505061157c565b5060019392505050565b8051600090811a608081101561561457600091505061157c565b60b881108061562f575060c0811080159061562f575060f881105b1561563e57600191505061157c565b60c08110156156525760b51901905061157c565b60f51901905061157c565b80516000908190811a60808110156156785760019150615789565b60b881101561568d57607e1981019150615789565b60c081101561570757600060b78203600186019550806020036101000a865104915060018101820193505080831015615701576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50615789565b60f881101561571c5760be1981019150615789565b600060f78203600186019550806020036101000a865104915060018101820193505080831015615787576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080518082019091526000808252602082015290565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b60405180604001604052806158966158a3565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe6d73672e76616c7565206d757374206265204e202a203165313020616e642067726561746572207468616e2073756d206f66206d696e6952656c617946656520616e64206d6972726f724665656f6e6c79206265703230206f776e65722063616e20617070726f766520746869732062696e64207265717565737465787069726554696d65206d7573742062652074776f206d696e75746573206c6174657220616e64206f6e6520646179206561726c69657272656c6179466565206d757374206265204e202a203165313020616e642067726561746572207468616e206d696e6952656c6179466565636f6e74616374206164647265737320646f65736e277420657175616c20746f2074686520636f6e7472616374206164647265737320696e2062696e642072657175657374536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f776d73672e76616c7565206d757374206265204e202a203165313020616e64206e6f206c6573732073756d206f66206d696e6952656c617946656520616e642073796e63466565746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e747261637474686520626570323020746f6b656e20697320696e206d6972726f722070656e64696e672073746174757373796d626f6c206d757374206e6f7420636f6e7461696e206e6f6e2d616c706861626574a26469706673582212201165eef2c3a9b93126944a081b2726c7c09babc88a4afff1c0ba3b8ec0bcb9ec64736f6c63430006040033" }, "0x0000000000000000000000000000000000002000": { "balance": "0x0", diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index c93fc4d8..bf32face 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -23,6 +23,7 @@ const TokenHub = artifacts.require("TokenHub"); const TokenManager = artifacts.require("TokenManager"); const ABCToken = artifacts.require("test/ABCToken"); const DEFToken = artifacts.require("test/DEFToken"); +const XYZToken = artifacts.require("test/XYZToken"); const MiniToken = artifacts.require("test/MiniToken"); const MaliciousToken = artifacts.require("test/MaliciousToken"); const BSCValidatorSetTool = artifacts.require("tool/BSCValidatorSetTool"); @@ -48,6 +49,7 @@ module.exports = function(deployer, network, accounts) { }); deployer.deploy(ABCToken); deployer.deploy(DEFToken); + deployer.deploy(XYZToken); deployer.deploy(MiniToken); deployer.deploy(MaliciousToken); deployer.deploy(MockRelayerHub); diff --git a/test/TestTokenHub.js b/test/TestTokenHub.js index 206c0a57..2469f794 100644 --- a/test/TestTokenHub.js +++ b/test/TestTokenHub.js @@ -11,9 +11,13 @@ const TokenManager = artifacts.require("TokenManager"); const CrossChain = artifacts.require("CrossChain"); const ABCToken = artifacts.require("ABCToken"); const DEFToken = artifacts.require("DEFToken"); +const XYZToken = artifacts.require("test/XYZToken"); const MiniToken = artifacts.require("test/MiniToken"); const MaliciousToken = artifacts.require("test/MaliciousToken"); const RelayerHub = artifacts.require("RelayerHub"); +const GovHub = artifacts.require("GovHub"); +const BSCValidatorSet = artifacts.require("BSCValidatorSet"); +const SlashIndicator = artifacts.require("SlashIndicator"); const crypto = require('crypto'); const Web3 = require('web3'); @@ -23,6 +27,9 @@ const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); const BIND_CHANNEL_ID = 0x01; const TRANSFER_IN_CHANNELID = 0x02; const TRANSFER_OUT_CHANNELID = 0x03; +const MIRROR_CHANNELID = 0x04; +const SYNC_CHANNELID = 0x05; +const GOV_CHANNEL_ID = 0x09; const proof = Buffer.from(web3.utils.hexToBytes("0x00")); const merkleHeight = 100; @@ -38,7 +45,7 @@ function toBytes32String(input) { return inputHexStr; } -function toBytes32Bep2Symbol(symbol) { +function stringToBytes32(symbol) { var initialSymbolHexStr = ''; for (var i=0; i=33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); + mirrorSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); + + const mirrorSender = web3.utils.bytesToHex(mirrorSynPackage[0]); + const bep20Addr = web3.utils.bytesToHex(mirrorSynPackage[1]); + const bep20Name = web3.utils.bytesToHex(mirrorSynPackage[2]); + const bep20Symbol = web3.utils.bytesToHex(mirrorSynPackage[3]); + const bep20Supply = web3.utils.bytesToHex(mirrorSynPackage[4]); + const bep20Decimals = web3.utils.bytesToHex(mirrorSynPackage[5]); + const mirrorFee = web3.utils.bytesToHex(mirrorSynPackage[6]); + const expireTime = web3.utils.bytesToHex(mirrorSynPackage[7]); + + return {mirrorSender, bep20Addr, bep20Name, bep20Symbol, bep20Supply, bep20Decimals, mirrorFee, expireTime}; +} + +function buildMirrorAckPackage(mirrorSender, bep20Addr, bep20Decimals, bep2Symbol, refundAmount, errorCode) { + const packageBytesPrefix = buildAckPackagePrefix(); + const packageBytes = RLP.encode([ + mirrorSender, + bep20Addr, + bep20Decimals, + stringToBytes32(bep2Symbol), + refundAmount, + errorCode]); + return Buffer.concat([packageBytesPrefix, packageBytes]); +} + +function decodeSyncSynPackage(packageBytes) { + eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(packageBytes)); + assert.ok(eventPayloadBytes.length>=33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); + syncSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); + const syncSender = web3.utils.bytesToHex(syncSynPackage[0]); + const bep20Addr = web3.utils.bytesToHex(syncSynPackage[1]); + const bep2Symbol = web3.utils.bytesToHex(syncSynPackage[2]); + const bep20Supply = web3.utils.bytesToHex(syncSynPackage[3]); + const syncFee = web3.utils.bytesToHex(syncSynPackage[4]); + const expireTime = web3.utils.bytesToHex(syncSynPackage[5]); + return {syncSender, bep20Addr, bep2Symbol, bep20Supply, syncFee, expireTime}; +} + +function buildSyncAckPackage(syncSender, bep20Addr, refundAmount, errorCode) { + const packageBytesPrefix = buildAckPackagePrefix(); + const packageBytes = RLP.encode([ + syncSender, + bep20Addr, + refundAmount, + errorCode + ]); + return Buffer.concat([packageBytesPrefix, packageBytes]); +} + +function serialize(key, value, target, extra) { + let pkg = []; + pkg.push(key); + pkg.push(value); + pkg.push(target); + if(extra != null){ + pkg.push(extra); + } + return RLP.encode(pkg); +} + function verifyPrefixAndExtractSyncPackage(payload, expectedRelayFee) { eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(payload)); assert.ok(eventPayloadBytes.length>=33, "wrong bind ack package"); @@ -182,8 +261,8 @@ contract('TokenHub', (accounts) => { await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); - let bindRequenst = await tokenManager.bindPackageRecord.call(toBytes32Bep2Symbol("ABC-9C7")); // symbol: ABC-9C7 - assert.equal(bindRequenst.bep2TokenSymbol.toString(), toBytes32Bep2Symbol("ABC-9C7"), "wrong bep2TokenSymbol"); + let bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 + assert.equal(bindRequenst.bep2TokenSymbol.toString(), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); assert.equal(bindRequenst.totalSupply.eq(new BN('52b7d2dcc80cd2e4000000', 16)), true, "wrong total supply"); // 1e26 assert.equal(bindRequenst.peggyAmount.eq(new BN('51e410c0f93fe543000000', 16)), true, "wrong peggy amount"); // 99e24 assert.equal(bindRequenst.contractAddr.toString(), abcToken.address.toString(), "wrong contract address"); @@ -219,9 +298,9 @@ contract('TokenHub', (accounts) => { let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); - assert.equal(web3.utils.bytesToHex(decoded[1]), toBytes32Bep2Symbol("ABC-9C7"), "wrong bep2TokenSymbol"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - bindRequenst = await tokenManager.bindPackageRecord.call(toBytes32Bep2Symbol("ABC-9C7")); // symbol: ABC-9C7 + bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); }); it('Reject bind', async () => { @@ -250,9 +329,9 @@ contract('TokenHub', (accounts) => { decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); assert.equal(web3.utils.bytesToHex(decoded[0]), "0x07", "bind status should be rejected"); - assert.equal(web3.utils.bytesToHex(decoded[1]), toBytes32Bep2Symbol("ABC-9C7"), "wrong bep2TokenSymbol"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - const bindRequenst = await tokenManager.bindPackageRecord.call(toBytes32Bep2Symbol("ABC-9C7")); // symbol: ABC-9C7 + const bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); }); it('Expire bind', async () => { @@ -282,9 +361,9 @@ contract('TokenHub', (accounts) => { let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); - assert.equal(web3.utils.bytesToHex(decoded[1]), toBytes32Bep2Symbol("ABC-9C7"), "wrong bep2TokenSymbol"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - bindRequenst = await tokenManager.bindPackageRecord.call(toBytes32Bep2Symbol("ABC-9C7")); // symbol: ABC-9C7 + bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); }); it('Mismatched token symbol', async () => { @@ -305,9 +384,9 @@ contract('TokenHub', (accounts) => { let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); assert.equal(web3.utils.bytesToHex(decoded[0]), "0x02", "bind status should be symbol mismatch"); - assert.equal(web3.utils.bytesToHex(decoded[1]), toBytes32Bep2Symbol("DEF-9C7"), "wrong bep2TokenSymbol"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("DEF-9C7"), "wrong bep2TokenSymbol"); - bindRequenst = await tokenManager.bindPackageRecord.call(toBytes32Bep2Symbol("DEF-9C7")); // symbol: ABC-9C7 + bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("DEF-9C7")); // symbol: ABC-9C7 assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); }); it('Success bind', async () => { @@ -330,7 +409,7 @@ contract('TokenHub', (accounts) => { 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("ABC-9C7"), "wrong bep2TokenSymbol"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); const tokenHub = await TokenHub.deployed(); const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); @@ -382,7 +461,7 @@ contract('TokenHub', (accounts) => { return matched; }); let decoded = verifyPrefixAndExtractAckPackage(event.payload); - assert.equal(web3.utils.bytesToHex(decoded[0]), toBytes32Bep2Symbol("ABC-9C7"), "response should be empty"); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "response should be empty"); assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(155e7).toString(16), "response should be empty"); assert.equal(web3.utils.bytesToHex(decoded[2]), "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", "response should be empty"); assert.equal(web3.utils.bytesToHex(decoded[3]), "0x01", "refund status should be timeout"); @@ -430,7 +509,7 @@ contract('TokenHub', (accounts) => { return matched; }); let decoded = verifyPrefixAndExtractAckPackage(event.payload); - assert.equal(web3.utils.bytesToHex(decoded[0]), toBytes32Bep2Symbol("BNB"), "response should be empty"); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "response should be empty"); assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(1e8).toString(16), "response should be empty"); assert.equal(web3.utils.bytesToHex(decoded[2]), "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", "response should be empty"); assert.equal(web3.utils.bytesToHex(decoded[3]), "0x04", "refund status should be non-payable recipient address"); @@ -511,7 +590,7 @@ contract('TokenHub', (accounts) => { let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), toBytes32Bep2Symbol("ABC-9C7"), "wrong symbol"); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "wrong symbol"); assert.equal(web3.utils.bytesToHex(decoded[1]), abcToken.address.toLowerCase(), "wrong contract address"); assert.ok(web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e8)), "wrong transferOut amount"); assert.equal(web3.utils.bytesToHex(decoded[3][0]), recipient.toLowerCase(), "wrong recipient address"); @@ -578,7 +657,7 @@ contract('TokenHub', (accounts) => { assert.equal(tx.receipt.status, true, "failed transaction"); let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 2e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), toBytes32Bep2Symbol("BNB"), "wrong symbol"); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "wrong symbol"); assert.equal(web3.utils.bytesToHex(decoded[1]), "0x0000000000000000000000000000000000000000", "wrong contract address"); assert.ok(web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e6)), "wrong transferOut amount"); assert.ok(web3.utils.toBN(web3.utils.bytesToHex(decoded[2][1])).eq(web3.utils.toBN(2e6)), "wrong transferOut amount"); @@ -684,7 +763,7 @@ contract('TokenHub', (accounts) => { )); packageBytes = RLP.encode([ - toBytes32Bep2Symbol("ABC-9C7"), + stringToBytes32("ABC-9C7"), abcToken.address, [1e6, 2e6], ["0x37B8516a0F88E65D677229b402ec6C1e0E333004", "0xfA5E36a04EeF3152092099F352DDbe88953bB540"], @@ -786,7 +865,7 @@ contract('TokenHub', (accounts) => { 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"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("XYZ-9C7M"), "wrong bep2TokenSymbol"); const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(miniToken.address); assert.equal(bep2Symbol, "XYZ-9C7M", "wrong symbol"); @@ -823,4 +902,381 @@ contract('TokenHub', (accounts) => { const newBalance = await miniToken.balanceOf.call(accounts[2]); assert.equal(newBalance.sub(initBalance).eq(amount), true, "wrong balance"); }); + it('enable mirror and sync channel', async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + const govHub = await GovHub.deployed(); + + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, CrossChain.address); + + const owner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + const tokenMgrAddrStr = TokenManager.address.toString().replace("0x", ""); + let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + let govValue = "0x04" + "01" + tokenMgrAddrStr; + let govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x05" + "01" + tokenMgrAddrStr; + govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x0000000000000000000000000000000000000000000000056bc75e2d63100000";// 1e20; + govPackageBytes = serialize("mirrorFee", govValue, TokenManager.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x0000000000000000000000000000000000000000000000008ac7230489e80000"; // 1e19 + govPackageBytes = serialize("syncFee", govValue, TokenManager.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + const mirrorFee = await tokenManager.mirrorFee(); + assert.equal(web3.utils.toBN(1e20).eq(mirrorFee), true, "Wrong mirrorFee"); + const syncFee = await tokenManager.syncFee(); + assert.equal(web3.utils.toBN(1e19).eq(syncFee), true, "Wrong syncFee"); + + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, accounts[8]); + }); + it('iterate mirror failures', async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const miniToken = await MiniToken.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + const miniRelayFee = await tokenHub.getMiniRelayFee(); + const mirrorFee = await tokenManager.mirrorFee(); + const xyzTokenOwner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(miniToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("already bound")); + } + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 100; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); + } + + try { + await xyzToken.setName("", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("name length must be in [1,32]")); + } + + try { + await xyzToken.setName("XYZ TokenXYZ TokenXYZ TokenXYZ Token", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("name length must be in [1,32]")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XY", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol length must be in [3,8]")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZXYZXYZ", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol length must be in [3,8]")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("X-Z", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol must not contain non-alphabet")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(1, {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large total supply")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large total supply")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee).add(web3.utils.toBN(1e9))}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee).sub(web3.utils.toBN(1e9))}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("mirror pending")); + const mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); + const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "", mirrorFee, 1); + await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, {from: relayer}); + const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + } + + }); + it('successful mirror', async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const xyzTokenOwner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + + const miniRelayFee = await tokenHub.getMiniRelayFee(); + const xyzTokenTotalSupply = await xyzToken.totalSupply(); + const xyzTokenDecimals = await xyzToken.decimals(); + const xyzTokenName = await xyzToken.name(); + const xyzTokenSymbol = await xyzToken.symbol(); + + const mirrorFee = await tokenManager.mirrorFee(); + const syncFee = await tokenManager.syncFee(); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + let tx = await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decodedMirrorSynPackage = decodeMirrorSynPackage(nestedEventValues.payload); + assert.equal(decodedMirrorSynPackage.mirrorSender.toLowerCase(), player.toLowerCase(), "Wrong mirror sender in mirror sync package"); + assert.equal(decodedMirrorSynPackage.bep20Addr.toLowerCase(), XYZToken.address.toLowerCase(), "Wrong bep20 address in mirror sync package"); + assert.equal(decodedMirrorSynPackage.bep20Name, stringToBytes32(xyzTokenName), "Wrong bep20 name in mirror sync package"); // name: XYZ Token + assert.equal(decodedMirrorSynPackage.bep20Symbol, stringToBytes32(xyzTokenSymbol), "Wrong bep20 symbol in mirror sync package"); // symbol: XYZ + assert.equal(web3.utils.toBN(decodedMirrorSynPackage.mirrorFee).mul(web3.utils.toBN(1e10)).eq(mirrorFee), true, "Wrong mirrorFee in mirror sync package"); + assert.equal(web3.utils.hexToNumber(decodedMirrorSynPackage.bep20Decimals), xyzTokenDecimals, "Wrong decimals in mirror sync package"); + assert.equal(web3.utils.toBN(decodedMirrorSynPackage.bep20Supply).eq(xyzTokenTotalSupply), true, "Wrong total supply in mirror sync package"); + let tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); + + // mirror fail ack + let mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); + const mirrorFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); + await crossChain.handlePackage(Buffer.concat([buildFailAckPackagePrefix(), mirrorFailAckPackageBytes.subarray(33, mirrorFailAckPackageBytes.length)]), proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, {from: relayer}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + + // success mirror + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + tx = await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); + + mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); + const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "XYZ-123", mirrorFee, 0); + await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, {from: relayer}); + + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(xyzToken.address); + assert.equal(bep2Symbol, "XYZ-123", "wrong symbol"); + + + await xyzToken.mint(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); + + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + tx = await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(syncFee)}); + nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); + assert.equal(decodedSyncSynPackage.syncSender.toLowerCase(), player.toLowerCase(), "Wrong mirror sender in sync syn package"); + assert.equal(decodedSyncSynPackage.bep20Addr.toLowerCase(), XYZToken.address.toLowerCase(), "Wrong bep20 address in sync syn package"); + assert.equal(web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), true, "Wrong total supply in sync syn package"); + assert.equal(web3.utils.toBN(decodedSyncSynPackage.syncFee).mul(web3.utils.toBN(1e10)).eq(syncFee), true, "Wrong mirrorFee in sync syn package"); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); + + // sync fail ack package + let syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); + const syncFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); + await crossChain.handlePackage(Buffer.concat([buildFailAckPackagePrefix(), syncFailAckPackageBytes.subarray(33, syncFailAckPackageBytes.length)]), proof, merkleHeight, syncChannelSeq, SYNC_CHANNELID, {from: relayer}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + + // success sync and sync ack + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(syncFee)}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); + + syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); + await crossChain.handlePackage(buildSyncAckPackage(player, xyzToken.address, syncFee, 0), proof, merkleHeight, syncChannelSeq, SYNC_CHANNELID, {from: relayer}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + }); + it('iterate sync failures', async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const miniToken = await MiniToken.deployed(); + const defToken = await DEFToken.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + const miniRelayFee = await tokenHub.getMiniRelayFee(); + const mirrorFee = await tokenManager.mirrorFee(); + const xyzTokenOwner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + const syncFee = await tokenManager.syncFee(); + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(defToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee) + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("not bound")); + } + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(miniToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee) + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("not bound by mirror")); + } + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 100; // expire at five minutes later + await tokenManager.sync(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee) + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); + } + + try { + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large total supply")); + } + + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); + + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + tx = await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(syncFee)}); + nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); + assert.equal(web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), true, "Wrong total supply in sync syn package"); + }); });