Contract
0x0000000000000000000000000000000000001000
12
My Name Tag:
Not Available, login to update
ContractCreator:
GENESIS at txn GENESIS_0000000000000000000000000000000000001000
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
BSCValidatorSet
Compiler Version
v0.6.4+commit.1dca32f3
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at BscScan.com on 2020-09-02 */ // File: contracts/interface/ISystemReward.sol pragma solidity 0.6.4; interface ISystemReward { function claimRewards(address payable to, uint256 amount) external returns(uint256 actualAmount); } // File: contracts/interface/IRelayerHub.sol pragma solidity 0.6.4; interface IRelayerHub { function isRelayer(address sender) external view returns (bool); } // File: contracts/interface/ILightClient.sol pragma solidity 0.6.4; interface ILightClient { function isHeaderSynced(uint64 height) external view returns (bool); function getAppHash(uint64 height) external view returns (bytes32); function getSubmitter(uint64 height) external view returns (address payable); } // File: contracts/System.sol pragma solidity 0.6.4; contract System { bool public alreadyInit; uint32 public constant CODE_OK = 0; uint32 public constant ERROR_FAIL_DECODE = 100; uint8 constant public BIND_CHANNELID = 0x01; uint8 constant public TRANSFER_IN_CHANNELID = 0x02; uint8 constant public TRANSFER_OUT_CHANNELID = 0x03; uint8 constant public STAKING_CHANNELID = 0x08; uint8 constant public GOV_CHANNELID = 0x09; uint8 constant public SLASH_CHANNELID = 0x0b; uint16 constant public bscChainID = 0x0038; address public constant VALIDATOR_CONTRACT_ADDR = 0x0000000000000000000000000000000000001000; address public constant SLASH_CONTRACT_ADDR = 0x0000000000000000000000000000000000001001; address public constant SYSTEM_REWARD_ADDR = 0x0000000000000000000000000000000000001002; address public constant LIGHT_CLIENT_ADDR = 0x0000000000000000000000000000000000001003; address public constant TOKEN_HUB_ADDR = 0x0000000000000000000000000000000000001004; address public constant INCENTIVIZE_ADDR=0x0000000000000000000000000000000000001005; address public constant RELAYERHUB_CONTRACT_ADDR = 0x0000000000000000000000000000000000001006; address public constant GOV_HUB_ADDR = 0x0000000000000000000000000000000000001007; address public constant TOKEN_MANAGER_ADDR = 0x0000000000000000000000000000000000001008; address public constant CROSS_CHAIN_CONTRACT_ADDR = 0x0000000000000000000000000000000000002000; modifier onlyCoinbase() { require(msg.sender == block.coinbase, "the message sender must be the block producer"); _; } modifier onlyNotInit() { require(!alreadyInit, "the contract already init"); _; } modifier onlyInit() { require(alreadyInit, "the contract not init yet"); _; } modifier onlySlash() { require(msg.sender == SLASH_CONTRACT_ADDR, "the message sender must be slash contract"); _; } modifier onlyTokenHub() { require(msg.sender == TOKEN_HUB_ADDR, "the message sender must be token hub contract"); _; } modifier onlyGov() { require(msg.sender == GOV_HUB_ADDR, "the message sender must be governance contract"); _; } modifier onlyValidatorContract() { require(msg.sender == VALIDATOR_CONTRACT_ADDR, "the message sender must be validatorSet contract"); _; } modifier onlyCrossChainContract() { require(msg.sender == CROSS_CHAIN_CONTRACT_ADDR, "the message sender must be cross chain contract"); _; } modifier onlyRelayerIncentivize() { require(msg.sender == INCENTIVIZE_ADDR, "the message sender must be incentivize contract"); _; } modifier onlyRelayer() { require(IRelayerHub(RELAYERHUB_CONTRACT_ADDR).isRelayer(msg.sender), "the msg sender is not a relayer"); _; } modifier onlyTokenManager() { require(msg.sender == TOKEN_MANAGER_ADDR, "the msg sender must be tokenManager"); _; } // Not reliable, do not use when need strong verify function isContract(address addr) internal view returns (bool) { uint size; assembly { size := extcodesize(addr) } return size > 0; } } // File: contracts/lib/BytesToTypes.sol pragma solidity 0.6.4; /** * @title BytesToTypes * Copyright (c) 2016-2020 zpouladzade/Seriality * @dev The BytesToTypes contract converts the memory byte arrays to the standard solidity types * @author [email protected] */ library BytesToTypes { function bytesToAddress(uint _offst, bytes memory _input) internal pure returns (address _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToBool(uint _offst, bytes memory _input) internal pure returns (bool _output) { uint8 x; assembly { x := mload(add(_input, _offst)) } x==0 ? _output = false : _output = true; } function getStringSize(uint _offst, bytes memory _input) internal pure returns(uint size) { assembly{ size := mload(add(_input,_offst)) let chunk_count := add(div(size,32),1) // chunk_count = size/32 + 1 if gt(mod(size,32),0) {// if size%32 > 0 chunk_count := add(chunk_count,1) } size := mul(chunk_count,32)// first 32 bytes reseves for size in strings } } function bytesToString(uint _offst, bytes memory _input, bytes memory _output) internal pure { uint size = 32; assembly { let chunk_count size := mload(add(_input,_offst)) chunk_count := add(div(size,32),1) // chunk_count = size/32 + 1 if gt(mod(size,32),0) { chunk_count := add(chunk_count,1) // chunk_count++ } for { let index:= 0 } lt(index , chunk_count) { index := add(index,1) } { mstore(add(_output,mul(index,32)),mload(add(_input,_offst))) _offst := sub(_offst,32) // _offst -= 32 } } } function bytesToBytes32(uint _offst, bytes memory _input, bytes32 _output) internal pure { assembly { mstore(_output , add(_input, _offst)) mstore(add(_output,32) , add(add(_input, _offst),32)) } } function bytesToInt8(uint _offst, bytes memory _input) internal pure returns (int8 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt16(uint _offst, bytes memory _input) internal pure returns (int16 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt24(uint _offst, bytes memory _input) internal pure returns (int24 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt32(uint _offst, bytes memory _input) internal pure returns (int32 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt40(uint _offst, bytes memory _input) internal pure returns (int40 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt48(uint _offst, bytes memory _input) internal pure returns (int48 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt56(uint _offst, bytes memory _input) internal pure returns (int56 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt64(uint _offst, bytes memory _input) internal pure returns (int64 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt72(uint _offst, bytes memory _input) internal pure returns (int72 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt80(uint _offst, bytes memory _input) internal pure returns (int80 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt88(uint _offst, bytes memory _input) internal pure returns (int88 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt96(uint _offst, bytes memory _input) internal pure returns (int96 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt104(uint _offst, bytes memory _input) internal pure returns (int104 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt112(uint _offst, bytes memory _input) internal pure returns (int112 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt120(uint _offst, bytes memory _input) internal pure returns (int120 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt128(uint _offst, bytes memory _input) internal pure returns (int128 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt136(uint _offst, bytes memory _input) internal pure returns (int136 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt144(uint _offst, bytes memory _input) internal pure returns (int144 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt152(uint _offst, bytes memory _input) internal pure returns (int152 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt160(uint _offst, bytes memory _input) internal pure returns (int160 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt168(uint _offst, bytes memory _input) internal pure returns (int168 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt176(uint _offst, bytes memory _input) internal pure returns (int176 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt184(uint _offst, bytes memory _input) internal pure returns (int184 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt192(uint _offst, bytes memory _input) internal pure returns (int192 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt200(uint _offst, bytes memory _input) internal pure returns (int200 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt208(uint _offst, bytes memory _input) internal pure returns (int208 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt216(uint _offst, bytes memory _input) internal pure returns (int216 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt224(uint _offst, bytes memory _input) internal pure returns (int224 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt232(uint _offst, bytes memory _input) internal pure returns (int232 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt240(uint _offst, bytes memory _input) internal pure returns (int240 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt248(uint _offst, bytes memory _input) internal pure returns (int248 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToInt256(uint _offst, bytes memory _input) internal pure returns (int256 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint8(uint _offst, bytes memory _input) internal pure returns (uint8 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint16(uint _offst, bytes memory _input) internal pure returns (uint16 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint24(uint _offst, bytes memory _input) internal pure returns (uint24 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint32(uint _offst, bytes memory _input) internal pure returns (uint32 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint40(uint _offst, bytes memory _input) internal pure returns (uint40 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint48(uint _offst, bytes memory _input) internal pure returns (uint48 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint56(uint _offst, bytes memory _input) internal pure returns (uint56 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint64(uint _offst, bytes memory _input) internal pure returns (uint64 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint72(uint _offst, bytes memory _input) internal pure returns (uint72 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint80(uint _offst, bytes memory _input) internal pure returns (uint80 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint88(uint _offst, bytes memory _input) internal pure returns (uint88 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint96(uint _offst, bytes memory _input) internal pure returns (uint96 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint104(uint _offst, bytes memory _input) internal pure returns (uint104 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint112(uint _offst, bytes memory _input) internal pure returns (uint112 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint120(uint _offst, bytes memory _input) internal pure returns (uint120 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint128(uint _offst, bytes memory _input) internal pure returns (uint128 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint136(uint _offst, bytes memory _input) internal pure returns (uint136 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint144(uint _offst, bytes memory _input) internal pure returns (uint144 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint152(uint _offst, bytes memory _input) internal pure returns (uint152 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint160(uint _offst, bytes memory _input) internal pure returns (uint160 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint168(uint _offst, bytes memory _input) internal pure returns (uint168 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint176(uint _offst, bytes memory _input) internal pure returns (uint176 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint184(uint _offst, bytes memory _input) internal pure returns (uint184 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint192(uint _offst, bytes memory _input) internal pure returns (uint192 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint200(uint _offst, bytes memory _input) internal pure returns (uint200 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint208(uint _offst, bytes memory _input) internal pure returns (uint208 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint216(uint _offst, bytes memory _input) internal pure returns (uint216 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint224(uint _offst, bytes memory _input) internal pure returns (uint224 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint232(uint _offst, bytes memory _input) internal pure returns (uint232 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint240(uint _offst, bytes memory _input) internal pure returns (uint240 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint248(uint _offst, bytes memory _input) internal pure returns (uint248 _output) { assembly { _output := mload(add(_input, _offst)) } } function bytesToUint256(uint _offst, bytes memory _input) internal pure returns (uint256 _output) { assembly { _output := mload(add(_input, _offst)) } } } // File: contracts/lib/Memory.sol pragma solidity 0.6.4; library Memory { // Size of a word, in bytes. uint internal constant WORD_SIZE = 32; // Size of the header of a 'bytes' array. uint internal constant BYTES_HEADER_SIZE = 32; // Address of the free memory pointer. uint internal constant FREE_MEM_PTR = 0x40; // Compares the 'len' bytes starting at address 'addr' in memory with the 'len' // bytes starting at 'addr2'. // Returns 'true' if the bytes are the same, otherwise 'false'. function equals(uint addr, uint addr2, uint len) internal pure returns (bool equal) { assembly { equal := eq(keccak256(addr, len), keccak256(addr2, len)) } } // Compares the 'len' bytes starting at address 'addr' in memory with the bytes stored in // 'bts'. It is allowed to set 'len' to a lower value then 'bts.length', in which case only // the first 'len' bytes will be compared. // Requires that 'bts.length >= len' function equals(uint addr, uint len, bytes memory bts) internal pure returns (bool equal) { require(bts.length >= len); uint addr2; assembly { addr2 := add(bts, /*BYTES_HEADER_SIZE*/32) } return equals(addr, addr2, len); } function compareStrings(string memory a, string memory b) internal pure returns (bool) { return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)))); } // Copy 'len' bytes from memory address 'src', to address 'dest'. // This function does not check the or destination, it only copies // the bytes. function copy(uint src, uint dest, uint len) internal pure { // Copy word-length chunks while possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } dest += WORD_SIZE; src += WORD_SIZE; } // Copy remaining bytes uint mask = 256 ** (WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } // Returns a memory pointer to the provided bytes array. function ptr(bytes memory bts) internal pure returns (uint addr) { assembly { addr := bts } } // Returns a memory pointer to the data portion of the provided bytes array. function dataPtr(bytes memory bts) internal pure returns (uint addr) { assembly { addr := add(bts, /*BYTES_HEADER_SIZE*/32) } } // This function does the same as 'dataPtr(bytes memory)', but will also return the // length of the provided bytes array. function fromBytes(bytes memory bts) internal pure returns (uint addr, uint len) { len = bts.length; assembly { addr := add(bts, /*BYTES_HEADER_SIZE*/32) } } // Creates a 'bytes memory' variable from the memory address 'addr', with the // length 'len'. The function will allocate new memory for the bytes array, and // the 'len bytes starting at 'addr' will be copied into that new memory. function toBytes(uint addr, uint len) internal pure returns (bytes memory bts) { bts = new bytes(len); uint btsptr; assembly { btsptr := add(bts, /*BYTES_HEADER_SIZE*/32) } copy(addr, btsptr, len); } // Get the word stored at memory address 'addr' as a 'uint'. function toUint(uint addr) internal pure returns (uint n) { assembly { n := mload(addr) } } // Get the word stored at memory address 'addr' as a 'bytes32'. function toBytes32(uint addr) internal pure returns (bytes32 bts) { assembly { bts := mload(addr) } } } // File: contracts/interface/ISlashIndicator.sol pragma solidity 0.6.4; interface ISlashIndicator { function clean() external; } // File: contracts/interface/ITokenHub.sol pragma solidity 0.6.4; interface ITokenHub { function getMiniRelayFee() external view returns(uint256); function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view returns(address); function getBep2SymbolByContractAddr(address contractAddr) external view returns(bytes32); function bindToken(bytes32 bep2Symbol, address contractAddr, uint256 decimals) external; function unbindToken(bytes32 bep2Symbol, address contractAddr) external; function transferOut(address contractAddr, address recipient, uint256 amount, uint64 expireTime) external payable returns (bool); /* solium-disable-next-line */ function batchTransferOutBNB(address[] calldata recipientAddrs, uint256[] calldata amounts, address[] calldata refundAddrs, uint64 expireTime) external payable returns (bool); } // File: contracts/interface/IParamSubscriber.sol pragma solidity 0.6.4; interface IParamSubscriber { function updateParam(string calldata key, bytes calldata value) external; } // File: contracts/interface/IBSCValidatorSet.sol pragma solidity 0.6.4; interface IBSCValidatorSet { function misdemeanor(address validator) external; function felony(address validator)external; } // File: contracts/interface/IApplication.sol pragma solidity 0.6.4; interface IApplication { /** * @dev Handle syn package */ function handleSynPackage(uint8 channelId, bytes calldata msgBytes) external returns(bytes memory responsePayload); /** * @dev Handle ack package */ function handleAckPackage(uint8 channelId, bytes calldata msgBytes) external; /** * @dev Handle fail ack package */ function handleFailAckPackage(uint8 channelId, bytes calldata msgBytes) external; } // File: contracts/lib/SafeMath.sol pragma solidity 0.6.4; /** * Copyright (c) 2016-2019 zOS Global Limited * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: contracts/lib/RLPDecode.sol pragma solidity 0.6.4; library RLPDecode { uint8 constant STRING_SHORT_START = 0x80; uint8 constant STRING_LONG_START = 0xb8; uint8 constant LIST_SHORT_START = 0xc0; uint8 constant LIST_LONG_START = 0xf8; uint8 constant WORD_SIZE = 32; struct RLPItem { uint len; uint memPtr; } struct Iterator { RLPItem item; // Item that's being iterated over. uint nextPtr; // Position of the next item in the list. } function next(Iterator memory self) internal pure returns (RLPItem memory) { require(hasNext(self)); uint ptr = self.nextPtr; uint itemLength = _itemLength(ptr); self.nextPtr = ptr + itemLength; return RLPItem(itemLength, ptr); } function hasNext(Iterator memory self) internal pure returns (bool) { RLPItem memory item = self.item; return self.nextPtr < item.memPtr + item.len; } function toRLPItem(bytes memory self) internal pure returns (RLPItem memory) { uint memPtr; assembly { memPtr := add(self, 0x20) } return RLPItem(self.length, memPtr); } function iterator(RLPItem memory self) internal pure returns (Iterator memory) { require(isList(self)); uint ptr = self.memPtr + _payloadOffset(self.memPtr); return Iterator(self, ptr); } function rlpLen(RLPItem memory item) internal pure returns (uint) { return item.len; } function payloadLen(RLPItem memory item) internal pure returns (uint) { return item.len - _payloadOffset(item.memPtr); } function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { require(isList(item)); uint items = numItems(item); RLPItem[] memory result = new RLPItem[](items); uint memPtr = item.memPtr + _payloadOffset(item.memPtr); uint dataLen; for (uint i = 0; i < items; i++) { dataLen = _itemLength(memPtr); result[i] = RLPItem(dataLen, memPtr); memPtr = memPtr + dataLen; } return result; } function isList(RLPItem memory item) internal pure returns (bool) { if (item.len == 0) return false; uint8 byte0; uint memPtr = item.memPtr; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < LIST_SHORT_START) return false; return true; } function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { bytes memory result = new bytes(item.len); if (result.length == 0) return result; uint ptr; assembly { ptr := add(0x20, result) } copy(item.memPtr, ptr, item.len); return result; } function toBoolean(RLPItem memory item) internal pure returns (bool) { require(item.len == 1); uint result; uint memPtr = item.memPtr; assembly { result := byte(0, mload(memPtr)) } return result == 0 ? false : true; } function toAddress(RLPItem memory item) internal pure returns (address) { // 1 byte for the length prefix require(item.len == 21); return address(toUint(item)); } function toUint(RLPItem memory item) internal pure returns (uint) { require(item.len > 0 && item.len <= 33); uint offset = _payloadOffset(item.memPtr); require(item.len >= offset, "length is less than offset"); uint len = item.len - offset; uint result; uint memPtr = item.memPtr + offset; assembly { result := mload(memPtr) // shfit to the correct location if neccesary if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } } return result; } // enforces 32 byte length function toUintStrict(RLPItem memory item) internal pure returns (uint) { // one byte prefix require(item.len == 33); uint result; uint memPtr = item.memPtr + 1; assembly { result := mload(memPtr) } return result; } function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); uint offset = _payloadOffset(item.memPtr); uint len = item.len - offset; // data length bytes memory result = new bytes(len); uint destPtr; assembly { destPtr := add(0x20, result) } copy(item.memPtr + offset, destPtr, len); return result; } function numItems(RLPItem memory item) private pure returns (uint) { if (item.len == 0) return 0; uint count = 0; uint currPtr = item.memPtr + _payloadOffset(item.memPtr); uint endPtr = item.memPtr + item.len; while (currPtr < endPtr) { currPtr = currPtr + _itemLength(currPtr); // skip over an item count++; } return count; } function _itemLength(uint memPtr) private pure returns (uint) { uint itemLen; uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) itemLen = 1; else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1; else if (byte0 < LIST_SHORT_START) { uint dataLen; assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is memPtr := add(memPtr, 1) // skip over the first byte /* 32 byte word size */ dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len itemLen := add(dataLen, add(byteLen, 1)) } require(itemLen >= dataLen, "addition overflow"); } else if (byte0 < LIST_LONG_START) { itemLen = byte0 - LIST_SHORT_START + 1; } else { uint dataLen; assembly { let byteLen := sub(byte0, 0xf7) memPtr := add(memPtr, 1) dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length itemLen := add(dataLen, add(byteLen, 1)) } require(itemLen >= dataLen, "addition overflow"); } return itemLen; } // @return number of bytes until the data function _payloadOffset(uint memPtr) private pure returns (uint) { uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) return 0; else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1; else if (byte0 < LIST_SHORT_START) // being explicit return byte0 - (STRING_LONG_START - 1) + 1; else return byte0 - (LIST_LONG_START - 1) + 1; } /* * @param src Pointer to source * @param dest Pointer to destination * @param len Amount of memory to copy from the source */ function copy(uint src, uint dest, uint len) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } // left over bytes. Mask is used to remove unwanted bytes from the word uint mask = 256 ** (WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } } // File: contracts/lib/RLPEncode.sol pragma solidity 0.6.4; library RLPEncode { uint8 constant STRING_OFFSET = 0x80; uint8 constant LIST_OFFSET = 0xc0; /** * @notice Encode string item * @param self The string (ie. byte array) item to encode * @return The RLP encoded string in bytes */ function encodeBytes(bytes memory self) internal pure returns (bytes memory) { if (self.length == 1 && self[0] <= 0x7f) { return self; } return mergeBytes(encodeLength(self.length, STRING_OFFSET), self); } /** * @notice Encode address * @param self The address to encode * @return The RLP encoded address in bytes */ function encodeAddress(address self) internal pure returns (bytes memory) { bytes memory b; assembly { let m := mload(0x40) mstore(add(m, 20), xor(0x140000000000000000000000000000000000000000, self)) mstore(0x40, add(m, 52)) b := m } return encodeBytes(b); } /** * @notice Encode uint * @param self The uint to encode * @return The RLP encoded uint in bytes */ function encodeUint(uint self) internal pure returns (bytes memory) { return encodeBytes(toBinary(self)); } /** * @notice Encode int * @param self The int to encode * @return The RLP encoded int in bytes */ function encodeInt(int self) internal pure returns (bytes memory) { return encodeUint(uint(self)); } /** * @notice Encode bool * @param self The bool to encode * @return The RLP encoded bool in bytes */ function encodeBool(bool self) internal pure returns (bytes memory) { bytes memory rs = new bytes(1); if (self) { rs[0] = bytes1(uint8(1)); } return rs; } /** * @notice Encode list of items * @param self The list of items to encode, each item in list must be already encoded * @return The RLP encoded list of items in bytes */ function encodeList(bytes[] memory self) internal pure returns (bytes memory) { if (self.length == 0) { return new bytes(0); } bytes memory payload = self[0]; for (uint i = 1; i < self.length; i++) { payload = mergeBytes(payload, self[i]); } return mergeBytes(encodeLength(payload.length, LIST_OFFSET), payload); } /** * @notice Concat two bytes arrays * @param _preBytes The first bytes array * @param _postBytes The second bytes array * @return The merged bytes array */ function mergeBytes( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } /** * @notice Encode the first byte, followed by the `length` in binary form if `length` is more than 55. * @param length The length of the string or the payload * @param offset `STRING_OFFSET` if item is string, `LIST_OFFSET` if item is list * @return RLP encoded bytes */ function encodeLength(uint length, uint offset) internal pure returns (bytes memory) { require(length < 256**8, "input too long"); bytes memory rs = new bytes(1); if (length <= 55) { rs[0] = byte(uint8(length + offset)); return rs; } bytes memory bl = toBinary(length); rs[0] = byte(uint8(bl.length + offset + 55)); return mergeBytes(rs, bl); } /** * @notice Encode integer in big endian binary form with no leading zeroes * @param x The integer to encode * @return RLP encoded bytes */ function toBinary(uint x) internal pure returns (bytes memory) { bytes memory b = new bytes(32); assembly { mstore(add(b, 32), x) } uint i; if (x & 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 == 0) { i = 24; } else if (x & 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000 == 0) { i = 16; } else { i = 0; } for (; i < 32; i++) { if (b[i] != 0) { break; } } uint length = 32 - i; bytes memory rs = new bytes(length); assembly { mstore(add(rs, length), x) mstore(rs, length) } return rs; } } // File: contracts/lib/CmnPkg.sol pragma solidity 0.6.4; library CmnPkg { using RLPEncode for *; using RLPDecode for *; struct CommonAckPackage { uint32 code; } function encodeCommonAckPackage(uint32 code) internal pure returns (bytes memory) { bytes[] memory elements = new bytes[](1); elements[0] = uint256(code).encodeUint(); return elements.encodeList(); } function decodeCommonAckPackage(bytes memory msgBytes) internal pure returns (CommonAckPackage memory, bool) { CommonAckPackage memory ackPkg; RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; uint256 idx=0; while (iter.hasNext()) { if (idx == 0) { ackPkg.code = uint32(iter.next().toUint()); success = true; } else { break; } idx++; } return (ackPkg, success); } } // File: contracts/BSCValidatorSet.sol pragma solidity 0.6.4; contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplication { using SafeMath for uint256; using RLPDecode for *; // will not transfer value less than 0.1 BNB for validators uint256 constant public DUSTY_INCOMING = 1e17; uint8 public constant JAIL_MESSAGE_TYPE = 1; uint8 public constant VALIDATORS_UPDATE_MESSAGE_TYPE = 0; // the precision of cross chain value transfer. uint256 public constant PRECISION = 1e10; uint256 public constant EXPIRE_TIME_SECOND_GAP = 1000; uint256 public constant MAX_NUM_OF_VALIDATORS = 41; bytes public constant INIT_VALIDATORSET_BYTES = hex"f905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a2000"; uint32 public constant ERROR_UNKNOWN_PACKAGE_TYPE = 101; uint32 public constant ERROR_FAIL_CHECK_VALIDATORS = 102; uint32 public constant ERROR_LEN_OF_VAL_MISMATCH = 103; uint32 public constant ERROR_RELAYFEE_TOO_LARGE = 104; /*********************** state of the contract **************************/ Validator[] public currentValidatorSet; uint256 public expireTimeSecondGap; uint256 public totalInComing; // key is the `consensusAddress` of `Validator`, // value is the index of the element in `currentValidatorSet`. mapping(address =>uint256) public currentValidatorSetMap; uint256 public numOfJailed; struct Validator{ address consensusAddress; address payable feeAddress; address BBCFeeAddress; uint64 votingPower; // only in state bool jailed; uint256 incoming; } /*********************** cross chain package **************************/ struct IbcValidatorSetPackage { uint8 packageType; Validator[] validatorSet; } /*********************** modifiers **************************/ modifier noEmptyDeposit() { require(msg.value > 0, "deposit value is zero"); _; } /*********************** events **************************/ event validatorSetUpdated(); event validatorJailed(address indexed validator); event validatorEmptyJailed(address indexed validator); event batchTransfer(uint256 amount); event batchTransferFailed(uint256 indexed amount, string reason); event batchTransferLowerFailed(uint256 indexed amount, bytes reason); event systemTransfer(uint256 amount); event directTransfer(address payable indexed validator, uint256 amount); event directTransferFail(address payable indexed validator, uint256 amount); event deprecatedDeposit(address indexed validator, uint256 amount); event validatorDeposit(address indexed validator, uint256 amount); event validatorMisdemeanor(address indexed validator, uint256 amount); event validatorFelony(address indexed validator, uint256 amount); event failReasonWithStr(string message); event unexpectedPackage(uint8 channelId, bytes msgBytes); event paramChange(string key, bytes value); /*********************** init **************************/ function init() external onlyNotInit{ (IbcValidatorSetPackage memory validatorSetPkg, bool valid)= decodeValidatorSetSynPackage(INIT_VALIDATORSET_BYTES); require(valid, "failed to parse init validatorSet"); for (uint i = 0;i<validatorSetPkg.validatorSet.length;i++) { currentValidatorSet.push(validatorSetPkg.validatorSet[i]); currentValidatorSetMap[validatorSetPkg.validatorSet[i].consensusAddress] = i+1; } expireTimeSecondGap = EXPIRE_TIME_SECOND_GAP; alreadyInit = true; } /*********************** Cross Chain App Implement **************************/ function handleSynPackage(uint8, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory responsePayload) { (IbcValidatorSetPackage memory validatorSetPackage, bool ok) = decodeValidatorSetSynPackage(msgBytes); if (!ok) { return CmnPkg.encodeCommonAckPackage(ERROR_FAIL_DECODE); } uint32 resCode; if (validatorSetPackage.packageType == VALIDATORS_UPDATE_MESSAGE_TYPE) { resCode = updateValidatorSet(validatorSetPackage.validatorSet); } else if (validatorSetPackage.packageType == JAIL_MESSAGE_TYPE) { if (validatorSetPackage.validatorSet.length != 1) { emit failReasonWithStr("length of jail validators must be one"); resCode = ERROR_LEN_OF_VAL_MISMATCH; } else { resCode = jailValidator(validatorSetPackage.validatorSet[0]); } } else { resCode = ERROR_UNKNOWN_PACKAGE_TYPE; } if (resCode == CODE_OK) { return new bytes(0); } else { return CmnPkg.encodeCommonAckPackage(resCode); } } function handleAckPackage(uint8 channelId, bytes calldata msgBytes) external onlyCrossChainContract override { // should not happen emit unexpectedPackage(channelId, msgBytes); } function handleFailAckPackage(uint8 channelId, bytes calldata msgBytes) external onlyCrossChainContract override { // should not happen emit unexpectedPackage(channelId, msgBytes); } /*********************** External Functions **************************/ function deposit(address valAddr) external payable onlyCoinbase onlyInit noEmptyDeposit{ uint256 value = msg.value; uint256 index = currentValidatorSetMap[valAddr]; if (index>0) { Validator storage validator = currentValidatorSet[index-1]; if (validator.jailed) { emit deprecatedDeposit(valAddr,value); } else { totalInComing = totalInComing.add(value); validator.incoming = validator.incoming.add(value); emit validatorDeposit(valAddr,value); } } else { // get incoming from deprecated validator; emit deprecatedDeposit(valAddr,value); } } function jailValidator(Validator memory v) internal returns (uint32) { uint256 index = currentValidatorSetMap[v.consensusAddress]; if (index==0 || currentValidatorSet[index-1].jailed) { emit validatorEmptyJailed(v.consensusAddress); return CODE_OK; } uint n = currentValidatorSet.length; bool shouldKeep = (numOfJailed >= n-1); // will not jail if it is the last valid validator if (shouldKeep) { emit validatorEmptyJailed(v.consensusAddress); return CODE_OK; } numOfJailed ++; currentValidatorSet[index-1].jailed = true; emit validatorJailed(v.consensusAddress); return CODE_OK; } function updateValidatorSet(Validator[] memory validatorSet) internal returns (uint32) { // do verify. (bool valid, string memory errMsg) = checkValidatorSet(validatorSet); if (!valid) { emit failReasonWithStr(errMsg); return ERROR_FAIL_CHECK_VALIDATORS; } //step 1: do calculate distribution, do not make it as an internal function for saving gas. uint crossSize; uint directSize; for (uint i = 0;i<currentValidatorSet.length;i++) { if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { crossSize ++; } else if (currentValidatorSet[i].incoming > 0) { directSize ++; } } //cross transfer address[] memory crossAddrs = new address[](crossSize); uint256[] memory crossAmounts = new uint256[](crossSize); uint256[] memory crossIndexes = new uint256[](crossSize); address[] memory crossRefundAddrs = new address[](crossSize); uint256 crossTotal; // direct transfer address payable[] memory directAddrs = new address payable[](directSize); uint256[] memory directAmounts = new uint256[](directSize); crossSize = 0; directSize = 0; Validator[] memory validatorSetTemp = validatorSet; // fix error: stack too deep, try removing local variables uint256 relayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee(); if (relayFee > DUSTY_INCOMING) { emit failReasonWithStr("fee is larger than DUSTY_INCOMING"); return ERROR_RELAYFEE_TOO_LARGE; } for (uint i = 0;i<currentValidatorSet.length;i++) { if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION; crossAmounts[crossSize] = value.sub(relayFee); crossRefundAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; crossIndexes[crossSize] = i; crossTotal = crossTotal.add(value); crossSize ++; } else if (currentValidatorSet[i].incoming > 0) { directAddrs[directSize] = currentValidatorSet[i].feeAddress; directAmounts[directSize] = currentValidatorSet[i].incoming; directSize ++; } } //step 2: do cross chain transfer bool failCross = false; if (crossTotal > 0) { try ITokenHub(TOKEN_HUB_ADDR).batchTransferOutBNB{value:crossTotal}(crossAddrs, crossAmounts, crossRefundAddrs, uint64(block.timestamp + expireTimeSecondGap)) returns (bool success) { if (success) { emit batchTransfer(crossTotal); } else { emit batchTransferFailed(crossTotal, "batch transfer return false"); } }catch Error(string memory reason) { failCross = true; emit batchTransferFailed(crossTotal, reason); }catch (bytes memory lowLevelData) { failCross = true; emit batchTransferLowerFailed(crossTotal, lowLevelData); } } if (failCross) { for (uint i = 0; i< crossIndexes.length;i++) { uint idx = crossIndexes[i]; bool success = currentValidatorSet[idx].feeAddress.send(currentValidatorSet[idx].incoming); if (success) { emit directTransfer(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); } else { emit directTransferFail(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); } } } // step 3: direct transfer if (directAddrs.length>0) { for (uint i = 0;i<directAddrs.length;i++) { bool success = directAddrs[i].send(directAmounts[i]); if (success) { emit directTransfer(directAddrs[i], directAmounts[i]); } else { emit directTransferFail(directAddrs[i], directAmounts[i]); } } } // step 4: do dusk transfer if (address(this).balance>0) { emit systemTransfer(address(this).balance); address(uint160(SYSTEM_REWARD_ADDR)).transfer(address(this).balance); } // step 5: do update validator set state totalInComing = 0; numOfJailed = 0; if (validatorSetTemp.length>0) { doUpdateState(validatorSetTemp); } // step 6: clean slash contract ISlashIndicator(SLASH_CONTRACT_ADDR).clean(); emit validatorSetUpdated(); return CODE_OK; } function getValidators()external view returns(address[] memory) { uint n = currentValidatorSet.length; uint valid = 0; for (uint i = 0;i<n;i++) { if (!currentValidatorSet[i].jailed) { valid ++; } } address[] memory consensusAddrs = new address[](valid); valid = 0; for (uint i = 0;i<n;i++) { if (!currentValidatorSet[i].jailed) { consensusAddrs[valid] = currentValidatorSet[i].consensusAddress; valid ++; } } return consensusAddrs; } function getIncoming(address validator)external view returns(uint256) { uint256 index = currentValidatorSetMap[validator]; if (index<=0) { return 0; } return currentValidatorSet[index-1].incoming; } /*********************** For slash **************************/ function misdemeanor(address validator)external onlySlash override{ uint256 index = currentValidatorSetMap[validator]; if (index <= 0) { return; } // the actually index index = index - 1; uint256 income = currentValidatorSet[index].incoming; currentValidatorSet[index].incoming = 0; uint256 rest = currentValidatorSet.length - 1; emit validatorMisdemeanor(validator,income); if (rest==0) { // should not happen, but still protect return; } uint256 averageDistribute = income/rest; if (averageDistribute!=0) { for (uint i=0;i<index;i++) { currentValidatorSet[i].incoming = currentValidatorSet[i].incoming + averageDistribute; } uint n = currentValidatorSet.length; for (uint i=index+1;i<n;i++) { currentValidatorSet[i].incoming = currentValidatorSet[i].incoming + averageDistribute; } } // averageDistribute*rest may less than income, but it is ok, the dust income will go to system reward eventually. } function felony(address validator)external onlySlash override{ uint256 index = currentValidatorSetMap[validator]; if (index <= 0) { return; } // the actually index index = index - 1; uint256 income = currentValidatorSet[index].incoming; uint256 rest = currentValidatorSet.length - 1; if (rest==0) { // will not remove the validator if it is the only one validator. currentValidatorSet[index].incoming = 0; return; } emit validatorFelony(validator,income); delete currentValidatorSetMap[validator]; // It is ok that the validatorSet is not in order. if (index != currentValidatorSet.length-1) { currentValidatorSet[index] = currentValidatorSet[currentValidatorSet.length-1]; currentValidatorSetMap[currentValidatorSet[index].consensusAddress] = index + 1; } currentValidatorSet.pop(); uint256 averageDistribute = income/rest; if (averageDistribute!=0) { uint n = currentValidatorSet.length; for (uint i=0;i<n;i++) { currentValidatorSet[i].incoming = currentValidatorSet[i].incoming + averageDistribute; } } // averageDistribute*rest may less than income, but it is ok, the dust income will go to system reward eventually. } /*********************** Param update ********************************/ function updateParam(string calldata key, bytes calldata value) override external onlyInit onlyGov{ if (Memory.compareStrings(key, "expireTimeSecondGap")) { require(value.length == 32, "length of expireTimeSecondGap mismatch"); uint256 newExpireTimeSecondGap = BytesToTypes.bytesToUint256(32, value); require(newExpireTimeSecondGap >=100 && newExpireTimeSecondGap <= 1e5, "the expireTimeSecondGap is out of range"); expireTimeSecondGap = newExpireTimeSecondGap; } else { require(false, "unknown param"); } emit paramChange(key, value); } /*********************** Internal Functions **************************/ function checkValidatorSet(Validator[] memory validatorSet) private pure returns(bool, string memory) { if (validatorSet.length > MAX_NUM_OF_VALIDATORS){ return (false, "the number of validators exceed the limit"); } for (uint i = 0;i<validatorSet.length;i++) { for (uint j = 0;j<i;j++) { if (validatorSet[i].consensusAddress == validatorSet[j].consensusAddress) { return (false, "duplicate consensus address of validatorSet"); } } } return (true,""); } function doUpdateState(Validator[] memory validatorSet) private{ uint n = currentValidatorSet.length; uint m = validatorSet.length; for (uint i = 0;i<n;i++) { bool stale = true; Validator memory oldValidator = currentValidatorSet[i]; for (uint j = 0;j<m;j++) { if (oldValidator.consensusAddress == validatorSet[j].consensusAddress) { stale = false; break; } } if (stale) { delete currentValidatorSetMap[oldValidator.consensusAddress]; } } if (n>m) { for (uint i = m;i<n;i++) { currentValidatorSet.pop(); } } uint k = n < m ? n:m; for (uint i = 0;i<k;i++) { if (!isSameValidator(validatorSet[i], currentValidatorSet[i])) { currentValidatorSetMap[validatorSet[i].consensusAddress] = i+1; currentValidatorSet[i] = validatorSet[i]; } else { currentValidatorSet[i].incoming = 0; } } if (m>n) { for (uint i = n;i<m;i++) { currentValidatorSet.push(validatorSet[i]); currentValidatorSetMap[validatorSet[i].consensusAddress] = i+1; } } } function isSameValidator(Validator memory v1, Validator memory v2) private pure returns(bool) { return v1.consensusAddress == v2.consensusAddress && v1.feeAddress == v2.feeAddress && v1.BBCFeeAddress == v2.BBCFeeAddress && v1.votingPower == v2.votingPower; } //rlp encode & decode function function decodeValidatorSetSynPackage(bytes memory msgBytes) internal pure returns (IbcValidatorSetPackage memory, bool) { IbcValidatorSetPackage memory validatorSetPkg; RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; uint256 idx=0; while (iter.hasNext()) { if (idx == 0) { validatorSetPkg.packageType = uint8(iter.next().toUint()); } else if (idx == 1) { RLPDecode.RLPItem[] memory items = iter.next().toList(); validatorSetPkg.validatorSet =new Validator[](items.length); for (uint j = 0;j<items.length;j++) { (Validator memory val, bool ok) = decodeValidator(items[j]); if (!ok) { return (validatorSetPkg, false); } validatorSetPkg.validatorSet[j] = val; } success = true; } else { break; } idx++; } return (validatorSetPkg, success); } function decodeValidator(RLPDecode.RLPItem memory itemValidator) internal pure returns(Validator memory, bool) { Validator memory validator; RLPDecode.Iterator memory iter = itemValidator.iterator(); bool success = false; uint256 idx=0; while (iter.hasNext()) { if (idx == 0) { validator.consensusAddress = iter.next().toAddress(); } else if (idx == 1) { validator.feeAddress = address(uint160(iter.next().toAddress())); } else if (idx == 2) { validator.BBCFeeAddress = iter.next().toAddress(); } else if (idx == 3) { validator.votingPower = uint64(iter.next().toUint()); success = true; } else { break; } idx++; } return (validator, success); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"type":"event","name":"batchTransfer","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"batchTransferFailed","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":true},{"type":"string","name":"reason","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"batchTransferLowerFailed","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":true},{"type":"bytes","name":"reason","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"deprecatedDeposit","inputs":[{"type":"address","name":"validator","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"directTransfer","inputs":[{"type":"address","name":"validator","internalType":"address payable","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"directTransferFail","inputs":[{"type":"address","name":"validator","internalType":"address payable","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"failReasonWithStr","inputs":[{"type":"string","name":"message","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"paramChange","inputs":[{"type":"string","name":"key","internalType":"string","indexed":false},{"type":"bytes","name":"value","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"systemTransfer","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"unexpectedPackage","inputs":[{"type":"uint8","name":"channelId","internalType":"uint8","indexed":false},{"type":"bytes","name":"msgBytes","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"validatorDeposit","inputs":[{"type":"address","name":"validator","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"validatorEmptyJailed","inputs":[{"type":"address","name":"validator","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"validatorFelony","inputs":[{"type":"address","name":"validator","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"validatorJailed","inputs":[{"type":"address","name":"validator","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"validatorMisdemeanor","inputs":[{"type":"address","name":"validator","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"validatorSetUpdated","inputs":[],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"BIND_CHANNELID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"CODE_OK","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"CROSS_CHAIN_CONTRACT_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"DUSTY_INCOMING","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"ERROR_FAIL_CHECK_VALIDATORS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"ERROR_FAIL_DECODE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"ERROR_LEN_OF_VAL_MISMATCH","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"ERROR_RELAYFEE_TOO_LARGE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"ERROR_UNKNOWN_PACKAGE_TYPE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"EXPIRE_TIME_SECOND_GAP","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"GOV_CHANNELID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"GOV_HUB_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"INCENTIVIZE_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"INIT_VALIDATORSET_BYTES","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"JAIL_MESSAGE_TYPE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"LIGHT_CLIENT_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_NUM_OF_VALIDATORS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"PRECISION","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"RELAYERHUB_CONTRACT_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"SLASH_CHANNELID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"SLASH_CONTRACT_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"STAKING_CHANNELID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"SYSTEM_REWARD_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"TOKEN_HUB_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"TOKEN_MANAGER_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"TRANSFER_IN_CHANNELID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"TRANSFER_OUT_CHANNELID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"VALIDATORS_UPDATE_MESSAGE_TYPE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"VALIDATOR_CONTRACT_ADDR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"alreadyInit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"bscChainID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"consensusAddress","internalType":"address"},{"type":"address","name":"feeAddress","internalType":"address payable"},{"type":"address","name":"BBCFeeAddress","internalType":"address"},{"type":"uint64","name":"votingPower","internalType":"uint64"},{"type":"bool","name":"jailed","internalType":"bool"},{"type":"uint256","name":"incoming","internalType":"uint256"}],"name":"currentValidatorSet","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentValidatorSetMap","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"deposit","inputs":[{"type":"address","name":"valAddr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"expireTimeSecondGap","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"felony","inputs":[{"type":"address","name":"validator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getIncoming","inputs":[{"type":"address","name":"validator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getValidators","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"handleAckPackage","inputs":[{"type":"uint8","name":"channelId","internalType":"uint8"},{"type":"bytes","name":"msgBytes","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"handleFailAckPackage","inputs":[{"type":"uint8","name":"channelId","internalType":"uint8"},{"type":"bytes","name":"msgBytes","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bytes","name":"responsePayload","internalType":"bytes"}],"name":"handleSynPackage","inputs":[{"type":"uint8","name":"","internalType":"uint8"},{"type":"bytes","name":"msgBytes","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"init","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"misdemeanor","inputs":[{"type":"address","name":"validator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"numOfJailed","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInComing","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateParam","inputs":[{"type":"string","name":"key","internalType":"string"},{"type":"bytes","name":"value","internalType":"bytes"}]}]
Contract Creation Code
0x60806040526004361061027d5760003560e01c80639dc092621161014f578063c8509d81116100c1578063eb57e2021161007a578063eb57e20214610940578063eda5868c14610973578063f340fa0114610988578063f9a2bbc7146109ae578063fc3e5908146109c3578063fd6a6879146109d85761027d565b8063c8509d8114610609578063d86222d5146108d7578063daacdb66146108ec578063dc927faf14610901578063e086c7b114610916578063e1c7392a1461092b5761027d565b8063ab51bb9611610113578063ab51bb961461074a578063ac4317511461075f578063ad3c9da61461082a578063b7ab4db51461085d578063bf9f49951461041b578063c81b1662146108c25761027d565b80639dc09262146106cd578063a1a11bf5146106e2578063a5422d5c146106f7578063a78abc161461070c578063aaf5eb68146107355761027d565b80635667515a116101f35780637942fd05116101ac5780637942fd05146105df57806381650b62146105f4578063831d65d114610609578063853230aa1461068e57806386249882146106a357806396713da9146106b85761027d565b80635667515a146105005780635d77156c146105155780636969a25c1461052a5780636e47b482146105a057806370fd5bad146105b557806375d47a0a146105ca5761027d565b80633dffc387116102455780633dffc3871461041b57806343756e5c14610446578063493279b1146104775780634bf6c882146104a357806351e80672146104b8578063565c56b3146104cd5761027d565b80630bee7a67146102825780631182b875146102b05780631ff18069146103aa578063219f22d5146103d157806335409f7f146103e6575b600080fd5b34801561028e57600080fd5b506102976109ed565b6040805163ffffffff9092168252519081900360200190f35b3480156102bc57600080fd5b50610335600480360360408110156102d357600080fd5b60ff8235169190810190604081016020820135600160201b8111156102f757600080fd5b82018360208201111561030957600080fd5b803590602001918460018302840111600160201b8311171561032a57600080fd5b5090925090506109f2565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561036f578181015183820152602001610357565b50505050905090810190601f16801561039c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103b657600080fd5b506103bf610bdf565b60408051918252519081900360200190f35b3480156103dd57600080fd5b50610297610be5565b3480156103f257600080fd5b506104196004803603602081101561040957600080fd5b50356001600160a01b0316610bea565b005b34801561042757600080fd5b50610430610efe565b6040805160ff9092168252519081900360200190f35b34801561045257600080fd5b5061045b610f03565b604080516001600160a01b039092168252519081900360200190f35b34801561048357600080fd5b5061048c610f09565b6040805161ffff9092168252519081900360200190f35b3480156104af57600080fd5b50610430610f0e565b3480156104c457600080fd5b5061045b610f13565b3480156104d957600080fd5b506103bf600480360360208110156104f057600080fd5b50356001600160a01b0316610f19565b34801561050c57600080fd5b50610430610f6b565b34801561052157600080fd5b50610297610f70565b34801561053657600080fd5b506105546004803603602081101561054d57600080fd5b5035610f75565b604080516001600160a01b039788168152958716602087015293909516848401526001600160401b0390911660608401521515608083015260a082019290925290519081900360c00190f35b3480156105ac57600080fd5b5061045b610fd9565b3480156105c157600080fd5b50610430610fdf565b3480156105d657600080fd5b5061045b610fe4565b3480156105eb57600080fd5b50610430610fea565b34801561060057600080fd5b50610297610fef565b34801561061557600080fd5b506104196004803603604081101561062c57600080fd5b60ff8235169190810190604081016020820135600160201b81111561065057600080fd5b82018360208201111561066257600080fd5b803590602001918460018302840111600160201b8311171561068357600080fd5b509092509050610ff4565b34801561069a57600080fd5b506103bf6110a7565b3480156106af57600080fd5b506103bf6110ad565b3480156106c457600080fd5b506104306110b3565b3480156106d957600080fd5b5061045b6110b8565b3480156106ee57600080fd5b5061045b6110be565b34801561070357600080fd5b506103356110c4565b34801561071857600080fd5b506107216110e3565b604080519115158252519081900360200190f35b34801561074157600080fd5b506103bf6110ec565b34801561075657600080fd5b50610297610f6b565b34801561076b57600080fd5b506104196004803603604081101561078257600080fd5b810190602081018135600160201b81111561079c57600080fd5b8201836020820111156107ae57600080fd5b803590602001918460018302840111600160201b831117156107cf57600080fd5b919390929091602081019035600160201b8111156107ec57600080fd5b8201836020820111156107fe57600080fd5b803590602001918460018302840111600160201b8311171561081f57600080fd5b5090925090506110f5565b34801561083657600080fd5b506103bf6004803603602081101561084d57600080fd5b50356001600160a01b031661139c565b34801561086957600080fd5b506108726113ae565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156108ae578181015183820152602001610896565b505050509050019250505060405180910390f35b3480156108ce57600080fd5b5061045b6114d4565b3480156108e357600080fd5b506103bf6114da565b3480156108f857600080fd5b506103bf6114e6565b34801561090d57600080fd5b5061045b6114ec565b34801561092257600080fd5b506103bf6114f2565b34801561093757600080fd5b506104196114f7565b34801561094c57600080fd5b506104196004803603602081101561096357600080fd5b50356001600160a01b03166116fa565b34801561097f57600080fd5b506102976118c9565b6104196004803603602081101561099e57600080fd5b50356001600160a01b03166118ce565b3480156109ba57600080fd5b5061045b611b04565b3480156109cf57600080fd5b50610430611b0a565b3480156109e457600080fd5b5061045b611b0f565b606481565b60005460609060ff16610a48576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b3361200014610a885760405162461bcd60e51b815260040180806020018281038252602f815260200180614516602f913960400191505060405180910390fd5b610a90613d69565b6000610ad185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b1592505050565b9150915080610aed57610ae46064611c6e565b92505050610bd8565b815160009060ff16610b0d57610b068360200151611ccf565b9050610ba4565b825160ff1660011415610ba057826020015151600114610b7a577f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2604051808060200182810382526025815260200180613e6c6025913960400191505060405180910390a1506067610b9b565b610b068360200151600081518110610b8e57fe5b6020026020010151612ad5565b610ba4565b5060655b63ffffffff8116610bc95750506040805160008152602081019091529150610bd89050565b610bd281611c6e565b93505050505b9392505050565b60035481565b606881565b3361100114610c2a5760405162461bcd60e51b81526004018080602001828103825260298152602001806145726029913960400191505060405180910390fd5b6001600160a01b03811660009081526004602052604090205480610c4e5750610efb565b600181039050600060018281548110610c6357fe5b60009182526020909120600360049092020101546001549091506000190180610cb257600060018481548110610c9557fe5b906000526020600020906004020160030181905550505050610efb565b6040805183815290516001600160a01b038616917f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70919081900360200190a26001600160a01b038416600090815260046020526040812055600154600019018314610e3457600180546000198101908110610d2957fe5b906000526020600020906004020160018481548110610d4457fe5b6000918252602082208354600492830290910180546001600160a01b03199081166001600160a01b0393841617825560018087015481840180548416918616919091179055600280880180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b199094169390931790556003948501549401939093558254868401939192919087908110610e0957fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020555b6001805480610e3f57fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b03191690556003018190559155818381610e9257fe5b0490508015610ef65760015460005b81811015610ef3578260018281548110610eb757fe5b9060005260206000209060040201600301540160018281548110610ed757fe5b6000918252602090912060036004909202010155600101610ea1565b50505b505050505b50565b600181565b61100181565b603881565b600881565b61200081565b6001600160a01b03811660009081526004602052604081205480610f41576000915050610f66565b600180820381548110610f5057fe5b9060005260206000209060040201600301549150505b919050565b600081565b606781565b60018181548110610f8257fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b61100881565b600b81565b606681565b33612000146110345760405162461bcd60e51b815260040180806020018281038252602f815260200180614516602f913960400191505060405180910390fd5b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a1505050565b6103e881565b60025481565b600981565b61100781565b61100681565b6040518061062001604052806105ef8152602001613f276105ef913981565b60005460ff1681565b6402540be40081565b60005460ff16611148576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b33611007146111885760405162461bcd60e51b815260040180806020018281038252602e815260200180613e91602e913960400191505060405180910390fd5b6111f284848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b60208201529150612c4c9050565b156112cd57602081146112365760405162461bcd60e51b8152600401808060200182810382526026815260200180613ee06026913960400191505060405180910390fd5b604080516020601f840181900481028201810190925282815260009161127491858580838501838280828437600092019190915250612d3492505050565b90506064811015801561128a5750620186a08111155b6112c55760405162461bcd60e51b8152600401808060200182810382526027815260200180613e456027913960400191505060405180910390fd5b60025561130a565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b60046020526000908152604090205481565b6001546060906000805b828110156113ff57600181815481106113cd57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166113f7576001909101905b6001016113b8565b5060608160405190808252806020026020018201604052801561142c578160200160208202803683370190505b50600092509050815b838110156114cc576001818154811061144a57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166114c4576001818154811061147a57fe5b600091825260209091206004909102015482516001600160a01b03909116908390859081106114a557fe5b6001600160a01b03909216602092830291909101909101526001909201915b600101611435565b509250505090565b61100281565b67016345785d8a000081565b60055481565b61100381565b602981565b60005460ff161561154f576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b611557613d69565b600061157d6040518061062001604052806105ef8152602001613f276105ef9139611b15565b91509150806115bd5760405162461bcd60e51b8152600401808060200182810382526021815260200180613f066021913960400191505060405180910390fd5b60005b8260200151518110156116e2576001836020015182815181106115df57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a0909301516003909301929092559186015180519185019391859081106116b557fe5b602090810291909101810151516001600160a01b03168252810191909152604001600020556001016115c0565b50506103e8600255506000805460ff19166001179055565b336110011461173a5760405162461bcd60e51b81526004018080602001828103825260298152602001806145726029913960400191505060405180910390fd5b6001600160a01b0381166000908152600460205260409020548061175e5750610efb565b60018103905060006001828154811061177357fe5b906000526020600020906004020160030154905060006001838154811061179657fe5b906000526020600020906004020160030181905550600060018080549050039050836001600160a01b03167f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d836040518082815260200191505060405180910390a28061180557505050610efb565b600081838161181057fe5b0490508015610ef65760005b8481101561186e57816001828154811061183257fe5b906000526020600020906004020160030154016001828154811061185257fe5b600091825260209091206003600490920201015560010161181c565b50600180549085015b81811015610ef357826001828154811061188d57fe5b90600052602060002090600402016003015401600182815481106118ad57fe5b6000918252602090912060036004909202010155600101611877565b606581565b33411461190c5760405162461bcd60e51b815260040180806020018281038252602d815260200180614545602d913960400191505060405180910390fd5b60005460ff1661195f576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b600034116119ac576040805162461bcd60e51b81526020600482015260156024820152746465706f7369742076616c7565206973207a65726f60581b604482015290519081900360640190fd5b6001600160a01b03811660009081526004602052604090205434908015611abf5760006001808303815481106119de57fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615611a49576040805184815290516001600160a01b038616917ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4919081900360200190a2611ab9565b600354611a5c908463ffffffff612d3916565b6003908155810154611a74908463ffffffff612d3916565b60038201556040805184815290516001600160a01b038616917f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc055919081900360200190a25b50611aff565b6040805183815290516001600160a01b038516917ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4919081900360200190a25b505050565b61100081565b600381565b61100481565b611b1d613d69565b6000611b27613d69565b611b2f613d81565b611b40611b3b86612d93565b612db8565b90506000805b611b4f83612e02565b15611c605780611b7457611b6a611b6584612e23565b612e71565b60ff168452611c58565b8060011415611c53576060611b90611b8b85612e23565b612f28565b90508051604051908082528060200260200182016040528015611bcd57816020015b611bba613da1565b815260200190600190039081611bb25790505b50602086015260005b8151811015611c4857611be7613da1565b6000611c05848481518110611bf857fe5b6020026020010151612ff9565b9150915080611c2257876000995099505050505050505050611c69565b8188602001518481518110611c3357fe5b60209081029190910101525050600101611bd6565b506001925050611c58565b611c60565b600101611b46565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b6060815260200190600190039081611c88579050509050611cae8363ffffffff166130d6565b81600081518110611cbb57fe5b6020026020010181905250610bd8816130e9565b6000806060611cdd84613173565b9150915081611d8a577f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2816040518080602001828103825283818151815260200191508051906020019080838360005b83811015611d45578181015183820152602001611d2d565b50505050905090810190601f168015611d725780820380516001836020036101000a031916815260200191505b509250505060405180910390a1606692505050610f66565b600080805b600154811015611e075767016345785d8a000060018281548110611daf57fe5b90600052602060002090600402016003015410611dd157600190920191611dff565b600060018281548110611de057fe5b9060005260206000209060040201600301541115611dff576001909101905b600101611d8f565b50606082604051908082528060200260200182016040528015611e34578160200160208202803683370190505b509050606083604051908082528060200260200182016040528015611e63578160200160208202803683370190505b509050606084604051908082528060200260200182016040528015611e92578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015611ec1578160200160208202803683370190505b5090506000606086604051908082528060200260200182016040528015611ef2578160200160208202803683370190505b509050606087604051908082528060200260200182016040528015611f21578160200160208202803683370190505b509050600098506000975060608d905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015611f6e57600080fd5b505afa158015611f82573d6000803e3d6000fd5b505050506040513d6020811015611f9857600080fd5b5051905067016345785d8a000081111561200d577f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2604051808060200182810382526021815260200180613ebf6021913960400191505060405180910390a160689d5050505050505050505050505050610f66565b60005b6001548110156122805767016345785d8a00006001828154811061203057fe5b906000526020600020906004020160030154106121b6576001818154811061205457fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b03168a8d8151811061208557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be400600183815481106120ba57fe5b906000526020600020906004020160030154816120d357fe5b06600183815481106120e157fe5b906000526020600020906004020160030154039050612109838261325590919063ffffffff16565b8a8e8151811061211557fe5b6020026020010181815250506001828154811061212e57fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316888e8151811061215f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081898e8151811061218c57fe5b60209081029190910101526121a7878263ffffffff612d3916565b6001909d019c96506122789050565b6000600182815481106121c557fe5b906000526020600020906004020160030154111561227857600181815481106121ea57fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316858c8151811061221b57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001818154811061224857fe5b906000526020600020906004020160030154848c8151811061226657fe5b60209081029190910101526001909a01995b600101612010565b50600085156126be576110046001600160a01b0316636e056520878c8c8b60025442016040518663ffffffff1660e01b815260040180806020018060200180602001856001600160401b03166001600160401b03168152602001848103845288818151815260200191508051906020019060200280838360005b838110156123125781810151838201526020016122fa565b50505050905001848103835287818151815260200191508051906020019060200280838360005b83811015612351578181015183820152602001612339565b50505050905001848103825286818151815260200191508051906020019060200280838360005b83811015612390578181015183820152602001612378565b505050509050019750505050505050506020604051808303818588803b1580156123b957600080fd5b505af1935050505080156123df57506040513d60208110156123da57600080fd5b505160015b61261a576040516000815260443d10156123fb57506000612496565b60046000803e60005160e01c6308c379a0811461241c576000915050612496565b60043d036004833e81513d60248201116001600160401b038211171561244757600092505050612496565b80830180516001600160401b03811115612468576000945050505050612496565b8060208301013d860181111561248657600095505050505050612496565b601f01601f191660405250925050505b806124a15750612545565b60019150867fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280826040518080602001828103825283818151815260200191508051906020019080838360005b838110156125055781810151838201526020016124ed565b50505050905090810190601f1680156125325780820380516001836020036101000a031916815260200191505b509250505060405180910390a250612615565b3d80801561256f576040519150601f19603f3d011682016040523d82523d6000602084013e612574565b606091505b5060019150867fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a45826040518080602001828103825283818151815260200191508051906020019080838360005b838110156125d95781810151838201526020016125c1565b50505050905090810190601f1680156126065780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b6126be565b8015612658576040805188815290517fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b709181900360200190a16126bc565b604080516020808252601b908201527f6261746368207472616e736665722072657475726e2066616c7365000000000081830152905188917fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280919081900360600190a25b505b80156128745760005b88518110156128725760008982815181106126de57fe5b602002602001015190506000600182815481106126f757fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc918590811061272857fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f19350505050905080156127e4576001828154811061276957fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d91859081106127b857fe5b9060005260206000209060040201600301546040518082815260200191505060405180910390a2612868565b600182815481106127f157fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d918590811061284057fe5b9060005260206000209060040201600301546040518082815260200191505060405180910390a25b50506001016126c7565b505b8451156129be5760005b85518110156129bc57600086828151811061289557fe5b60200260200101516001600160a01b03166108fc8784815181106128b557fe5b60200260200101519081150290604051600060405180830381858888f193505050509050801561294b578682815181106128eb57fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d87848151811061292957fe5b60200260200101516040518082815260200191505060405180910390a26129b3565b86828151811061295757fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d87848151811061299557fe5b60200260200101516040518082815260200191505060405180910390a25b5060010161287e565b505b4715612a27576040805147815290517f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d9181900360200190a1604051611002904780156108fc02916000818181858888f19350505050158015612a25573d6000803e3d6000fd5b505b60006003819055600555825115612a4157612a4183613297565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612a7e57600080fd5b505af1158015612a92573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a15060009f9e505050505050505050505050505050565b80516001600160a01b0316600090815260046020526040812054801580612b265750600180820381548110612b0657fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b15612b6c5782516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a26000915050610f66565b600154600554600019820111801590612bc25784516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a260009350505050610f66565b600580546001908101909155805481906000198601908110612be057fe5b6000918252602082206002600490920201018054921515600160e01b0260ff60e01b199093169290921790915585516040516001600160a01b03909116917ff226e7d8f547ff903d9d419cf5f54e0d7d07efa9584135a53a057c5f1f27f49a91a2506000949350505050565b6000816040516020018082805190602001908083835b60208310612c815780518252601f199092019160209182019101612c62565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310612cef5780518252601f199092019160209182019101612cd0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001201490505b92915050565b015190565b600082820183811015610bd8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612d9b613dd6565b506040805180820190915281518152602082810190820152919050565b612dc0613d81565b612dc98261375e565b612dd257600080fd5b6000612de18360200151613798565b60208085015160408051808201909152868152920190820152915050919050565b6000612e0c613dd6565b505080518051602091820151919092015191011190565b612e2b613dd6565b612e3482612e02565b612e3d57600080fd5b60208201516000612e4d826137fb565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590612e8657508151602110155b612e8f57600080fd5b6000612e9e8360200151613798565b90508083600001511015612ef9576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015612f1f57826020036101000a820491505b50949350505050565b6060612f338261375e565b612f3c57600080fd5b6000612f478361392e565b9050606081604051908082528060200260200182016040528015612f8557816020015b612f72613dd6565b815260200190600190039081612f6a5790505b5090506000612f978560200151613798565b60208601510190506000805b84811015612fee57612fb4836137fb565b9150604051806040016040528083815260200184815250848281518110612fd757fe5b602090810291909101015291810191600101612fa3565b509195945050505050565b613001613da1565b600061300b613da1565b613013613d81565b61301c85612db8565b90506000805b61302b83612e02565b15611c6057806130565761304661304184612e23565b61398a565b6001600160a01b031684526130ce565b806001141561307e5761306b61304184612e23565b6001600160a01b031660208501526130ce565b80600214156130a65761309361304184612e23565b6001600160a01b031660408501526130ce565b8060031415611c53576130bb611b6584612e23565b6001600160401b03166060850152600191505b600101613022565b6060612d2e6130e4836139a4565b613a8a565b606081516000141561310a5750604080516000815260208101909152610f66565b60608260008151811061311957fe5b602002602001015190506000600190505b835181101561315a576131508285838151811061314357fe5b6020026020010151613adc565b915060010161312a565b50610bd861316d825160c060ff16613b59565b82613adc565b600060606029835111156131a5576000604051806060016040528060298152602001613df16029913991509150611c69565b60005b835181101561323b5760005b81811015613232578481815181106131c857fe5b6020026020010151600001516001600160a01b03168583815181106131e957fe5b6020026020010151600001516001600160a01b0316141561322a5760006040518060600160405280602b8152602001613e1a602b9139935093505050611c69565b6001016131b4565b506001016131a8565b505060408051602081019091526000815260019150915091565b6000610bd883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613c51565b600154815160005b828110156133b45760016132b1613da1565b600183815481106132be57fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b848110156133885786818151811061334e57fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b031614156133805760009250613388565b60010161333a565b5081156133aa5780516001600160a01b03166000908152600460205260408120555b505060010161329f565b508082111561342957805b828110156134275760018054806133d257fe5b60008281526020812060046000199093019283020180546001600160a01b03199081168255600182810180549092169091556002820180546001600160e81b03191690556003909101919091559155016133bf565b505b6000818310613438578161343a565b825b905060005b81811015613634576134ec85828151811061345657fe5b60200260200101516001838154811061346b57fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152613ce8565b61360757806001016004600087848151811061350457fe5b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000208190555084818151811061354057fe5b60200260200101516001828154811061355557fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015561362c565b60006001828154811061361657fe5b9060005260206000209060040201600301819055505b60010161343f565b508282111561375857825b82811015610ef657600185828151811061365557fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782559585015181840180549184169188169190911790556040850151600282018054606088015160808901511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590971692909a169190911792909216939093171695909517905560a0909201516003909301929092558751908401929088908590811061372b57fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161363f565b50505050565b805160009061376f57506000610f66565b6020820151805160001a9060c082101561378e57600092505050610f66565b5060019392505050565b8051600090811a60808110156137b2576000915050610f66565b60b88110806137cd575060c081108015906137cd575060f881105b156137dc576001915050610f66565b60c08110156137f05760b519019050610f66565b60f519019050610f66565b80516000908190811a60808110156138165760019150613927565b60b881101561382b57607e1981019150613927565b60c08110156138a557600060b78203600186019550806020036101000a86510491506001810182019350508083101561389f576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50613927565b60f88110156138ba5760be1981019150613927565b600060f78203600186019550806020036101000a865104915060018101820193505080831015613925576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b805160009061393f57506000610f66565b600080905060006139538460200151613798565b602085015185519181019250015b8082101561398157613972826137fb565b60019093019290910190613961565b50909392505050565b805160009060151461399b57600080fd5b612d2e82612e71565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166139e857506018613a0c565b6fffffffffffffffffffffffffffffffff198416613a0857506010613a0c565b5060005b6020811015613a4257818181518110613a2157fe5b01602001516001600160f81b03191615613a3a57613a42565b600101613a0c565b60008160200390506060816040519080825280601f01601f191660200182016040528015613a77576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015613abc5750607f60f81b82600081518110613aaa57fe5b01602001516001600160f81b03191611155b15613ac8575080610f66565b612d2e613ada8351608060ff16613b59565b835b6060806040519050835180825260208201818101602087015b81831015613b0d578051835260209283019201613af5565b50855184518101855292509050808201602086015b81831015613b3a578051835260209283019201613b22565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310613ba9576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b60408051600180825281830190925260609160208201818036833701905050905060378411613c035782840160f81b81600081518110613be557fe5b60200101906001600160f81b031916908160001a9053509050612d2e565b6060613c0e856139a4565b90508381510160370160f81b82600081518110613c2757fe5b60200101906001600160f81b031916908160001a905350613c488282613adc565b95945050505050565b60008184841115613ce05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613ca5578181015183820152602001613c8d565b50505050905090810190601f168015613cd25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b805182516000916001600160a01b039182169116148015613d22575081602001516001600160a01b031683602001516001600160a01b0316145b8015613d47575081604001516001600160a01b031683604001516001600160a01b0316145b8015610bd85750506060908101519101516001600160401b0390811691161490565b60408051808201909152600081526060602082015290565b6040518060400160405280613d94613dd6565b8152602001600081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60405180604001604052806000815260200160008152509056fe746865206e756d626572206f662076616c696461746f72732065786365656420746865206c696d69746475706c696361746520636f6e73656e7375732061646472657373206f662076616c696461746f725365747468652065787069726554696d655365636f6e64476170206973206f7574206f662072616e67656c656e677468206f66206a61696c2076616c696461746f7273206d757374206265206f6e65746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374666565206973206c6172676572207468616e2044555354595f494e434f4d494e476c656e677468206f662065787069726554696d655365636f6e64476170206d69736d617463686661696c656420746f20706172736520696e69742076616c696461746f72536574f905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a2000746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d6573736167652073656e646572206d7573742062652074686520626c6f636b2070726f6475636572746865206d6573736167652073656e646572206d75737420626520736c61736820636f6e7472616374a2646970667358221220f4016eb3755efa2abde797b21f8695280d971b0fea37198122d2e5867516da0464736f6c63430006040033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.