Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ForeignAMB
Compiler Version
v0.4.24+commit.e67f0147
Optimization Enabled:
Yes with 100 runs
Other Settings:
byzantium EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.4.24; import "./BasicForeignAMB.sol"; contract ForeignAMB is BasicForeignAMB { event UserRequestForAffirmation(bytes32 indexed messageId, bytes encodedData); event RelayedMessage(address indexed sender, address indexed executor, bytes32 indexed messageId, bool status); function emitEventOnMessageRequest(bytes32 messageId, bytes encodedData) internal { emit UserRequestForAffirmation(messageId, encodedData); } function emitEventOnMessageProcessed(address sender, address executor, bytes32 messageId, bool status) internal { emit RelayedMessage(sender, executor, messageId, status); } }
pragma solidity 0.4.24; import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; contract ERC677 is ERC20 { event Transfer(address indexed from, address indexed to, uint256 value, bytes data); function transferAndCall(address, uint256, bytes) external returns (bool); function increaseAllowance(address spender, uint256 addedValue) public returns (bool); function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool); } contract LegacyERC20 { function transfer(address _spender, uint256 _value) public; // returns (bool); function transferFrom(address _owner, address _spender, uint256 _value) public; // returns (bool); }
pragma solidity 0.4.24; interface IYaho { function dispatchMessage( uint256 targetChainId, uint256 threshold, address receiver, bytes data, address[] reporters, address[] adapters ) external returns (uint256); }
pragma solidity 0.4.24; interface IBridgeValidators { function isValidator(address _validator) external view returns (bool); function requiredSignatures() external view returns (uint256); function owner() external view returns (address); }
pragma solidity 0.4.24; interface IHashiManager { function adapters() external view returns (address[]); function reporters() external view returns (address[]); function expectedAdaptersHash() external view returns (bytes32); function expectedThreshold() external view returns (uint256); function yaho() external view returns (address); function yaru() external view returns (address); function targetAddress() external view returns (address); function targetChainId() external view returns (uint256); function threshold() external view returns (uint256); }
pragma solidity 0.4.24; interface IUpgradeabilityOwnerStorage { function upgradeabilityOwner() external view returns (address); }
pragma solidity 0.4.24; import "../upgradeable_contracts/Sacrifice.sol"; /** * @title Address * @dev Helper methods for Address type. */ library Address { /** * @dev Try to send native tokens to the address. If it fails, it will force the transfer by creating a selfdestruct contract * @param _receiver address that will receive the native tokens * @param _value the amount of native tokens to send */ function safeSendValue(address _receiver, uint256 _value) internal { if (!_receiver.send(_value)) { (new Sacrifice).value(_value)(_receiver); } } }
pragma solidity 0.4.24; import "./Bytes.sol"; library ArbitraryMessage { /** * @dev Unpacks data fields from AMB message * layout of message :: bytes: * offset 0 : 32 bytes :: uint256 - message length * offset 32 : 32 bytes :: bytes32 - messageId * offset 64 : 20 bytes :: address - sender address * offset 84 : 20 bytes :: address - executor contract * offset 104 : 4 bytes :: uint32 - gasLimit * offset 108 : 1 bytes :: uint8 - source chain id length (X) * offset 109 : 1 bytes :: uint8 - destination chain id length (Y) * offset 110 : 1 bytes :: uint8 - dataType * offset 111 : X bytes :: bytes - source chain id * offset 111 + X : Y bytes :: bytes - destination chain id * NOTE: when message structure is changed, make sure that MESSAGE_PACKING_VERSION from VersionableAMB is updated as well * NOTE: assembly code uses calldatacopy, make sure that message is passed as the first argument in the calldata * @param _data encoded message */ function unpackData(bytes _data) internal pure returns ( bytes32 messageId, address sender, address executor, uint32 gasLimit, uint8 dataType, uint256[2] chainIds, bytes memory data ) { // 32 (message id) + 20 (sender) + 20 (executor) + 4 (gasLimit) + 1 (source chain id length) + 1 (destination chain id length) + 1 (dataType) uint256 srcdataptr = 32 + 20 + 20 + 4 + 1 + 1 + 1; uint256 datasize; assembly { messageId := mload(add(_data, 32)) // 32 bytes sender := and(mload(add(_data, 52)), 0xffffffffffffffffffffffffffffffffffffffff) // 20 bytes // executor (20 bytes) + gasLimit (4 bytes) + srcChainIdLength (1 byte) + dstChainIdLength (1 bytes) + dataType (1 byte) + remainder (5 bytes) let blob := mload(add(_data, 84)) // after bit shift left 12 bytes are zeros automatically executor := shr(96, blob) gasLimit := and(shr(64, blob), 0xffffffff) dataType := byte(26, blob) // load source chain id length let chainIdLength := byte(24, blob) // at this moment srcdataptr points to sourceChainId // mask for sourceChainId // e.g. length X -> (1 << (X * 8)) - 1 let mask := sub(shl(shl(3, chainIdLength), 1), 1) // increase payload offset by length of source chain id srcdataptr := add(srcdataptr, chainIdLength) // write sourceChainId mstore(chainIds, and(mload(add(_data, srcdataptr)), mask)) // at this moment srcdataptr points to destinationChainId // load destination chain id length chainIdLength := byte(25, blob) // mask for destinationChainId // e.g. length X -> (1 << (X * 8)) - 1 mask := sub(shl(shl(3, chainIdLength), 1), 1) // increase payload offset by length of destination chain id srcdataptr := add(srcdataptr, chainIdLength) // write destinationChainId mstore(add(chainIds, 32), and(mload(add(_data, srcdataptr)), mask)) // at this moment srcdataptr points to payload // datasize = message length - payload offset datasize := sub(mload(_data), srcdataptr) } data = Bytes.slice(_data, srcdataptr, datasize); } }
pragma solidity 0.4.24; /** * @title Bytes * @dev Helper methods to transform bytes to other solidity types. */ library Bytes { /** * @dev Converts bytes array to bytes32. * Truncates bytes array if its size is more than 32 bytes. * NOTE: This function does not perform any checks on the received parameter. * Make sure that the _bytes argument has a correct length, not less than 32 bytes. * A case when _bytes has length less than 32 will lead to the undefined behaviour, * since assembly will read data from memory that is not related to the _bytes argument. * @param _bytes to be converted to bytes32 type * @return bytes32 type of the firsts 32 bytes array in parameter. */ function bytesToBytes32(bytes _bytes) internal pure returns (bytes32 result) { assembly { result := mload(add(_bytes, 32)) } } /** * @dev Truncate bytes array if its size is more than 20 bytes. * NOTE: Similar to the bytesToBytes32 function, make sure that _bytes is not shorter than 20 bytes. * @param _bytes to be converted to address type * @return address included in the firsts 20 bytes of the bytes array in parameter. */ function bytesToAddress(bytes _bytes) internal pure returns (address addr) { assembly { addr := mload(add(_bytes, 20)) } } function slice(bytes memory data, uint256 start, uint256 length) internal pure returns (bytes memory) { require(data.length >= start + length); bytes memory tempData; assembly { switch iszero(length) case 0 { tempData := mload(0x40) let lengthmod := and(length, 31) let mc := add(add(tempData, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, length) for { let cc := add(add(add(data, lengthmod), mul(0x20, iszero(lengthmod))), start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempData, length) mstore(0x40, and(add(mc, 31), not(31))) } default { tempData := mload(0x40) mstore(tempData, 0) mstore(0x40, add(tempData, 0x20)) } } return tempData; } }
pragma solidity 0.4.24; import "../interfaces/IBridgeValidators.sol"; library Message { function addressArrayContains(address[] array, address value) internal pure returns (bool) { for (uint256 i = 0; i < array.length; i++) { if (array[i] == value) { return true; } } return false; } // layout of message :: bytes: // offset 0: 32 bytes :: uint256 - message length // offset 32: 20 bytes :: address - recipient address // offset 52: 32 bytes :: uint256 - value // offset 84: 32 bytes :: bytes32 - transaction hash // offset 116: 20 bytes :: address - contract address to prevent double spending // mload always reads 32 bytes. // so we can and have to start reading recipient at offset 20 instead of 32. // if we were to read at 32 the address would contain part of value and be corrupted. // when reading from offset 20 mload will read 12 bytes (most of them zeros) followed // by the 20 recipient address bytes and correctly convert it into an address. // this saves some storage/gas over the alternative solution // which is padding address to 32 bytes and reading recipient at offset 32. // for more details see discussion in: // https://github.com/paritytech/parity-bridge/issues/61 function parseMessage(bytes message) internal pure returns (address recipient, uint256 amount, bytes32 txHash, address contractAddress) { require(isMessageValid(message)); assembly { recipient := mload(add(message, 20)) amount := mload(add(message, 52)) txHash := mload(add(message, 84)) contractAddress := mload(add(message, 104)) } } function isMessageValid(bytes _msg) internal pure returns (bool) { return _msg.length == requiredMessageLength(); } function requiredMessageLength() internal pure returns (uint256) { return 104; } function recoverAddressFromSignedMessage(bytes signature, bytes message, bool isAMBMessage) internal pure returns (address) { require(signature.length == 65); bytes32 r; bytes32 s; bytes1 v; assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := mload(add(signature, 0x60)) } require(uint8(v) == 27 || uint8(v) == 28); require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0); return ecrecover(hashMessage(message, isAMBMessage), uint8(v), r, s); } function hashMessage(bytes message, bool isAMBMessage) internal pure returns (bytes32) { bytes memory prefix = "\x19Ethereum Signed Message:\n"; if (isAMBMessage) { return keccak256(abi.encodePacked(prefix, uintToString(message.length), message)); } else { string memory msgLength = "104"; return keccak256(abi.encodePacked(prefix, msgLength, message)); } } /** * @dev Validates provided signatures, only first requiredSignatures() number * of signatures are going to be validated, these signatures should be from different validators. * @param _message bytes message used to generate signatures * @param _signatures bytes blob with signatures to be validated. * First byte X is a number of signatures in a blob, * next X bytes are v components of signatures, * next 32 * X bytes are r components of signatures, * next 32 * X bytes are s components of signatures. * @param _validatorContract contract, which conforms to the IBridgeValidators interface, * where info about current validators and required signatures is stored. * @param isAMBMessage true if _message is an AMB message with arbitrary length. */ function hasEnoughValidSignatures( bytes _message, bytes _signatures, IBridgeValidators _validatorContract, bool isAMBMessage ) internal view { require(isAMBMessage || isMessageValid(_message)); uint256 requiredSignatures = _validatorContract.requiredSignatures(); uint256 amount; assembly { amount := and(mload(add(_signatures, 1)), 0xff) } require(amount >= requiredSignatures); bytes32 hash = hashMessage(_message, isAMBMessage); address[] memory encounteredAddresses = new address[](requiredSignatures); for (uint256 i = 0; i < requiredSignatures; i++) { uint8 v; bytes32 r; bytes32 s; uint256 posr = 33 + amount + 32 * i; uint256 poss = posr + 32 * amount; assembly { v := mload(add(_signatures, add(2, i))) r := mload(add(_signatures, posr)) s := mload(add(_signatures, poss)) } address recoveredAddress = ecrecover(hash, v, r, s); require(_validatorContract.isValidator(recoveredAddress)); require(!addressArrayContains(encounteredAddresses, recoveredAddress)); encounteredAddresses[i] = recoveredAddress; } } function uintToString(uint256 i) internal pure returns (string) { if (i == 0) return "0"; uint256 j = i; uint256 length; while (j != 0) { length++; j /= 10; } bytes memory bstr = new bytes(length); uint256 k = length - 1; while (i != 0) { bstr[k--] = bytes1(48 + (i % 10)); i /= 10; } return string(bstr); } }
pragma solidity 0.4.24; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../interfaces/ERC677.sol"; /** * @title SafeERC20 * @dev Helper methods for safe token transfers. * Functions perform additional checks to be sure that token transfer really happened. */ library SafeERC20 { using SafeMath for uint256; /** * @dev Same as ERC20.transfer(address,uint256) but with extra consistency checks. * @param _token address of the token contract * @param _to address of the receiver * @param _value amount of tokens to send */ function safeTransfer(address _token, address _to, uint256 _value) internal { LegacyERC20(_token).transfer(_to, _value); assembly { if returndatasize { returndatacopy(0, 0, 32) if iszero(mload(0)) { revert(0, 0) } } } } /** * @dev Same as ERC20.transferFrom(address,address,uint256) but with extra consistency checks. * @param _token address of the token contract * @param _from address of the sender * @param _value amount of tokens to send */ function safeTransferFrom(address _token, address _from, uint256 _value) internal { LegacyERC20(_token).transferFrom(_from, address(this), _value); assembly { if returndatasize { returndatacopy(0, 0, 32) if iszero(mload(0)) { revert(0, 0) } } } } }
pragma solidity 0.4.24; /** * @title EternalStorage * @dev This contract holds all the necessary state variables to carry out the storage of any contract. */ contract EternalStorage { mapping(bytes32 => uint256) internal uintStorage; mapping(bytes32 => string) internal stringStorage; mapping(bytes32 => address) internal addressStorage; mapping(bytes32 => bytes) internal bytesStorage; mapping(bytes32 => bool) internal boolStorage; mapping(bytes32 => int256) internal intStorage; }
pragma solidity 0.4.24; import "../BasicBridge.sol"; import "./VersionableAMB.sol"; contract BasicAMB is BasicBridge, VersionableAMB { bytes32 internal constant MAX_GAS_PER_TX = 0x2670ecc91ec356e32067fd27b36614132d727b84a1e03e08f412a4f2cf075974; // keccak256(abi.encodePacked("maxGasPerTx")) bytes32 internal constant NONCE = 0x7ab1577440dd7bedf920cb6de2f9fc6bf7ba98c78c85a3fa1f8311aac95e1759; // keccak256(abi.encodePacked("nonce")) bytes32 internal constant SOURCE_CHAIN_ID = 0x67d6f42a1ed69c62022f2d160ddc6f2f0acd37ad1db0c24f4702d7d3343a4add; // keccak256(abi.encodePacked("sourceChainId")) bytes32 internal constant SOURCE_CHAIN_ID_LENGTH = 0xe504ae1fd6471eea80f18b8532a61a9bb91fba4f5b837f80a1cfb6752350af44; // keccak256(abi.encodePacked("sourceChainIdLength")) bytes32 internal constant DESTINATION_CHAIN_ID = 0xbbd454018e72a3f6c02bbd785bacc49e46292744f3f6761276723823aa332320; // keccak256(abi.encodePacked("destinationChainId")) bytes32 internal constant DESTINATION_CHAIN_ID_LENGTH = 0xfb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d4989692811594; // keccak256(abi.encodePacked("destinationChainIdLength")) bytes32 internal constant ALLOW_REENTRANT_REQUESTS = 0xffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd6; // keccak256(abi.encodePacked("allowReentrantRequests")) /** * Initializes AMB contract * @param _sourceChainId chain id of a network where this contract is deployed * @param _destinationChainId chain id of a network where all outgoing messages are directed * @param _validatorContract address of the validators contract * @param _maxGasPerTx maximum amount of gas per one message execution * @param _gasPrice default gas price used by oracles for sending transactions in this network * @param _requiredBlockConfirmations number of block confirmations oracle will wait before processing passed messages * @param _owner address of new bridge owner */ function initialize( uint256 _sourceChainId, uint256 _destinationChainId, address _validatorContract, uint256 _maxGasPerTx, uint256 _gasPrice, uint256 _requiredBlockConfirmations, address _owner ) external onlyRelevantSender returns (bool) { require(!isInitialized()); require(AddressUtils.isContract(_validatorContract)); _setChainIds(_sourceChainId, _destinationChainId); addressStorage[VALIDATOR_CONTRACT] = _validatorContract; uintStorage[DEPLOYED_AT_BLOCK] = block.number; uintStorage[MAX_GAS_PER_TX] = _maxGasPerTx; _setGasPrice(_gasPrice); _setRequiredBlockConfirmations(_requiredBlockConfirmations); _setOwner(_owner); setInitialize(); return isInitialized(); } function getBridgeMode() external pure returns (bytes4 _data) { return 0x2544fbb9; // bytes4(keccak256(abi.encodePacked("arbitrary-message-bridge-core"))) } function maxGasPerTx() public view returns (uint256) { return uintStorage[MAX_GAS_PER_TX]; } function setMaxGasPerTx(uint256 _maxGasPerTx) external onlyOwner { uintStorage[MAX_GAS_PER_TX] = _maxGasPerTx; } /** * Internal function for retrieving chain id for the source network * @return chain id for the current network */ function sourceChainId() public view returns (uint256) { return uintStorage[SOURCE_CHAIN_ID]; } /** * Internal function for retrieving chain id for the destination network * @return chain id for the destination network */ function destinationChainId() public view returns (uint256) { return uintStorage[DESTINATION_CHAIN_ID]; } /** * Updates chain ids of used networks * @param _sourceChainId chain id for current network * @param _destinationChainId chain id for opposite network */ function setChainIds(uint256 _sourceChainId, uint256 _destinationChainId) external onlyOwner { _setChainIds(_sourceChainId, _destinationChainId); } /** * Sets the flag to allow passing new AMB requests in the opposite direction, * while other AMB message is being processed. * Only owner can call this method. * @param _enable true, if reentrant requests are allowed. */ function setAllowReentrantRequests(bool _enable) external onlyOwner { boolStorage[ALLOW_REENTRANT_REQUESTS] = _enable; } /** * Tells if passing reentrant requests is allowed. * @return true, if reentrant requests are allowed. */ function allowReentrantRequests() public view returns (bool) { return boolStorage[ALLOW_REENTRANT_REQUESTS]; } /** * @dev Withdraws the erc20 tokens or native coins from this contract. * @param _token address of the claimed token or address(0) for native coins. * @param _to address of the tokens/coins receiver. */ function claimTokens(address _token, address _to) external onlyIfUpgradeabilityOwner { claimValues(_token, _to); } /** * Internal function for retrieving current nonce value * @return nonce value */ function _nonce() internal view returns (uint64) { return uint64(uintStorage[NONCE]); } /** * Internal function for updating nonce value * @param _nonce new nonce value */ function _setNonce(uint64 _nonce) internal { uintStorage[NONCE] = uint256(_nonce); } /** * Internal function for updating chain ids of used networks * @param _sourceChainId chain id for current network * @param _destinationChainId chain id for opposite network */ function _setChainIds(uint256 _sourceChainId, uint256 _destinationChainId) internal { require(_sourceChainId > 0 && _destinationChainId > 0); require(_sourceChainId != _destinationChainId); // Length fields are needed further when encoding the message. // Chain ids are compressed, so that leading zero bytes are not preserved. // In order to save some gas during calls to MessageDelivery.c, // lengths of chain ids are precalculated and being saved in the storage. uint256 sourceChainIdLength = 0; uint256 destinationChainIdLength = 0; uint256 mask = 0xff; for (uint256 i = 1; sourceChainIdLength == 0 || destinationChainIdLength == 0; i++) { if (sourceChainIdLength == 0 && _sourceChainId & mask == _sourceChainId) { sourceChainIdLength = i; } if (destinationChainIdLength == 0 && _destinationChainId & mask == _destinationChainId) { destinationChainIdLength = i; } mask = (mask << 8) | 0xff; } uintStorage[SOURCE_CHAIN_ID] = _sourceChainId; uintStorage[SOURCE_CHAIN_ID_LENGTH] = sourceChainIdLength; uintStorage[DESTINATION_CHAIN_ID] = _destinationChainId; uintStorage[DESTINATION_CHAIN_ID_LENGTH] = destinationChainIdLength; } /** * Internal function for retrieving chain id length for the source network * @return chain id for the current network */ function _sourceChainIdLength() internal view returns (uint256) { return uintStorage[SOURCE_CHAIN_ID_LENGTH]; } /** * Internal function for retrieving chain id length for the destination network * @return chain id for the destination network */ function _destinationChainIdLength() internal view returns (uint256) { return uintStorage[DESTINATION_CHAIN_ID_LENGTH]; } /** * Internal function for validating version of the received message * @param _messageId id of the received message */ function _isMessageVersionValid(bytes32 _messageId) internal returns (bool) { return _messageId & 0xffffffff00000000000000000000000000000000000000000000000000000000 == MESSAGE_PACKING_VERSION; } /** * Internal function for validating destination chain id of the received message * @param _chainId destination chain id of the received message */ function _isDestinationChainIdValid(uint256 _chainId) internal returns (bool res) { return _chainId == sourceChainId(); } }
pragma solidity 0.4.24; import "../../libraries/Message.sol"; import "../../libraries/ArbitraryMessage.sol"; import "./BasicAMB.sol"; import "./MessageDelivery.sol"; import "../MessageRelay.sol"; contract BasicForeignAMB is BasicAMB, MessageRelay, MessageDelivery { /** * @dev Validates provided signatures and relays a given message * @param _data bytes to be relayed * @param _signatures bytes blob with signatures to be validated */ function executeSignatures(bytes _data, bytes _signatures) public { _allowMessageExecution(_data, _signatures); bytes32 msgId; address sender; address executor; uint32 gasLimit; uint8 dataType; uint256[2] memory chainIds; bytes memory data; (msgId, sender, executor, gasLimit, dataType, chainIds, data) = ArbitraryMessage.unpackData(_data); _executeMessage( keccak256(abi.encodePacked(_data)), msgId, sender, executor, gasLimit, dataType, chainIds, data ); } /** * @dev Validates provided signatures and relays a given message. * The message is not allowed to fail. The whole tx will be revered if message fails. * @param _data bytes to be relayed * @param _signatures bytes blob with signatures to be validated */ function safeExecuteSignatures(bytes _data, bytes _signatures) external { executeSignatures(_data, _signatures); } /** * @dev Validates provided signatures and relays a given message. Allows to override the gas limit of the passed message. * Usually it makes sense to provide a higher amount of gas for the execution. * The message is not allowed to fail. The whole tx will be revered if message fails. * @param _data bytes to be relayed * @param _signatures bytes blob with signatures to be validated */ function safeExecuteSignaturesWithGasLimit(bytes _data, bytes _signatures, uint32 _gas) public { _allowMessageExecution(_data, _signatures); bytes32 msgId; address sender; address executor; uint8 dataType; uint256[2] memory chainIds; bytes memory data; (msgId, sender, executor, , dataType, chainIds, data) = ArbitraryMessage.unpackData(_data); _executeMessage(keccak256(abi.encodePacked(_data)), msgId, sender, executor, _gas, dataType, chainIds, data); } /** * @dev Validates provided signatures and relays a given message. Passes all available gas for the execution. * The message is not allowed to fail. The whole tx will be revered if message fails. * @param _data bytes to be relayed * @param _signatures bytes blob with signatures to be validated */ function safeExecuteSignaturesWithAutoGasLimit(bytes _data, bytes _signatures) external { safeExecuteSignaturesWithGasLimit(_data, _signatures, 0xffffffff); } /** * @dev Internal function for validating pre-execution requirements. * @param _data bytes to be relayed. * @param _signatures bytes blob with signatures to be validated. */ function _allowMessageExecution(bytes _data, bytes _signatures) internal { // this checks prevents execution of other messages, while some other message is being processed // nested executeSignatures is considered to be unsafe, // since it allows to change/reset the AMB context variables (messageId, messageSender, messageSourceChainId) // while processing nested message require(messageId() == bytes32(0)); Message.hasEnoughValidSignatures(_data, _signatures, validatorContract(), true); } /** * @dev Internal function for executing decoded message. Performs additional validation on the message fields. * @param hashMsg hash of the entire message. * @param msgId id of the processed message. * @param sender sender address on the other side. * @param executor address of an executor. * @param gasLimit gas limit for a call to executor. * @param dataType AMB message dataType to be included as a part of the header. * @param chainIds pair of source and destination chain ids. * @param data calldata for a call to executor. */ function _executeMessage( bytes32 hashMsg, bytes32 msgId, address sender, address executor, uint32 gasLimit, uint8 dataType, uint256[2] memory chainIds, bytes memory data ) internal { require(_isMessageVersionValid(msgId)); require(_isDestinationChainIdValid(chainIds[1])); require(!relayedMessages(msgId)); if (HASHI_IS_ENABLED && HASHI_IS_MANDATORY) require(isApprovedByHashi(hashMsg)); setRelayedMessages(msgId, true); processMessage(sender, executor, msgId, gasLimit, dataType, chainIds[0], data); } function onMessage( uint256, /*messageId*/ uint256 chainId, address sender, uint256 threshold, address[] adapters, bytes data ) external returns (bytes) { _validateHashiMessage(chainId, threshold, sender, adapters); bytes32 hashMsg = keccak256(abi.encodePacked(data)); require(!isApprovedByHashi(hashMsg)); _setHashiApprovalForMessage(hashMsg, true); } /** * @dev Validates message execution status. Reverts if message is was executed in safe mode and reverted. * @param _status message execution status. */ function _validateExecutionStatus(bool _status) internal { require(_status || msg.sig == this.executeSignatures.selector); } /** * @dev Internal function for updating fallback gas price value. * @param _gasPrice new value for the gas price, zero gas price is not allowed. */ function _setGasPrice(uint256 _gasPrice) internal { require(_gasPrice > 0); super._setGasPrice(_gasPrice); } }
pragma solidity 0.4.24; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./BasicAMB.sol"; import "./MessageProcessor.sol"; import "../../libraries/ArbitraryMessage.sol"; import "../../libraries/Bytes.sol"; contract MessageDelivery is BasicAMB, MessageProcessor { using SafeMath for uint256; uint256 internal constant SEND_TO_ORACLE_DRIVEN_LANE = 0x00; // after EIP2929, call to warmed contract address costs 100 instead of 2600 uint256 internal constant MIN_GAS_PER_CALL = 100; /** * @dev Requests message relay to the opposite network * @param _contract executor address on the other side * @param _data calldata passed to the executor on the other side * @param _gas gas limit used on the other network for executing a message */ function requireToPassMessage(address _contract, bytes memory _data, uint256 _gas) public returns (bytes32) { return _sendMessage(_contract, _data, _gas, SEND_TO_ORACLE_DRIVEN_LANE); } /** * @dev Initiates sending of an AMB message to the opposite network * @param _contract executor address on the other side * @param _data calldata passed to the executor on the other side * @param _gas gas limit used on the other network for executing a message * @param _dataType AMB message dataType to be included as a part of the header */ function _sendMessage(address _contract, bytes memory _data, uint256 _gas, uint256 _dataType) internal returns (bytes32) { // it is not allowed to pass messages while other messages are processed // if other is not explicitly configured require(messageId() == bytes32(0) || allowReentrantRequests()); require(_gas >= MIN_GAS_PER_CALL && _gas <= maxGasPerTx()); uint256 selector; assembly { selector := and(mload(add(_data, 4)), 0xffffffff) } // In order to prevent possible unauthorized ERC20 withdrawals, the following function signatures are prohibited: // * transfer(address,uint256) // * approve(address,uint256) // * transferFrom(address,address,uint256) // * approveAndCall(address,uint256,bytes) // * transferAndCall(address,uint256,bytes) // See https://medium.com/immunefi/xdai-stake-arbitrary-call-method-bug-postmortem-f80a90ac56e3 for more details require( selector != 0xa9059cbb && selector != 0x095ea7b3 && selector != 0x23b872dd && selector != 0x4000aea0 && selector != 0xcae9ca51 ); (bytes32 _messageId, bytes memory header) = _packHeader(_contract, _gas, _dataType); bytes memory eventData = abi.encodePacked(header, _data); emitEventOnMessageRequest(_messageId, eventData); _maybeSendDataWithHashi(eventData); return _messageId; } /** * @dev Packs message header into a single bytes blob * @param _contract executor address on the other side * @param _gas gas limit used on the other network for executing a message * @param _dataType AMB message dataType to be included as a part of the header */ function _packHeader(address _contract, uint256 _gas, uint256 _dataType) internal view returns (bytes32 _messageId, bytes memory header) { uint256 srcChainId = sourceChainId(); uint256 srcChainIdLength = _sourceChainIdLength(); uint256 dstChainId = destinationChainId(); uint256 dstChainIdLength = _destinationChainIdLength(); _messageId = _getNewMessageId(srcChainId); // 79 = 4 + 20 + 8 + 20 + 20 + 4 + 1 + 1 + 1 header = new bytes(79 + srcChainIdLength + dstChainIdLength); // In order to save the gas, the header is packed in the reverse order. // With such approach, it is possible to store right-aligned values without any additional bit shifts. assembly { let ptr := add(header, mload(header)) // points to the last word of header mstore(ptr, dstChainId) mstore(sub(ptr, dstChainIdLength), srcChainId) mstore(add(header, 79), _dataType) mstore(add(header, 78), dstChainIdLength) mstore(add(header, 77), srcChainIdLength) mstore(add(header, 76), _gas) mstore(add(header, 72), _contract) mstore(add(header, 52), caller) mstore(add(header, 32), _messageId) } } /** * @dev Generates a new messageId for the passed request/message. * Increments the nonce accordingly. * @param _srcChainId source chain id of the newly created message. Should be a chain id of the current network. * @return unique message id to use for the new request/message. */ function _getNewMessageId(uint256 _srcChainId) internal returns (bytes32) { uint64 nonce = _nonce(); _setNonce(nonce + 1); // Bridge id is recalculated every time again and again, since it is still cheaper than using SLOAD opcode (800 gas) bytes32 bridgeId = keccak256(abi.encodePacked(_srcChainId, address(this))) & 0x00000000ffffffffffffffffffffffffffffffffffffffff0000000000000000; return MESSAGE_PACKING_VERSION | bridgeId | bytes32(nonce); } /* solcov ignore next */ function emitEventOnMessageRequest(bytes32 messageId, bytes encodedData) internal; }
pragma solidity 0.4.24; import "../../upgradeability/EternalStorage.sol"; import "../../libraries/Bytes.sol"; contract MessageProcessor is EternalStorage { /** * @dev Returns a status of the message that came from the other side. * @param _messageId id of the message from the other side that triggered a call. * @return true if call executed successfully. */ function messageCallStatus(bytes32 _messageId) external view returns (bool) { return boolStorage[keccak256(abi.encodePacked("messageCallStatus", _messageId))]; } /** * @dev Sets a status of the message that came from the other side. * @param _messageId id of the message from the other side that triggered a call. * @param _status execution status, true if executed successfully. */ function setMessageCallStatus(bytes32 _messageId, bool _status) internal { boolStorage[keccak256(abi.encodePacked("messageCallStatus", _messageId))] = _status; } /** * @dev Returns a data hash of the failed message that came from the other side. * NOTE: dataHash was used previously to identify outgoing message before AMB message id was introduced. * It is kept for backwards compatibility with old mediators contracts. * @param _messageId id of the message from the other side that triggered a call. * @return keccak256 hash of message data. */ function failedMessageDataHash(bytes32 _messageId) external view returns (bytes32) { return bytes32(uintStorage[keccak256(abi.encodePacked("failedMessageDataHash", _messageId))]); } /** * @dev Sets a data hash of the failed message that came from the other side. * NOTE: dataHash was used previously to identify outgoing message before AMB message id was introduced. * It is kept for backwards compatibility with old mediators contracts. * @param _messageId id of the message from the other side that triggered a call. * @param data of the processed message. */ function setFailedMessageDataHash(bytes32 _messageId, bytes data) internal { uintStorage[keccak256(abi.encodePacked("failedMessageDataHash", _messageId))] = uint256(keccak256(data)); } /** * @dev Returns a receiver address of the failed message that came from the other side. * @param _messageId id of the message from the other side that triggered a call. * @return receiver address. */ function failedMessageReceiver(bytes32 _messageId) external view returns (address) { return addressStorage[keccak256(abi.encodePacked("failedMessageReceiver", _messageId))]; } /** * @dev Sets a sender address of the failed message that came from the other side. * @param _messageId id of the message from the other side that triggered a call. * @param _receiver address of the receiver. */ function setFailedMessageReceiver(bytes32 _messageId, address _receiver) internal { addressStorage[keccak256(abi.encodePacked("failedMessageReceiver", _messageId))] = _receiver; } /** * @dev Returns a sender address of the failed message that came from the other side. * @param _messageId id of the message from the other side that triggered a call. * @return sender address on the other side. */ function failedMessageSender(bytes32 _messageId) external view returns (address) { return addressStorage[keccak256(abi.encodePacked("failedMessageSender", _messageId))]; } /** * @dev Sets a sender address of the failed message that came from the other side. * @param _messageId id of the message from the other side that triggered a call. * @param _sender address of the sender on the other side. */ function setFailedMessageSender(bytes32 _messageId, address _sender) internal { addressStorage[keccak256(abi.encodePacked("failedMessageSender", _messageId))] = _sender; } /** * @dev Returns an address of the sender on the other side for the currently processed message. * Can be used by executors for getting other side caller address. * @return address of the sender on the other side. */ function messageSender() external view returns (address sender) { assembly { // Even though this is not the same as addressStorage[keccak256(abi.encodePacked("messageSender"))], // since solidity mapping introduces another level of addressing, such slot change is safe // for temporary variables which are cleared at the end of the call execution. sender := sload(0x7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b) // keccak256(abi.encodePacked("messageSender")) } } /** * @dev Sets an address of the sender on the other side for the currently processed message. * @param _sender address of the sender on the other side. */ function setMessageSender(address _sender) internal { assembly { // Even though this is not the same as addressStorage[keccak256(abi.encodePacked("messageSender"))], // since solidity mapping introduces another level of addressing, such slot change is safe // for temporary variables which are cleared at the end of the call execution. sstore(0x7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b, _sender) // keccak256(abi.encodePacked("messageSender")) } } /** * @dev Returns an id of the currently processed message. * @return id of the message that originated on the other side. */ function messageId() public view returns (bytes32 id) { assembly { // Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageId"))], // since solidity mapping introduces another level of addressing, such slot change is safe // for temporary variables which are cleared at the end of the call execution. id := sload(0xe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe65083304) // keccak256(abi.encodePacked("messageId")) } } /** * @dev Returns an id of the currently processed message. * NOTE: transactionHash was used previously to identify incoming message before AMB message id was introduced. * It is kept for backwards compatibility with old mediators contracts, although it doesn't return txHash anymore. * @return id of the message that originated on the other side. */ function transactionHash() external view returns (bytes32) { return messageId(); } /** * @dev Sets a message id of the currently processed message. * @param _messageId id of the message that originated on the other side. */ function setMessageId(bytes32 _messageId) internal { assembly { // Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageId"))], // since solidity mapping introduces another level of addressing, such slot change is safe // for temporary variables which are cleared at the end of the call execution. sstore(0xe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe65083304, _messageId) // keccak256(abi.encodePacked("messageId")) } } /** * @dev Returns an originating chain id of the currently processed message. * @return source chain id of the message that originated on the other side. */ function messageSourceChainId() external view returns (uint256 id) { assembly { // Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageSourceChainId"))], // since solidity mapping introduces another level of addressing, such slot change is safe // for temporary variables which are cleared at the end of the call execution. id := sload(0x7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d2) // keccak256(abi.encodePacked("messageSourceChainId")) } } /** * @dev Sets an originating chain id of the currently processed message. * @param _sourceChainId source chain id of the message that originated on the other side. */ function setMessageSourceChainId(uint256 _sourceChainId) internal { assembly { // Even though this is not the same as uintStorage[keccak256(abi.encodePacked("messageSourceChainId"))], // since solidity mapping introduces another level of addressing, such slot change is safe // for temporary variables which are cleared at the end of the call execution. sstore(0x7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d2, _sourceChainId) // keccak256(abi.encodePacked("messageSourceChainId")) } } /** * @dev Processes received message. Makes a call to the message executor, * sets dataHash, receive, sender variables for failed messages. * @param _sender sender address on the other side. * @param _executor address of an executor. * @param _messageId id of the processed message. * @param _gasLimit gas limit for a call to executor. * @param _sourceChainId source chain id is of the received message. * @param _data calldata for a call to executor. */ function processMessage( address _sender, address _executor, bytes32 _messageId, uint256 _gasLimit, uint8, /* dataType */ uint256 _sourceChainId, bytes memory _data ) internal { bool status = _passMessage(_sender, _executor, _data, _gasLimit, _messageId, _sourceChainId); setMessageCallStatus(_messageId, status); if (!status) { setFailedMessageDataHash(_messageId, _data); setFailedMessageReceiver(_messageId, _executor); setFailedMessageSender(_messageId, _sender); } emitEventOnMessageProcessed(_sender, _executor, _messageId, status); } /** * @dev Makes a call to the message executor. * @param _sender sender address on the other side. * @param _contract address of an executor contract. * @param _data calldata for a call to executor. * @param _gas gas limit for a call to executor. 2^32 - 1, if caller will pass all available gas for the execution. * @param _messageId id of the processed message. * @param _sourceChainId source chain id is of the received message. */ function _passMessage( address _sender, address _contract, bytes _data, uint256 _gas, bytes32 _messageId, uint256 _sourceChainId ) internal returns (bool) { setMessageSender(_sender); setMessageId(_messageId); setMessageSourceChainId(_sourceChainId); // After EIP-150, max gas cost allowed to be passed to the internal call is equal to the 63/64 of total gas left. // In reality, min(gasLimit, 63/64 * gasleft()) will be used as the call gas limit. // Imagine a situation, when message requires 10000000 gas to be executed successfully. // Also suppose, that at this point, gasleft() is equal to 10158000, so the callee will receive ~ 10158000 * 63 / 64 = 9999300 gas. // That amount of gas is not enough, so the call will fail. At the same time, // even if the callee failed the bridge contract still has ~ 158000 gas to // finish its execution and it will be enough. The internal call fails but // only because the oracle provides incorrect gas limit for the transaction // This check is needed here in order to force contract to pass exactly the requested amount of gas. // Avoiding it may lead to the unwanted message failure in some extreme cases. require(_gas == 0xffffffff || (gasleft() * 63) / 64 > _gas); bool status = _contract.call.gas(_gas)(_data); _validateExecutionStatus(status); setMessageSender(address(0)); setMessageId(bytes32(0)); setMessageSourceChainId(0); return status; } /** * @dev Validates message execution status. In simplest case, does nothing. * @param _status message execution status. */ function _validateExecutionStatus(bool _status) internal { (_status); } /* solcov ignore next */ function emitEventOnMessageProcessed(address sender, address executor, bytes32 messageId, bool status) internal; }
pragma solidity 0.4.24; import "../VersionableBridge.sol"; contract VersionableAMB is VersionableBridge { // message format version as a single 4-bytes number padded to 32-bytes // value, included into every outgoing relay request // // the message version should be updated every time when // - new field appears // - some field removed // - fields order is changed bytes32 internal constant MESSAGE_PACKING_VERSION = 0x00050000 << 224; /** * Returns currently used bridge version * @return (major, minor, patch) version triple */ function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { return (6, 2, 0); } }
pragma solidity 0.4.24; import "./Upgradeable.sol"; import "./InitializableBridge.sol"; import "openzeppelin-solidity/contracts/AddressUtils.sol"; import "./Validatable.sol"; import "./Ownable.sol"; import "./Claimable.sol"; import "./VersionableBridge.sol"; import "./DecimalShiftBridge.sol"; import "../interfaces/hashi/IYaho.sol"; import "../interfaces/IHashiManager.sol"; contract BasicBridge is InitializableBridge, Validatable, Ownable, Upgradeable, Claimable, VersionableBridge, DecimalShiftBridge { event GasPriceChanged(uint256 gasPrice); event RequiredBlockConfirmationChanged(uint256 requiredBlockConfirmations); bytes32 internal constant GAS_PRICE = 0x55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b; // keccak256(abi.encodePacked("gasPrice")) bytes32 internal constant REQUIRED_BLOCK_CONFIRMATIONS = 0x916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071; // keccak256(abi.encodePacked("requiredBlockConfirmations")) bytes32 internal constant HASHI_MANAGER = 0x660d8ed18395a9aa930e304e0bb5e6e51957af1fa215b11db48bfda3dd38d511; // keccak256(abi.encodePacked("hashiManager")) bool public constant HASHI_IS_ENABLED = true; bool public constant HASHI_IS_MANDATORY = false; function isApprovedByHashi(bytes32 hashMsg) public view returns (bool) { return boolStorage[keccak256(abi.encodePacked("messagesApprovedByHashi", hashMsg))]; } /** * @dev Public setter for fallback gas price value. Only bridge owner can call this method. * @param _gasPrice new value for the gas price. */ function setGasPrice(uint256 _gasPrice) external onlyOwner { _setGasPrice(_gasPrice); } function gasPrice() external view returns (uint256) { return uintStorage[GAS_PRICE]; } function setRequiredBlockConfirmations(uint256 _blockConfirmations) external onlyOwner { _setRequiredBlockConfirmations(_blockConfirmations); } function _setRequiredBlockConfirmations(uint256 _blockConfirmations) internal { require(_blockConfirmations > 0); uintStorage[REQUIRED_BLOCK_CONFIRMATIONS] = _blockConfirmations; emit RequiredBlockConfirmationChanged(_blockConfirmations); } function requiredBlockConfirmations() external view returns (uint256) { return uintStorage[REQUIRED_BLOCK_CONFIRMATIONS]; } function hashiManager() public view returns (IHashiManager) { return IHashiManager(addressStorage[HASHI_MANAGER]); } function setHashiManager(address _hashiManager) external onlyOwner { addressStorage[HASHI_MANAGER] = _hashiManager; } /** * @dev Internal function for updating fallback gas price value. * @param _gasPrice new value for the gas price, zero gas price is allowed. */ function _setGasPrice(uint256 _gasPrice) internal { uintStorage[GAS_PRICE] = _gasPrice; emit GasPriceChanged(_gasPrice); } function _setHashiApprovalForMessage(bytes32 hashMsg, bool status) internal { boolStorage[keccak256(abi.encodePacked("messagesApprovedByHashi", hashMsg))] = status; } function resendDataWithHashi(bytes data) external { require(boolStorage[keccak256(abi.encodePacked("dataSentWithHashi", data))]); _dispatchMessageWithHashi(data); } function _maybeSendDataWithHashi(bytes data) internal { if (HASHI_IS_ENABLED) { boolStorage[keccak256(abi.encodePacked("dataSentWithHashi", data))] = true; _dispatchMessageWithHashi(data); } } function _dispatchMessageWithHashi(bytes data) internal { IHashiManager manager = hashiManager(); IYaho(manager.yaho()).dispatchMessage( manager.targetChainId(), manager.threshold(), manager.targetAddress(), data, manager.reporters(), manager.adapters() ); } function _validateHashiMessage(uint256 chainId, uint256 threshold, address sender, address[] adapters) internal { IHashiManager manager = hashiManager(); require( HASHI_IS_ENABLED && msg.sender == manager.yaru() && chainId == manager.targetChainId() && sender == manager.targetAddress() && threshold == manager.expectedThreshold() && keccak256(abi.encodePacked(adapters)) == manager.expectedAdaptersHash() ); } }
pragma solidity 0.4.24; import "../libraries/Address.sol"; import "../libraries/SafeERC20.sol"; /** * @title Claimable * @dev Implementation of the claiming utils that can be useful for withdrawing accidentally sent tokens that are not used in bridge operations. */ contract Claimable { using SafeERC20 for address; /** * Throws if a given address is equal to address(0) */ modifier validAddress(address _to) { require(_to != address(0)); /* solcov ignore next */ _; } /** * @dev Withdraws the erc20 tokens or native coins from this contract. * Caller should additionally check that the claimed token is not a part of bridge operations (i.e. that token != erc20token()). * @param _token address of the claimed token or address(0) for native coins. * @param _to address of the tokens/coins receiver. */ function claimValues(address _token, address _to) internal validAddress(_to) { if (_token == address(0)) { claimNativeCoins(_to); } else { claimErc20Tokens(_token, _to); } } /** * @dev Internal function for withdrawing all native coins from the contract. * @param _to address of the coins receiver. */ function claimNativeCoins(address _to) internal { uint256 value = address(this).balance; Address.safeSendValue(_to, value); } /** * @dev Internal function for withdrawing all tokens of ssome particular ERC20 contract from this contract. * @param _token address of the claimed ERC20 token. * @param _to address of the tokens receiver. */ function claimErc20Tokens(address _token, address _to) internal { ERC20Basic token = ERC20Basic(_token); uint256 balance = token.balanceOf(this); _token.safeTransfer(_to, balance); } }
pragma solidity 0.4.24; import "../upgradeability/EternalStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; contract DecimalShiftBridge is EternalStorage { using SafeMath for uint256; bytes32 internal constant DECIMAL_SHIFT = 0x1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee5; // keccak256(abi.encodePacked("decimalShift")) /** * @dev Internal function for setting the decimal shift for bridge operations. * Decimal shift can be positive, negative, or equal to zero. * It has the following meaning: N tokens in the foreign chain are equivalent to N * pow(10, shift) tokens on the home side. * @param _shift new value of decimal shift. */ function _setDecimalShift(int256 _shift) internal { // since 1 wei * 10**77 > 2**255, it does not make any sense to use higher values require(_shift > -77 && _shift < 77); uintStorage[DECIMAL_SHIFT] = uint256(_shift); } /** * @dev Returns the value of foreign-to-home decimal shift. * @return decimal shift. */ function decimalShift() public view returns (int256) { return int256(uintStorage[DECIMAL_SHIFT]); } /** * @dev Converts the amount of home tokens into the equivalent amount of foreign tokens. * @param _value amount of home tokens. * @return equivalent amount of foreign tokens. */ function _unshiftValue(uint256 _value) internal view returns (uint256) { return _shiftUint(_value, -decimalShift()); } /** * @dev Converts the amount of foreign tokens into the equivalent amount of home tokens. * @param _value amount of foreign tokens. * @return equivalent amount of home tokens. */ function _shiftValue(uint256 _value) internal view returns (uint256) { return _shiftUint(_value, decimalShift()); } /** * @dev Calculates _value * pow(10, _shift). * @param _value amount of tokens. * @param _shift decimal shift to apply. * @return shifted value. */ function _shiftUint(uint256 _value, int256 _shift) private pure returns (uint256) { if (_shift == 0) { return _value; } if (_shift > 0) { return _value.mul(10**uint256(_shift)); } return _value.div(10**uint256(-_shift)); } }
pragma solidity 0.4.24; import "../upgradeability/EternalStorage.sol"; contract Initializable is EternalStorage { bytes32 internal constant INITIALIZED = 0x0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba; // keccak256(abi.encodePacked("isInitialized")) function setInitialize() internal { boolStorage[INITIALIZED] = true; } function isInitialized() public view returns (bool) { return boolStorage[INITIALIZED]; } }
pragma solidity 0.4.24; import "./Initializable.sol"; contract InitializableBridge is Initializable { bytes32 internal constant DEPLOYED_AT_BLOCK = 0xb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b0; // keccak256(abi.encodePacked("deployedAtBlock")) function deployedAtBlock() external view returns (uint256) { return uintStorage[DEPLOYED_AT_BLOCK]; } }
pragma solidity 0.4.24; import "../upgradeability/EternalStorage.sol"; contract MessageRelay is EternalStorage { function relayedMessages(bytes32 _txHash) public view returns (bool) { return boolStorage[keccak256(abi.encodePacked("relayedMessages", _txHash))]; } function setRelayedMessages(bytes32 _txHash, bool _status) internal { boolStorage[keccak256(abi.encodePacked("relayedMessages", _txHash))] = _status; } }
pragma solidity 0.4.24; import "../upgradeability/EternalStorage.sol"; import "../interfaces/IUpgradeabilityOwnerStorage.sol"; /** * @title Ownable * @dev This contract has an owner address providing basic authorization control */ contract Ownable is EternalStorage { bytes4 internal constant UPGRADEABILITY_OWNER = 0x6fde8202; // upgradeabilityOwner() /** * @dev Event to show ownership has been transferred * @param previousOwner representing the address of the previous owner * @param newOwner representing the address of the new owner */ event OwnershipTransferred(address previousOwner, address newOwner); /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner()); /* solcov ignore next */ _; } /** * @dev Throws if called by any account other than contract itself or owner. */ modifier onlyRelevantSender() { // proxy owner if used through proxy, address(0) otherwise require( !address(this).call(abi.encodeWithSelector(UPGRADEABILITY_OWNER)) || // covers usage without calling through storage proxy msg.sender == IUpgradeabilityOwnerStorage(this).upgradeabilityOwner() || // covers usage through regular proxy calls msg.sender == address(this) // covers calls through upgradeAndCall proxy method ); /* solcov ignore next */ _; } bytes32 internal constant OWNER = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; // keccak256(abi.encodePacked("owner")) /** * @dev Tells the address of the owner * @return the address of the owner */ function owner() public view returns (address) { return addressStorage[OWNER]; } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner the address to transfer ownership to. */ function transferOwnership(address newOwner) external onlyOwner { _setOwner(newOwner); } /** * @dev Sets a new owner address */ function _setOwner(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(owner(), newOwner); addressStorage[OWNER] = newOwner; } }
pragma solidity 0.4.24; contract Sacrifice { constructor(address _recipient) public payable { selfdestruct(_recipient); } }
pragma solidity 0.4.24; import "../interfaces/IUpgradeabilityOwnerStorage.sol"; contract Upgradeable { // Avoid using onlyUpgradeabilityOwner name to prevent issues with implementation from proxy contract modifier onlyIfUpgradeabilityOwner() { require(msg.sender == IUpgradeabilityOwnerStorage(this).upgradeabilityOwner()); /* solcov ignore next */ _; } }
pragma solidity 0.4.24; import "../interfaces/IBridgeValidators.sol"; import "../upgradeability/EternalStorage.sol"; import "./ValidatorStorage.sol"; contract Validatable is EternalStorage, ValidatorStorage { function validatorContract() public view returns (IBridgeValidators) { return IBridgeValidators(addressStorage[VALIDATOR_CONTRACT]); } modifier onlyValidator() { require(validatorContract().isValidator(msg.sender)); /* solcov ignore next */ _; } function requiredSignatures() public view returns (uint256) { return validatorContract().requiredSignatures(); } }
pragma solidity 0.4.24; contract ValidatorStorage { bytes32 internal constant VALIDATOR_CONTRACT = 0x5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe; // keccak256(abi.encodePacked("validatorContract")) }
pragma solidity 0.4.24; contract VersionableBridge { function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { return (6, 1, 0); } /* solcov ignore next */ function getBridgeMode() external pure returns (bytes4); }
pragma solidity ^0.4.24; /** * Utility library of inline functions on addresses */ library AddressUtils { /** * Returns whether the target address is a contract * @dev This function will return false if invoked during the constructor of a contract, * as the code is not actually created until after the constructor finishes. * @param _addr address to check * @return whether the target address is a contract */ function isContract(address _addr) internal view returns (bool) { uint256 size; // XXX Currently there is no better way to check if there is a contract in an address // than to check the size of the code at that address. // See https://ethereum.stackexchange.com/a/14016/36603 // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. // solium-disable-next-line security/no-inline-assembly assembly { size := extcodesize(_addr) } return size > 0; } }
pragma solidity ^0.4.24; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) { // Gas optimization: this is cheaper than asserting 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (_a == 0) { return 0; } c = _a * _b; assert(c / _a == _b); return c; } /** * @dev Integer division of two numbers, truncating the quotient. */ function div(uint256 _a, uint256 _b) internal pure returns (uint256) { // assert(_b > 0); // Solidity automatically throws when dividing by 0 // uint256 c = _a / _b; // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold return _a / _b; } /** * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { assert(_b <= _a); return _a - _b; } /** * @dev Adds two numbers, throws on overflow. */ function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) { c = _a + _b; assert(c >= _a); return c; } }
pragma solidity ^0.4.24; import "./ERC20Basic.sol"; /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 is ERC20Basic { function allowance(address _owner, address _spender) public view returns (uint256); function transferFrom(address _from, address _to, uint256 _value) public returns (bool); function approve(address _spender, uint256 _value) public returns (bool); event Approval( address indexed owner, address indexed spender, uint256 value ); }
pragma solidity ^0.4.24; /** * @title ERC20Basic * @dev Simpler version of ERC20 interface * See https://github.com/ethereum/EIPs/issues/179 */ contract ERC20Basic { function totalSupply() public view returns (uint256); function balanceOf(address _who) public view returns (uint256); function transfer(address _to, uint256 _value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); }
{ "optimizer": { "enabled": true, "runs": 100 }, "evmVersion": "byzantium", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":true,"inputs":[],"name":"transactionHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sourceChainId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"HASHI_IS_MANDATORY","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_txHash","type":"bytes32"}],"name":"relayedMessages","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_data","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"safeExecuteSignaturesWithAutoGasLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_sourceChainId","type":"uint256"},{"name":"_destinationChainId","type":"uint256"},{"name":"_validatorContract","type":"address"},{"name":"_maxGasPerTx","type":"uint256"},{"name":"_gasPrice","type":"uint256"},{"name":"_requiredBlockConfirmations","type":"uint256"},{"name":"_owner","type":"address"}],"name":"initialize","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requiredBlockConfirmations","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_data","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"executeSignatures","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_messageId","type":"bytes32"}],"name":"failedMessageReceiver","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBridgeMode","outputs":[{"name":"_data","type":"bytes4"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_sourceChainId","type":"uint256"},{"name":"_destinationChainId","type":"uint256"}],"name":"setChainIds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_messageId","type":"bytes32"}],"name":"failedMessageSender","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allowReentrantRequests","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"messageId","outputs":[{"name":"id","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_to","type":"address"}],"name":"claimTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"data","type":"bytes"}],"name":"resendDataWithHashi","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxGasPerTx","type":"uint256"}],"name":"setMaxGasPerTx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hashiManager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"HASHI_IS_ENABLED","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requiredSignatures","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"hashMsg","type":"bytes32"}],"name":"isApprovedByHashi","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"validatorContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"deployedAtBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBridgeInterfacesVersion","outputs":[{"name":"major","type":"uint64"},{"name":"minor","type":"uint64"},{"name":"patch","type":"uint64"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"messageSourceChainId","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_blockConfirmations","type":"uint256"}],"name":"setRequiredBlockConfirmations","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"destinationChainId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_hashiManager","type":"address"}],"name":"setHashiManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_gasPrice","type":"uint256"}],"name":"setGasPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_enable","type":"bool"}],"name":"setAllowReentrantRequests","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_messageId","type":"bytes32"}],"name":"messageCallStatus","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"","type":"uint256"},{"name":"chainId","type":"uint256"},{"name":"sender","type":"address"},{"name":"threshold","type":"uint256"},{"name":"adapters","type":"address[]"},{"name":"data","type":"bytes"}],"name":"onMessage","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"messageSender","outputs":[{"name":"sender","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimalShift","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_contract","type":"address"},{"name":"_data","type":"bytes"},{"name":"_gas","type":"uint256"}],"name":"requireToPassMessage","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_messageId","type":"bytes32"}],"name":"failedMessageDataHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxGasPerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_data","type":"bytes"},{"name":"_signatures","type":"bytes"},{"name":"_gas","type":"uint32"}],"name":"safeExecuteSignaturesWithGasLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_data","type":"bytes"},{"name":"_signatures","type":"bytes"}],"name":"safeExecuteSignatures","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"gasPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"messageId","type":"bytes32"},{"indexed":false,"name":"encodedData","type":"bytes"}],"name":"UserRequestForAffirmation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":true,"name":"executor","type":"address"},{"indexed":true,"name":"messageId","type":"bytes32"},{"indexed":false,"name":"status","type":"bool"}],"name":"RelayedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"gasPrice","type":"uint256"}],"name":"GasPriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"requiredBlockConfirmations","type":"uint256"}],"name":"RequiredBlockConfirmationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousOwner","type":"address"},{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
Contract Creation Code
608060405234801561001057600080fd5b50613ebe806100206000396000f3006080604052600436106101f55763ffffffff60e060020a6000350416630ac1c31381146101fa5780631544298e146102215780631ded84681461023657806321d800ec1461025f57806323caab491461027757806325fbf4ee146102a5578063392e53cd146102de5780633f0a9f65146102f35780633f7658fd146103085780633f9a8e7e1461039f578063437764df146103d3578063467ad35a146104055780634a610b04146104205780634d4cb7a214610438578063669f618b1461044d57806369ffa08a14610462578063785b15d5146104895780637bac29c7146104a95780637ea5f8d4146104c15780638b94e255146104d65780638d068043146104eb5780638da5cb5b146105005780638dc8cf8714610515578063994390891461052d5780639a454b99146105425780639cb7595a146105575780639e307dff14610598578063acf5c689146105ad578063b0750611146105c5578063bec9fa7c146105da578063bf1fe420146105fb578063c2231ad214610613578063cb08a10c1461062d578063d496af2414610645578063d67bdd25146106ff578063dae5f0fd14610714578063dc8601b314610729578063e37c328914610792578063e5789d03146107aa578063e6d562a1146107bf578063eaa820d71461085e578063f2fde38b1461088a578063fe173b97146108ab575b600080fd5b34801561020657600080fd5b5061020f6108c0565b60408051918252519081900360200190f35b34801561022d57600080fd5b5061020f6108cf565b34801561024257600080fd5b5061024b61091d565b604080519115158252519081900360200190f35b34801561026b57600080fd5b5061024b600435610922565b34801561028357600080fd5b506102a360246004803582810192908201359181359182019101356109eb565b005b3480156102b157600080fd5b5061024b600435602435600160a060020a03604435811690606435906084359060a4359060c43516610a5e565b3480156102ea57600080fd5b5061024b610ca1565b3480156102ff57600080fd5b5061020f610cf2565b34801561031457600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102a394369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610d409650505050505050565b3480156103ab57600080fd5b506103b7600435610e5e565b60408051600160a060020a039092168252519081900360200190f35b3480156103df57600080fd5b506103e8610f2d565b60408051600160e060020a03199092168252519081900360200190f35b34801561041157600080fd5b506102a3600435602435610f51565b34801561042c57600080fd5b506103b7600435610f7b565b34801561044457600080fd5b5061024b610fff565b34801561045957600080fd5b5061020f611050565b34801561046e57600080fd5b506102a3600160a060020a0360043581169060243516611075565b34801561049557600080fd5b506102a360048035602481019101356110fd565b3480156104b557600080fd5b506102a3600435611203565b3480156104cd57600080fd5b506103b7611248565b3480156104e257600080fd5b5061024b61129f565b3480156104f757600080fd5b5061020f6112a4565b34801561050c57600080fd5b506103b761131c565b34801561052157600080fd5b5061024b600435611373565b34801561053957600080fd5b506103b76113f7565b34801561054e57600080fd5b5061020f61144e565b34801561056357600080fd5b5061056c61149c565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b3480156105a457600080fd5b5061020f6114a7565b3480156105b957600080fd5b506102a36004356114cc565b3480156105d157600080fd5b5061020f6114f4565b3480156105e657600080fd5b506102a3600160a060020a0360043516611542565b34801561060757600080fd5b506102a36004356115c8565b34801561061f57600080fd5b506102a360043515156115ed565b34801561063957600080fd5b5061024b600435611664565b34801561065157600080fd5b5061068a60048035906024803591600160a060020a0360443516916064359160843580830192908201359160a4359182019101356116e8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156106c45781810151838201526020016106ac565b50505050905090810190601f1680156106f15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561070b57600080fd5b506103b76117d5565b34801561072057600080fd5b5061020f6117fa565b34801561073557600080fd5b5060408051602060046024803582810135601f810185900485028601850190965285855261020f958335600160a060020a031695369560449491939091019190819084018382808284375094975050933594506118489350505050565b34801561079e57600080fd5b5061020f60043561185f565b3480156107b657600080fd5b5061020f611924565b3480156107cb57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102a394369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497505050923563ffffffff16935061194e92505050565b34801561086a57600080fd5b506102a36024600480358281019290820135918135918201910135611a5f565b34801561089657600080fd5b506102a3600160a060020a0360043516611ac6565b3480156108b757600080fd5b5061020f611aeb565b60006108ca611050565b905090565b7f67d6f42a1ed69c62022f2d160ddc6f2f0acd37ad1db0c24f4702d7d3343a4add60009081526020527ff6c66672b1a9fe5622677597b0da8fd180a2c85696efbcf7fe4b1e0f4f0f61085490565b600081565b6000600460008360405160200180807f72656c617965644d657373616765730000000000000000000000000000000000815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106109a75780518252601f199092019160209182019101610988565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b610a5884848080601f0160208091040260200160405190810160405280939291908181526020018383808284375050604080516020601f8a01819004810282018101909252888152945088935087925082915084018382808284375063ffffffff945061194e9350505050565b50505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f6fde8202000000000000000000000000000000000000000000000000000000001781529151815160009330939291829190808383895b83811015610adf578181015183820152602001610ac7565b50505050905090810190601f168015610b0c5780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af19150501580610b9e575030600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610b6657600080fd5b505af1158015610b7a573d6000803e3d6000fd5b505050506040513d6020811015610b9057600080fd5b5051600160a060020a031633145b80610ba857503330145b1515610bb357600080fd5b610bbb610ca1565b15610bc557600080fd5b610bce86611b39565b1515610bd957600080fd5b610be38888611b41565b7fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e08054600160a060020a031916600160a060020a03881617905560006020819052437fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b55600080516020613e738339815191529052600080516020613e53833981519152859055610c7384611c91565b610c7c83611ca7565b610c8582611d3a565b610c8d611e04565b610c95610ca1565b98975050505050505050565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc5460ff1690565b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d7940723007160009081526020527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e425490565b6000806000806000610d50613e07565b6060610d5c8989611e5b565b610d6589611e83565b809750819850829950839a50849b50859c50869d5050505050505050610e53896040516020018082805190602001908083835b60208310610db75780518252601f199092019160209182019101610d98565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310610e1a5780518252601f199092019160209182019101610dfb565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902088888888888888611f2e565b505050505050505050565b6000600260008360405160200180807f6661696c65644d6573736167655265636569766572000000000000000000000081525060150182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310610ee35780518252601f199092019160209182019101610ec4565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031695945050505050565b7f2544fbb90000000000000000000000000000000000000000000000000000000090565b610f5961131c565b600160a060020a03163314610f6d57600080fd5b610f778282611b41565b5050565b6000600260008360405160200180807f6661696c65644d65737361676553656e64657200000000000000000000000000815250601301826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310610ee35780518252601f199092019160209182019101610ec4565b7fffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd660005260046020527f265a43ea29ede07170a30cb6d77d0ab5810eee752b72432f7be348bde74aa08f5460ff1690565b7fe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe650833045490565b30600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156110b357600080fd5b505af11580156110c7573d6000803e3d6000fd5b505050506040513d60208110156110dd57600080fd5b5051600160a060020a031633146110f357600080fd5b610f778282611f9f565b60046000838360405160200180807f6461746153656e745769746848617368690000000000000000000000000000008152506011018383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b6020831061117f5780518252601f199092019160209182019101611160565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff16151592506111ca91505057600080fd5b610f7782828080601f01602080910402602001604051908101604052809392919081815260200183838082843750611fe2945050505050565b61120b61131c565b600160a060020a0316331461121f57600080fd5b600080516020613e738339815191526000908152602052600080516020613e5383398151915255565b7f660d8ed18395a9aa930e304e0bb5e6e51957af1fa215b11db48bfda3dd38d51160005260026020527fb1578d368dec034f5de4adb7567061a469e92e7039fd319ab435573139ccbcc654600160a060020a031690565b600181565b60006112ae6113f7565b600160a060020a0316638d0680436040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156112eb57600080fd5b505af11580156112ff573d6000803e3d6000fd5b505050506040513d602081101561131557600080fd5b5051905090565b7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e54600160a060020a031690565b6000600460008360405160200180807f6d65737361676573417070726f766564427948617368690000000000000000008152506017018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106109a75780518252601f199092019160209182019101610988565b7f5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe60005260026020527fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e054600160a060020a031690565b7fb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b060009081526020527fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b5490565b600660026000909192565b7f7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d25490565b6114d461131c565b600160a060020a031633146114e857600080fd5b6114f181611ca7565b50565b7fbbd454018e72a3f6c02bbd785bacc49e46292744f3f6761276723823aa33232060009081526020527f242329173dfc316001df0a0c3d5a8f58a7ffb1a8b7d99c268303b9a741bacdf95490565b61154a61131c565b600160a060020a0316331461155e57600080fd5b7f660d8ed18395a9aa930e304e0bb5e6e51957af1fa215b11db48bfda3dd38d51160005260026020527fb1578d368dec034f5de4adb7567061a469e92e7039fd319ab435573139ccbcc68054600160a060020a031916600160a060020a0392909216919091179055565b6115d061131c565b600160a060020a031633146115e457600080fd5b6114f181611c91565b6115f561131c565b600160a060020a0316331461160957600080fd5b7fffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd660005260046020527f265a43ea29ede07170a30cb6d77d0ab5810eee752b72432f7be348bde74aa08f805460ff1916911515919091179055565b6000600460008360405160200180807f6d65737361676543616c6c5374617475730000000000000000000000000000008152506011018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106109a75780518252601f199092019160209182019101610988565b6060600061172589888a89898080602002602001604051908101604052809392919081815260200183836020028082843750612519945050505050565b8383604051602001808383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b6020831061177b5780518252601f19909201916020918201910161175c565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902090506117b381611373565b156117bd57600080fd5b6117c8816001612832565b5098975050505050505050565b7f7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b5490565b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d5490565b60006118578484846000612904565b949350505050565b60008060008360405160200180807f6661696c65644d6573736167654461746148617368000000000000000000000081525060150182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106118e35780518252601f1990920191602091820191016118c4565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205495945050505050565b600080516020613e738339815191526000908152602052600080516020613e538339815191525490565b60008060008061195c613e07565b60606119688989611e5b565b61197189611e83565b90919250809650819750829850839950849a50859b50505050505050610e53896040516020018082805190602001908083835b602083106119c35780518252601f1990920191602091820191016119a4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310611a265780518252601f199092019160209182019101611a07565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390208787878b888888611f2e565b610a5884848080601f0160208091040260200160405190810160405280939291908181526020018383808284375050604080516020601f8a018190048102820181019092528881529450889350879250829150840183828082843750610d40945050505050565b611ace61131c565b600160a060020a03163314611ae257600080fd5b6114f181611d3a565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b60009081526020527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944195490565b6000903b1190565b600080600080600086118015611b575750600085115b1515611b6257600080fd5b85851415611b6f57600080fd5b506000925082915060ff905060015b831580611b89575082155b15611bd15783158015611b9d575085828716145b15611ba6578093505b82158015611bb5575084828616145b15611bbe578092505b6101009190910260ff1790600101611b7e565b5050600060208190527ff6c66672b1a9fe5622677597b0da8fd180a2c85696efbcf7fe4b1e0f4f0f6108949094557f2f30286a16f86ee067618e1a246990e40c07b7749418a6dd3133f9cfb7e814cc919091557f242329173dfc316001df0a0c3d5a8f58a7ffb1a8b7d99c268303b9a741bacdf9919091557ffb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d49896928115949091527f7b62b32ff48350e85ce95b571fde6f8b1096bc44a26db769ad6d0b3a26bf1c6d55565b60008111611c9e57600080fd5b6114f181612a93565b60008111611cb457600080fd5b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071600090815260209081527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e428290556040805183815290517f4fb76205cd57c896b21511d2114137d8e901b4ccd659e1a0f97d6306795264fb929181900390910190a150565b600160a060020a0381161515611d4f57600080fd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0611d7861131c565b60408051600160a060020a03928316815291841660208301528051918290030190a17f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e8054600160a060020a031916600160a060020a0392909216919091179055565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc805460ff19166001179055565b6000611e65611050565b14611e6f57600080fd5b610f778282611e7c6113f7565b6001612b19565b6000806000806000611e93613e07565b6060600080604f915060208a01519850600160a060020a0360348b015116975060548a01518060601c975063ffffffff8160401c16965080601a1a95508060181a6001808260031b1b03818501945080858e01511687528260191a91506001808360031b1b039050818501945080858e0151166020880152848d51039350505050611f1f8a8383612da3565b92505050919395979092949650565b611f3787612e28565b1515611f4257600080fd5b6020820151611f5090612e41565b1515611f5b57600080fd5b611f6487610922565b15611f6e57600080fd5b611f79876001612e53565b611f9586868963ffffffff881687876000602002015187612ed6565b5050505050505050565b80600160a060020a0381161515611fb557600080fd5b600160a060020a0383161515611fd357611fce82612f23565b611fdd565b611fdd8383612f2f565b505050565b6000611fec611248565b905080600160a060020a031663ee4937ba6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561202c57600080fd5b505af1158015612040573d6000803e3d6000fd5b505050506040513d602081101561205657600080fd5b5051604080517f146ffb260000000000000000000000000000000000000000000000000000000081529051600160a060020a03928316926339d0bf63929085169163146ffb26916004808201926020929091908290030181600087803b1580156120bf57600080fd5b505af11580156120d3573d6000803e3d6000fd5b505050506040513d60208110156120e957600080fd5b5051604080517f42cde4e80000000000000000000000000000000000000000000000000000000081529051600160a060020a038616916342cde4e89160048083019260209291908290030181600087803b15801561214657600080fd5b505af115801561215a573d6000803e3d6000fd5b505050506040513d602081101561217057600080fd5b5051604080517f5210eb560000000000000000000000000000000000000000000000000000000081529051600160a060020a03871691635210eb569160048083019260209291908290030181600087803b1580156121cd57600080fd5b505af11580156121e1573d6000803e3d6000fd5b505050506040513d60208110156121f757600080fd5b5051604080517ff144d48600000000000000000000000000000000000000000000000000000000815290518891600160a060020a0389169163f144d4869160048082019260009290919082900301818387803b15801561225657600080fd5b505af115801561226a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561229357600080fd5b8101908080516401000000008111156122ab57600080fd5b820160208101848111156122be57600080fd5b81518560208202830111640100000000821117156122db57600080fd5b505092919050505087600160a060020a0316636b6e93d56040518163ffffffff1660e060020a028152600401600060405180830381600087803b15801561232157600080fd5b505af1158015612335573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561235e57600080fd5b81019080805164010000000081111561237657600080fd5b8201602081018481111561238957600080fd5b81518560208202830111640100000000821117156123a657600080fd5b505060405160e060020a63ffffffff8c16028152600481018a8152602482018a9052600160a060020a038916604483015260c060648301908152885160c484015288519396509094509250608481019160a482019160e40190602089019080838360005b8381101561242257818101518382015260200161240a565b50505050905090810190601f16801561244f5780820380516001836020036101000a031916815260200191505b508481038352865181528651602091820191808901910280838360005b8381101561248457818101518382015260200161246c565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156124c35781810151838201526020016124ab565b505050509050019950505050505050505050602060405180830381600087803b1580156124ef57600080fd5b505af1158015612503573d6000803e3d6000fd5b505050506040513d6020811015610a5857600080fd5b6000612523611248565b905080600160a060020a031663789b11d76040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561256357600080fd5b505af1158015612577573d6000803e3d6000fd5b505050506040513d602081101561258d57600080fd5b5051600160a060020a03163314801561260e575080600160a060020a031663146ffb266040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156125df57600080fd5b505af11580156125f3573d6000803e3d6000fd5b505050506040513d602081101561260957600080fd5b505185145b801561268e575080600160a060020a0316635210eb566040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561265357600080fd5b505af1158015612667573d6000803e3d6000fd5b505050506040513d602081101561267d57600080fd5b5051600160a060020a038481169116145b8015612702575080600160a060020a0316632690ff8b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156126d357600080fd5b505af11580156126e7573d6000803e3d6000fd5b505050506040513d60208110156126fd57600080fd5b505184145b8015612820575080600160a060020a031663f238ca266040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561274757600080fd5b505af115801561275b573d6000803e3d6000fd5b505050506040513d602081101561277157600080fd5b5051604051835184916020908101918291848101910280838360005b838110156127a557818101518382015260200161278d565b505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106127ed5780518252601f1990920191602091820191016127ce565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b151561282b57600080fd5b5050505050565b80600460008460405160200180807f6d65737361676573417070726f7665644279486173686900000000000000000081525060170182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106128b65780518252601f199092019160209182019101612897565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff1916941515949094179093555050505050565b6000808060608082612914611050565b14806129235750612923610fff565b151561292e57600080fd5b606487101580156129465750612942611924565b8711155b151561295157600080fd5b63ffffffff60048901511693508363a9059cbb1415801561297657508363095ea7b314155b80156129865750836323b872dd14155b8015612996575083634000aea014155b80156129a657508363cae9ca5114155b15156129b157600080fd5b6129bc898888612fdc565b9250925081886040516020018083805190602001908083835b602083106129f45780518252601f1990920191602091820191016129d5565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310612a3c5780518252601f199092019160209182019101612a1d565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529050612a7d8382613092565b612a868161312f565b5090979650505050505050565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b600090815260209081527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944198290556040805183815290517f52264b89e0fceafb26e79fd49ef8a366eb6297483bf4035b027f0c99a7ad512e929181900390910190a150565b6000806000606060008060008060008060008b80612b3b5750612b3b8f613248565b1515612b4657600080fd5b8c600160a060020a0316638d0680436040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612b8457600080fd5b505af1158015612b98573d6000803e3d6000fd5b505050506040513d6020811015612bae57600080fd5b505160018f0151909b5060ff1699508a8a1015612bca57600080fd5b612bd48f8d61325c565b98508a604051908082528060200260200182016040528015612c00578160200160208202803883390190505b509750600096505b8a871015612d9257866020028a6021010192508960200283019150866002018e01519550828e01519450818e01519350600189878787604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015612caf573d6000803e3d6000fd5b5050506020604051035190508c600160a060020a031663facd743b826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015612d1657600080fd5b505af1158015612d2a573d6000803e3d6000fd5b505050506040513d6020811015612d4057600080fd5b50511515612d4d57600080fd5b612d578882613476565b15612d6157600080fd5b808888815181101515612d7057fe5b600160a060020a03909216602092830290910190910152600190960195612c08565b505050505050505050505050505050565b606080828401855110151515612db857600080fd5b82158015612dd55760405191506000825260208201604052612e1f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612e0e578051835260209283019201612df6565b5050858452601f01601f1916604052505b50949350505050565b600160e060020a0319811660f060020a60050214919050565b6000612e4b6108cf565b909114919050565b80600460008460405160200180807f72656c617965644d657373616765730000000000000000000000000000000000815250600f018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106128b65780518252601f199092019160209182019101612897565b6000612ee6888884888a886134d1565b9050612ef286826135c7565b801515612f1757612f03868361364a565b612f0d8688613759565b612f17868961383a565b611f95888888846138bd565b3031610f77828261390b565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b158015612f9457600080fd5b505af1158015612fa8573d6000803e3d6000fd5b505050506040513d6020811015612fbe57600080fd5b50519050610a58600160a060020a038516848363ffffffff61396c16565b60006060600080600080612fee6108cf565b9350612ff8613a01565b92506130026114f4565b915061300c613a4f565b905061301784613a9d565b95508083604f01016040519080825280601f01601f19166020018201604052801561304c578160200160208202803883390190505b50945084518501828152848282035287604f87015281604e87015283604d87015288604c8701528960488701523360348701528660208701525050505050935093915050565b604080516020808252835181830152835185937f482515ce3d9494a37ce83f18b72b363449458435fafdd7a53ddea7460fe01b589386939092839283019185019080838360005b838110156130f15781810151838201526020016130d9565b50505050905090810190601f16801561311e5780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b6001600460008360405160200180807f6461746153656e7457697468486173686900000000000000000000000000000081525060110182805190602001908083835b602083106131905780518252601f199092019160209182019101613171565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106131f35780518252601f1990920191602091820191016131d4565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff191694151594909417909355506114f19150829050611fe2565b6000613252613b88565b8251149050919050565b60408051808201909152601a81527f19457468657265756d205369676e6564204d6573736167653a0a00000000000060208201526000906060831561340257816132a68651613b8d565b866040516020018084805190602001908083835b602083106132d95780518252601f1990920191602091820191016132ba565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106133215780518252601f199092019160209182019101613302565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106133695780518252601f19909201916020918201910161334a565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b602083106133ce5780518252601f1990920191602091820191016133af565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020925061346e565b6040805190810160405280600381526020017f31303400000000000000000000000000000000000000000000000000000000008152509050818186604051602001808480519060200190808383602083106132d95780518252601f1990920191602091820191016132ba565b505092915050565b6000805b83518110156134c55782600160a060020a0316848281518110151561349b57fe5b90602001906020020151600160a060020a031614156134bd57600191506134ca565b60010161347a565b600091505b5092915050565b6000806134dd88613cb4565b6134e684613cd8565b6134ef83613cfc565b8463ffffffff148061350f57508460405a603f0281151561350c57fe5b04115b151561351a57600080fd5b86600160a060020a0316858760405180828051906020019080838360005b83811015613550578181015183820152602001613538565b50505050905090810190601f16801561357d5780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008787f192505050905061359e81613d20565b6135a86000613cb4565b6135b26000613cd8565b6135bc6000613cfc565b979650505050505050565b80600460008460405160200180807f6d65737361676543616c6c5374617475730000000000000000000000000000008152506011018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106128b65780518252601f199092019160209182019101612897565b806040518082805190602001908083835b6020831061367a5780518252601f19909201916020918201910161365b565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207f6661696c65644d657373616765446174614861736800000000000000000000008383015260358084018a905285518085039091018152605590930194859052825190965060009550859492935082918401908083835b602083106137175780518252601f1990920191602091820191016136f8565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b80600260008460405160200180807f6661696c65644d6573736167655265636569766572000000000000000000000081525060150182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106137dd5780518252601f1990920191602091820191016137be565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000208054600160a060020a031916600160a060020a0395909516949094179093555050505050565b80600260008460405160200180807f6661696c65644d65737361676553656e646572000000000000000000000000008152506013018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106137dd5780518252601f1990920191602091820191016137be565b60408051821515815290518391600160a060020a0380871692908816917f27333edb8bdcd40a0ae944fb121b5e2d62ea782683946654a0f5e607a908d578919081900360200190a450505050565b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610f77578082613940613e22565b600160a060020a039091168152604051908190036020019082f08015801561282b573d6000803e3d6000fd5b82600160a060020a031663a9059cbb83836040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b1580156139cf57600080fd5b505af11580156139e3573d6000803e3d6000fd5b505050503d15611fdd5760206000803e6000511515611fdd57600080fd5b7fe504ae1fd6471eea80f18b8532a61a9bb91fba4f5b837f80a1cfb6752350af4460009081526020527f2f30286a16f86ee067618e1a246990e40c07b7749418a6dd3133f9cfb7e814cc5490565b7ffb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d498969281159460009081526020527f7b62b32ff48350e85ce95b571fde6f8b1096bc44a26db769ad6d0b3a26bf1c6d5490565b6000806000613aaa613d62565b9150613ab882600101613db0565b6040805160208082018790526c0100000000000000000000000030028284015282516034818403018152605490920192839052815191929182918401908083835b60208310613b185780518252601f199092019160209182019101613af9565b5181516000196020949094036101000a93909301928316921916919091179052604051920182900390912067ffffffffffffffff86167bffffffffffffffffffffffffffffffffffffffff000000000000000090911690811760f060020a60050217965093505050505050919050565b606890565b60606000808281851515613bd65760408051808201909152600181527f300000000000000000000000000000000000000000000000000000000000000060208201529450613cab565b8593505b8315613bf157600190920191600a84049350613bda565b826040519080825280601f01601f191660200182016040528015613c1f578160200160208202803883390190505b5091505060001982015b8515613ca75781516000198201917f01000000000000000000000000000000000000000000000000000000000000006030600a8a060102918491908110613c6c57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a86049550613c29565b8194505b50505050919050565b7f7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b55565b7fe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe6508330455565b7f7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d255565b8080613d575750600035600160e060020a0319167f3f7658fd00000000000000000000000000000000000000000000000000000000145b15156114f157600080fd5b7f7ab1577440dd7bedf920cb6de2f9fc6bf7ba98c78c85a3fa1f8311aac95e175960009081526020527fa9b0f75b23e377b9b22d27feaca5d8a12329c0049ebce1dc695b905f3aa4cd005490565b7f7ab1577440dd7bedf920cb6de2f9fc6bf7ba98c78c85a3fa1f8311aac95e1759600090815260205267ffffffffffffffff167fa9b0f75b23e377b9b22d27feaca5d8a12329c0049ebce1dc695b905f3aa4cd0055565b60408051808201825290600290829080388339509192915050565b604051602180613e32833901905600608060405260405160208060218339810160405251600160a060020a038116ff003d7fe2ee9790702383ef0118b516833ef2542132d3ca4ac6c77f62f1230fa6102670ecc91ec356e32067fd27b36614132d727b84a1e03e08f412a4f2cf075974a165627a7a723058200463515421c3b0bab34d82cbed259998e8a7fd15b8c8cc2be9a00feaa599fd250029
Deployed Bytecode
0x6080604052600436106101f55763ffffffff60e060020a6000350416630ac1c31381146101fa5780631544298e146102215780631ded84681461023657806321d800ec1461025f57806323caab491461027757806325fbf4ee146102a5578063392e53cd146102de5780633f0a9f65146102f35780633f7658fd146103085780633f9a8e7e1461039f578063437764df146103d3578063467ad35a146104055780634a610b04146104205780634d4cb7a214610438578063669f618b1461044d57806369ffa08a14610462578063785b15d5146104895780637bac29c7146104a95780637ea5f8d4146104c15780638b94e255146104d65780638d068043146104eb5780638da5cb5b146105005780638dc8cf8714610515578063994390891461052d5780639a454b99146105425780639cb7595a146105575780639e307dff14610598578063acf5c689146105ad578063b0750611146105c5578063bec9fa7c146105da578063bf1fe420146105fb578063c2231ad214610613578063cb08a10c1461062d578063d496af2414610645578063d67bdd25146106ff578063dae5f0fd14610714578063dc8601b314610729578063e37c328914610792578063e5789d03146107aa578063e6d562a1146107bf578063eaa820d71461085e578063f2fde38b1461088a578063fe173b97146108ab575b600080fd5b34801561020657600080fd5b5061020f6108c0565b60408051918252519081900360200190f35b34801561022d57600080fd5b5061020f6108cf565b34801561024257600080fd5b5061024b61091d565b604080519115158252519081900360200190f35b34801561026b57600080fd5b5061024b600435610922565b34801561028357600080fd5b506102a360246004803582810192908201359181359182019101356109eb565b005b3480156102b157600080fd5b5061024b600435602435600160a060020a03604435811690606435906084359060a4359060c43516610a5e565b3480156102ea57600080fd5b5061024b610ca1565b3480156102ff57600080fd5b5061020f610cf2565b34801561031457600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102a394369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750610d409650505050505050565b3480156103ab57600080fd5b506103b7600435610e5e565b60408051600160a060020a039092168252519081900360200190f35b3480156103df57600080fd5b506103e8610f2d565b60408051600160e060020a03199092168252519081900360200190f35b34801561041157600080fd5b506102a3600435602435610f51565b34801561042c57600080fd5b506103b7600435610f7b565b34801561044457600080fd5b5061024b610fff565b34801561045957600080fd5b5061020f611050565b34801561046e57600080fd5b506102a3600160a060020a0360043581169060243516611075565b34801561049557600080fd5b506102a360048035602481019101356110fd565b3480156104b557600080fd5b506102a3600435611203565b3480156104cd57600080fd5b506103b7611248565b3480156104e257600080fd5b5061024b61129f565b3480156104f757600080fd5b5061020f6112a4565b34801561050c57600080fd5b506103b761131c565b34801561052157600080fd5b5061024b600435611373565b34801561053957600080fd5b506103b76113f7565b34801561054e57600080fd5b5061020f61144e565b34801561056357600080fd5b5061056c61149c565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b3480156105a457600080fd5b5061020f6114a7565b3480156105b957600080fd5b506102a36004356114cc565b3480156105d157600080fd5b5061020f6114f4565b3480156105e657600080fd5b506102a3600160a060020a0360043516611542565b34801561060757600080fd5b506102a36004356115c8565b34801561061f57600080fd5b506102a360043515156115ed565b34801561063957600080fd5b5061024b600435611664565b34801561065157600080fd5b5061068a60048035906024803591600160a060020a0360443516916064359160843580830192908201359160a4359182019101356116e8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156106c45781810151838201526020016106ac565b50505050905090810190601f1680156106f15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561070b57600080fd5b506103b76117d5565b34801561072057600080fd5b5061020f6117fa565b34801561073557600080fd5b5060408051602060046024803582810135601f810185900485028601850190965285855261020f958335600160a060020a031695369560449491939091019190819084018382808284375094975050933594506118489350505050565b34801561079e57600080fd5b5061020f60043561185f565b3480156107b657600080fd5b5061020f611924565b3480156107cb57600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526102a394369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497505050923563ffffffff16935061194e92505050565b34801561086a57600080fd5b506102a36024600480358281019290820135918135918201910135611a5f565b34801561089657600080fd5b506102a3600160a060020a0360043516611ac6565b3480156108b757600080fd5b5061020f611aeb565b60006108ca611050565b905090565b7f67d6f42a1ed69c62022f2d160ddc6f2f0acd37ad1db0c24f4702d7d3343a4add60009081526020527ff6c66672b1a9fe5622677597b0da8fd180a2c85696efbcf7fe4b1e0f4f0f61085490565b600081565b6000600460008360405160200180807f72656c617965644d657373616765730000000000000000000000000000000000815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106109a75780518252601f199092019160209182019101610988565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b610a5884848080601f0160208091040260200160405190810160405280939291908181526020018383808284375050604080516020601f8a01819004810282018101909252888152945088935087925082915084018382808284375063ffffffff945061194e9350505050565b50505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f6fde8202000000000000000000000000000000000000000000000000000000001781529151815160009330939291829190808383895b83811015610adf578181015183820152602001610ac7565b50505050905090810190601f168015610b0c5780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af19150501580610b9e575030600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610b6657600080fd5b505af1158015610b7a573d6000803e3d6000fd5b505050506040513d6020811015610b9057600080fd5b5051600160a060020a031633145b80610ba857503330145b1515610bb357600080fd5b610bbb610ca1565b15610bc557600080fd5b610bce86611b39565b1515610bd957600080fd5b610be38888611b41565b7fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e08054600160a060020a031916600160a060020a03881617905560006020819052437fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b55600080516020613e738339815191529052600080516020613e53833981519152859055610c7384611c91565b610c7c83611ca7565b610c8582611d3a565b610c8d611e04565b610c95610ca1565b98975050505050505050565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc5460ff1690565b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d7940723007160009081526020527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e425490565b6000806000806000610d50613e07565b6060610d5c8989611e5b565b610d6589611e83565b809750819850829950839a50849b50859c50869d5050505050505050610e53896040516020018082805190602001908083835b60208310610db75780518252601f199092019160209182019101610d98565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310610e1a5780518252601f199092019160209182019101610dfb565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902088888888888888611f2e565b505050505050505050565b6000600260008360405160200180807f6661696c65644d6573736167655265636569766572000000000000000000000081525060150182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310610ee35780518252601f199092019160209182019101610ec4565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031695945050505050565b7f2544fbb90000000000000000000000000000000000000000000000000000000090565b610f5961131c565b600160a060020a03163314610f6d57600080fd5b610f778282611b41565b5050565b6000600260008360405160200180807f6661696c65644d65737361676553656e64657200000000000000000000000000815250601301826000191660001916815260200191505060405160208183030381529060405260405180828051906020019080838360208310610ee35780518252601f199092019160209182019101610ec4565b7fffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd660005260046020527f265a43ea29ede07170a30cb6d77d0ab5810eee752b72432f7be348bde74aa08f5460ff1690565b7fe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe650833045490565b30600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156110b357600080fd5b505af11580156110c7573d6000803e3d6000fd5b505050506040513d60208110156110dd57600080fd5b5051600160a060020a031633146110f357600080fd5b610f778282611f9f565b60046000838360405160200180807f6461746153656e745769746848617368690000000000000000000000000000008152506011018383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b6020831061117f5780518252601f199092019160209182019101611160565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff16151592506111ca91505057600080fd5b610f7782828080601f01602080910402602001604051908101604052809392919081815260200183838082843750611fe2945050505050565b61120b61131c565b600160a060020a0316331461121f57600080fd5b600080516020613e738339815191526000908152602052600080516020613e5383398151915255565b7f660d8ed18395a9aa930e304e0bb5e6e51957af1fa215b11db48bfda3dd38d51160005260026020527fb1578d368dec034f5de4adb7567061a469e92e7039fd319ab435573139ccbcc654600160a060020a031690565b600181565b60006112ae6113f7565b600160a060020a0316638d0680436040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156112eb57600080fd5b505af11580156112ff573d6000803e3d6000fd5b505050506040513d602081101561131557600080fd5b5051905090565b7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e54600160a060020a031690565b6000600460008360405160200180807f6d65737361676573417070726f766564427948617368690000000000000000008152506017018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106109a75780518252601f199092019160209182019101610988565b7f5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe60005260026020527fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e054600160a060020a031690565b7fb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b060009081526020527fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b5490565b600660026000909192565b7f7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d25490565b6114d461131c565b600160a060020a031633146114e857600080fd5b6114f181611ca7565b50565b7fbbd454018e72a3f6c02bbd785bacc49e46292744f3f6761276723823aa33232060009081526020527f242329173dfc316001df0a0c3d5a8f58a7ffb1a8b7d99c268303b9a741bacdf95490565b61154a61131c565b600160a060020a0316331461155e57600080fd5b7f660d8ed18395a9aa930e304e0bb5e6e51957af1fa215b11db48bfda3dd38d51160005260026020527fb1578d368dec034f5de4adb7567061a469e92e7039fd319ab435573139ccbcc68054600160a060020a031916600160a060020a0392909216919091179055565b6115d061131c565b600160a060020a031633146115e457600080fd5b6114f181611c91565b6115f561131c565b600160a060020a0316331461160957600080fd5b7fffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd660005260046020527f265a43ea29ede07170a30cb6d77d0ab5810eee752b72432f7be348bde74aa08f805460ff1916911515919091179055565b6000600460008360405160200180807f6d65737361676543616c6c5374617475730000000000000000000000000000008152506011018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106109a75780518252601f199092019160209182019101610988565b6060600061172589888a89898080602002602001604051908101604052809392919081815260200183836020028082843750612519945050505050565b8383604051602001808383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b6020831061177b5780518252601f19909201916020918201910161175c565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902090506117b381611373565b156117bd57600080fd5b6117c8816001612832565b5098975050505050505050565b7f7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b5490565b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d5490565b60006118578484846000612904565b949350505050565b60008060008360405160200180807f6661696c65644d6573736167654461746148617368000000000000000000000081525060150182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106118e35780518252601f1990920191602091820191016118c4565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205495945050505050565b600080516020613e738339815191526000908152602052600080516020613e538339815191525490565b60008060008061195c613e07565b60606119688989611e5b565b61197189611e83565b90919250809650819750829850839950849a50859b50505050505050610e53896040516020018082805190602001908083835b602083106119c35780518252601f1990920191602091820191016119a4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310611a265780518252601f199092019160209182019101611a07565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390208787878b888888611f2e565b610a5884848080601f0160208091040260200160405190810160405280939291908181526020018383808284375050604080516020601f8a018190048102820181019092528881529450889350879250829150840183828082843750610d40945050505050565b611ace61131c565b600160a060020a03163314611ae257600080fd5b6114f181611d3a565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b60009081526020527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944195490565b6000903b1190565b600080600080600086118015611b575750600085115b1515611b6257600080fd5b85851415611b6f57600080fd5b506000925082915060ff905060015b831580611b89575082155b15611bd15783158015611b9d575085828716145b15611ba6578093505b82158015611bb5575084828616145b15611bbe578092505b6101009190910260ff1790600101611b7e565b5050600060208190527ff6c66672b1a9fe5622677597b0da8fd180a2c85696efbcf7fe4b1e0f4f0f6108949094557f2f30286a16f86ee067618e1a246990e40c07b7749418a6dd3133f9cfb7e814cc919091557f242329173dfc316001df0a0c3d5a8f58a7ffb1a8b7d99c268303b9a741bacdf9919091557ffb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d49896928115949091527f7b62b32ff48350e85ce95b571fde6f8b1096bc44a26db769ad6d0b3a26bf1c6d55565b60008111611c9e57600080fd5b6114f181612a93565b60008111611cb457600080fd5b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071600090815260209081527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e428290556040805183815290517f4fb76205cd57c896b21511d2114137d8e901b4ccd659e1a0f97d6306795264fb929181900390910190a150565b600160a060020a0381161515611d4f57600080fd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0611d7861131c565b60408051600160a060020a03928316815291841660208301528051918290030190a17f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e8054600160a060020a031916600160a060020a0392909216919091179055565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc805460ff19166001179055565b6000611e65611050565b14611e6f57600080fd5b610f778282611e7c6113f7565b6001612b19565b6000806000806000611e93613e07565b6060600080604f915060208a01519850600160a060020a0360348b015116975060548a01518060601c975063ffffffff8160401c16965080601a1a95508060181a6001808260031b1b03818501945080858e01511687528260191a91506001808360031b1b039050818501945080858e0151166020880152848d51039350505050611f1f8a8383612da3565b92505050919395979092949650565b611f3787612e28565b1515611f4257600080fd5b6020820151611f5090612e41565b1515611f5b57600080fd5b611f6487610922565b15611f6e57600080fd5b611f79876001612e53565b611f9586868963ffffffff881687876000602002015187612ed6565b5050505050505050565b80600160a060020a0381161515611fb557600080fd5b600160a060020a0383161515611fd357611fce82612f23565b611fdd565b611fdd8383612f2f565b505050565b6000611fec611248565b905080600160a060020a031663ee4937ba6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561202c57600080fd5b505af1158015612040573d6000803e3d6000fd5b505050506040513d602081101561205657600080fd5b5051604080517f146ffb260000000000000000000000000000000000000000000000000000000081529051600160a060020a03928316926339d0bf63929085169163146ffb26916004808201926020929091908290030181600087803b1580156120bf57600080fd5b505af11580156120d3573d6000803e3d6000fd5b505050506040513d60208110156120e957600080fd5b5051604080517f42cde4e80000000000000000000000000000000000000000000000000000000081529051600160a060020a038616916342cde4e89160048083019260209291908290030181600087803b15801561214657600080fd5b505af115801561215a573d6000803e3d6000fd5b505050506040513d602081101561217057600080fd5b5051604080517f5210eb560000000000000000000000000000000000000000000000000000000081529051600160a060020a03871691635210eb569160048083019260209291908290030181600087803b1580156121cd57600080fd5b505af11580156121e1573d6000803e3d6000fd5b505050506040513d60208110156121f757600080fd5b5051604080517ff144d48600000000000000000000000000000000000000000000000000000000815290518891600160a060020a0389169163f144d4869160048082019260009290919082900301818387803b15801561225657600080fd5b505af115801561226a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561229357600080fd5b8101908080516401000000008111156122ab57600080fd5b820160208101848111156122be57600080fd5b81518560208202830111640100000000821117156122db57600080fd5b505092919050505087600160a060020a0316636b6e93d56040518163ffffffff1660e060020a028152600401600060405180830381600087803b15801561232157600080fd5b505af1158015612335573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561235e57600080fd5b81019080805164010000000081111561237657600080fd5b8201602081018481111561238957600080fd5b81518560208202830111640100000000821117156123a657600080fd5b505060405160e060020a63ffffffff8c16028152600481018a8152602482018a9052600160a060020a038916604483015260c060648301908152885160c484015288519396509094509250608481019160a482019160e40190602089019080838360005b8381101561242257818101518382015260200161240a565b50505050905090810190601f16801561244f5780820380516001836020036101000a031916815260200191505b508481038352865181528651602091820191808901910280838360005b8381101561248457818101518382015260200161246c565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156124c35781810151838201526020016124ab565b505050509050019950505050505050505050602060405180830381600087803b1580156124ef57600080fd5b505af1158015612503573d6000803e3d6000fd5b505050506040513d6020811015610a5857600080fd5b6000612523611248565b905080600160a060020a031663789b11d76040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561256357600080fd5b505af1158015612577573d6000803e3d6000fd5b505050506040513d602081101561258d57600080fd5b5051600160a060020a03163314801561260e575080600160a060020a031663146ffb266040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156125df57600080fd5b505af11580156125f3573d6000803e3d6000fd5b505050506040513d602081101561260957600080fd5b505185145b801561268e575080600160a060020a0316635210eb566040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561265357600080fd5b505af1158015612667573d6000803e3d6000fd5b505050506040513d602081101561267d57600080fd5b5051600160a060020a038481169116145b8015612702575080600160a060020a0316632690ff8b6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156126d357600080fd5b505af11580156126e7573d6000803e3d6000fd5b505050506040513d60208110156126fd57600080fd5b505184145b8015612820575080600160a060020a031663f238ca266040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561274757600080fd5b505af115801561275b573d6000803e3d6000fd5b505050506040513d602081101561277157600080fd5b5051604051835184916020908101918291848101910280838360005b838110156127a557818101518382015260200161278d565b505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106127ed5780518252601f1990920191602091820191016127ce565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902060001916145b151561282b57600080fd5b5050505050565b80600460008460405160200180807f6d65737361676573417070726f7665644279486173686900000000000000000081525060170182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106128b65780518252601f199092019160209182019101612897565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff1916941515949094179093555050505050565b6000808060608082612914611050565b14806129235750612923610fff565b151561292e57600080fd5b606487101580156129465750612942611924565b8711155b151561295157600080fd5b63ffffffff60048901511693508363a9059cbb1415801561297657508363095ea7b314155b80156129865750836323b872dd14155b8015612996575083634000aea014155b80156129a657508363cae9ca5114155b15156129b157600080fd5b6129bc898888612fdc565b9250925081886040516020018083805190602001908083835b602083106129f45780518252601f1990920191602091820191016129d5565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310612a3c5780518252601f199092019160209182019101612a1d565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529050612a7d8382613092565b612a868161312f565b5090979650505050505050565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b600090815260209081527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944198290556040805183815290517f52264b89e0fceafb26e79fd49ef8a366eb6297483bf4035b027f0c99a7ad512e929181900390910190a150565b6000806000606060008060008060008060008b80612b3b5750612b3b8f613248565b1515612b4657600080fd5b8c600160a060020a0316638d0680436040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612b8457600080fd5b505af1158015612b98573d6000803e3d6000fd5b505050506040513d6020811015612bae57600080fd5b505160018f0151909b5060ff1699508a8a1015612bca57600080fd5b612bd48f8d61325c565b98508a604051908082528060200260200182016040528015612c00578160200160208202803883390190505b509750600096505b8a871015612d9257866020028a6021010192508960200283019150866002018e01519550828e01519450818e01519350600189878787604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015612caf573d6000803e3d6000fd5b5050506020604051035190508c600160a060020a031663facd743b826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015612d1657600080fd5b505af1158015612d2a573d6000803e3d6000fd5b505050506040513d6020811015612d4057600080fd5b50511515612d4d57600080fd5b612d578882613476565b15612d6157600080fd5b808888815181101515612d7057fe5b600160a060020a03909216602092830290910190910152600190960195612c08565b505050505050505050505050505050565b606080828401855110151515612db857600080fd5b82158015612dd55760405191506000825260208201604052612e1f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612e0e578051835260209283019201612df6565b5050858452601f01601f1916604052505b50949350505050565b600160e060020a0319811660f060020a60050214919050565b6000612e4b6108cf565b909114919050565b80600460008460405160200180807f72656c617965644d657373616765730000000000000000000000000000000000815250600f018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106128b65780518252601f199092019160209182019101612897565b6000612ee6888884888a886134d1565b9050612ef286826135c7565b801515612f1757612f03868361364a565b612f0d8688613759565b612f17868961383a565b611f95888888846138bd565b3031610f77828261390b565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b158015612f9457600080fd5b505af1158015612fa8573d6000803e3d6000fd5b505050506040513d6020811015612fbe57600080fd5b50519050610a58600160a060020a038516848363ffffffff61396c16565b60006060600080600080612fee6108cf565b9350612ff8613a01565b92506130026114f4565b915061300c613a4f565b905061301784613a9d565b95508083604f01016040519080825280601f01601f19166020018201604052801561304c578160200160208202803883390190505b50945084518501828152848282035287604f87015281604e87015283604d87015288604c8701528960488701523360348701528660208701525050505050935093915050565b604080516020808252835181830152835185937f482515ce3d9494a37ce83f18b72b363449458435fafdd7a53ddea7460fe01b589386939092839283019185019080838360005b838110156130f15781810151838201526020016130d9565b50505050905090810190601f16801561311e5780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b6001600460008360405160200180807f6461746153656e7457697468486173686900000000000000000000000000000081525060110182805190602001908083835b602083106131905780518252601f199092019160209182019101613171565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106131f35780518252601f1990920191602091820191016131d4565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff191694151594909417909355506114f19150829050611fe2565b6000613252613b88565b8251149050919050565b60408051808201909152601a81527f19457468657265756d205369676e6564204d6573736167653a0a00000000000060208201526000906060831561340257816132a68651613b8d565b866040516020018084805190602001908083835b602083106132d95780518252601f1990920191602091820191016132ba565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106133215780518252601f199092019160209182019101613302565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106133695780518252601f19909201916020918201910161334a565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b602083106133ce5780518252601f1990920191602091820191016133af565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020925061346e565b6040805190810160405280600381526020017f31303400000000000000000000000000000000000000000000000000000000008152509050818186604051602001808480519060200190808383602083106132d95780518252601f1990920191602091820191016132ba565b505092915050565b6000805b83518110156134c55782600160a060020a0316848281518110151561349b57fe5b90602001906020020151600160a060020a031614156134bd57600191506134ca565b60010161347a565b600091505b5092915050565b6000806134dd88613cb4565b6134e684613cd8565b6134ef83613cfc565b8463ffffffff148061350f57508460405a603f0281151561350c57fe5b04115b151561351a57600080fd5b86600160a060020a0316858760405180828051906020019080838360005b83811015613550578181015183820152602001613538565b50505050905090810190601f16801561357d5780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008787f192505050905061359e81613d20565b6135a86000613cb4565b6135b26000613cd8565b6135bc6000613cfc565b979650505050505050565b80600460008460405160200180807f6d65737361676543616c6c5374617475730000000000000000000000000000008152506011018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106128b65780518252601f199092019160209182019101612897565b806040518082805190602001908083835b6020831061367a5780518252601f19909201916020918201910161365b565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207f6661696c65644d657373616765446174614861736800000000000000000000008383015260358084018a905285518085039091018152605590930194859052825190965060009550859492935082918401908083835b602083106137175780518252601f1990920191602091820191016136f8565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b80600260008460405160200180807f6661696c65644d6573736167655265636569766572000000000000000000000081525060150182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106137dd5780518252601f1990920191602091820191016137be565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000208054600160a060020a031916600160a060020a0395909516949094179093555050505050565b80600260008460405160200180807f6661696c65644d65737361676553656e646572000000000000000000000000008152506013018260001916600019168152602001915050604051602081830303815290604052604051808280519060200190808383602083106137dd5780518252601f1990920191602091820191016137be565b60408051821515815290518391600160a060020a0380871692908816917f27333edb8bdcd40a0ae944fb121b5e2d62ea782683946654a0f5e607a908d578919081900360200190a450505050565b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610f77578082613940613e22565b600160a060020a039091168152604051908190036020019082f08015801561282b573d6000803e3d6000fd5b82600160a060020a031663a9059cbb83836040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b1580156139cf57600080fd5b505af11580156139e3573d6000803e3d6000fd5b505050503d15611fdd5760206000803e6000511515611fdd57600080fd5b7fe504ae1fd6471eea80f18b8532a61a9bb91fba4f5b837f80a1cfb6752350af4460009081526020527f2f30286a16f86ee067618e1a246990e40c07b7749418a6dd3133f9cfb7e814cc5490565b7ffb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d498969281159460009081526020527f7b62b32ff48350e85ce95b571fde6f8b1096bc44a26db769ad6d0b3a26bf1c6d5490565b6000806000613aaa613d62565b9150613ab882600101613db0565b6040805160208082018790526c0100000000000000000000000030028284015282516034818403018152605490920192839052815191929182918401908083835b60208310613b185780518252601f199092019160209182019101613af9565b5181516000196020949094036101000a93909301928316921916919091179052604051920182900390912067ffffffffffffffff86167bffffffffffffffffffffffffffffffffffffffff000000000000000090911690811760f060020a60050217965093505050505050919050565b606890565b60606000808281851515613bd65760408051808201909152600181527f300000000000000000000000000000000000000000000000000000000000000060208201529450613cab565b8593505b8315613bf157600190920191600a84049350613bda565b826040519080825280601f01601f191660200182016040528015613c1f578160200160208202803883390190505b5091505060001982015b8515613ca75781516000198201917f01000000000000000000000000000000000000000000000000000000000000006030600a8a060102918491908110613c6c57fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a86049550613c29565b8194505b50505050919050565b7f7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b55565b7fe34bb2103dc34f2c144cc216c132d6ffb55dac57575c22e089161bbe6508330455565b7f7f0fcd9e49860f055dd0c1682d635d309ecb5e3011654c716d9eb59a7ddec7d255565b8080613d575750600035600160e060020a0319167f3f7658fd00000000000000000000000000000000000000000000000000000000145b15156114f157600080fd5b7f7ab1577440dd7bedf920cb6de2f9fc6bf7ba98c78c85a3fa1f8311aac95e175960009081526020527fa9b0f75b23e377b9b22d27feaca5d8a12329c0049ebce1dc695b905f3aa4cd005490565b7f7ab1577440dd7bedf920cb6de2f9fc6bf7ba98c78c85a3fa1f8311aac95e1759600090815260205267ffffffffffffffff167fa9b0f75b23e377b9b22d27feaca5d8a12329c0049ebce1dc695b905f3aa4cd0055565b60408051808201825290600290829080388339509192915050565b604051602180613e32833901905600608060405260405160208060218339810160405251600160a060020a038116ff003d7fe2ee9790702383ef0118b516833ef2542132d3ca4ac6c77f62f1230fa6102670ecc91ec356e32067fd27b36614132d727b84a1e03e08f412a4f2cf075974a165627a7a723058200463515421c3b0bab34d82cbed259998e8a7fd15b8c8cc2be9a00feaa599fd250029
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.