Polygon Sponsored slots available. Book your slot here!
Overview
POL Balance
0 POL
POL Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 703 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Execute Refund | 43131180 | 558 days ago | IN | 0 POL | 0.01124428 | ||||
Execute Refund | 43131166 | 558 days ago | IN | 0 POL | 0.00946395 | ||||
Execute Refund | 41092096 | 610 days ago | IN | 0 POL | 0.03682995 | ||||
Src Release | 40895929 | 615 days ago | IN | 0 POL | 0.02674549 | ||||
Src Release | 40895714 | 615 days ago | IN | 0 POL | 0.03003406 | ||||
Src Deposit | 40895666 | 615 days ago | IN | 0.0495 POL | 0.01584086 | ||||
Src Deposit | 40895434 | 615 days ago | IN | 0.0495 POL | 0.02110046 | ||||
Execute Refund | 40744510 | 619 days ago | IN | 0 POL | 0.0179572 | ||||
Src Deposit | 40742626 | 619 days ago | IN | 0.0495 POL | 0.00952684 | ||||
Execute Refund | 40742563 | 619 days ago | IN | 0 POL | 0.01801173 | ||||
Src Deposit | 40741125 | 619 days ago | IN | 0.0495 POL | 0.00865057 | ||||
Src Deposit | 40740845 | 620 days ago | IN | 0.0495 POL | 0.00850117 | ||||
Src Release | 40736830 | 620 days ago | IN | 0 POL | 0.02031749 | ||||
Src Deposit | 40736570 | 620 days ago | IN | 0.0495 POL | 0.013905 | ||||
Src Release | 40733877 | 620 days ago | IN | 0 POL | 0.01638901 | ||||
Src Deposit | 40733610 | 620 days ago | IN | 0.0495 POL | 0.00972477 | ||||
Src Release | 40731145 | 620 days ago | IN | 0 POL | 0.01153971 | ||||
Src Deposit | 40730889 | 620 days ago | IN | 0.0495 POL | 0.0080446 | ||||
Src Release | 40727579 | 620 days ago | IN | 0 POL | 0.0190943 | ||||
Src Deposit | 40727305 | 620 days ago | IN | 0.0495 POL | 0.01222706 | ||||
Src Release | 40719879 | 620 days ago | IN | 0 POL | 0.03027138 | ||||
Src Deposit | 40719582 | 620 days ago | IN | 0.0495 POL | 0.01788167 | ||||
Src Release | 40717552 | 620 days ago | IN | 0 POL | 0.04374443 | ||||
Src Deposit | 40717284 | 620 days ago | IN | 0.0495 POL | 0.02197759 | ||||
Src Release | 40716791 | 620 days ago | IN | 0 POL | 0.1089809 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
40895666 | 615 days ago | 0.0495 POL | ||||
40895434 | 615 days ago | 0.0495 POL | ||||
40742626 | 619 days ago | 0.0495 POL | ||||
40741125 | 619 days ago | 0.0495 POL | ||||
40740845 | 620 days ago | 0.0495 POL | ||||
40736570 | 620 days ago | 0.0495 POL | ||||
40733610 | 620 days ago | 0.0495 POL | ||||
40730889 | 620 days ago | 0.0495 POL | ||||
40727305 | 620 days ago | 0.0495 POL | ||||
40719582 | 620 days ago | 0.0495 POL | ||||
40717284 | 620 days ago | 0.0495 POL | ||||
40716532 | 620 days ago | 0.0495 POL | ||||
40710584 | 620 days ago | 0.0495 POL | ||||
40705537 | 620 days ago | 0.0495 POL | ||||
40705341 | 620 days ago | 0.0495 POL | ||||
40704324 | 620 days ago | 0.0495 POL | ||||
40704280 | 620 days ago | 0.0495 POL | ||||
40701986 | 621 days ago | 0.0495 POL | ||||
40699698 | 621 days ago | 0.0495 POL | ||||
40699611 | 621 days ago | 0.0495 POL | ||||
40699569 | 621 days ago | 0.0495 POL | ||||
40694921 | 621 days ago | 0.0495 POL | ||||
40694111 | 621 days ago | 0.0495 POL | ||||
40692983 | 621 days ago | 0.0495 POL | ||||
40692291 | 621 days ago | 0.0495 POL |
Loading...
Loading
Contract Name:
RFQ
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.9; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "../framework/MessageSenderApp.sol"; import "../framework/MessageReceiverApp.sol"; import "../../safeguard/Pauser.sol"; import "../../safeguard/Governor.sol"; import "../../message/interfaces/IMessageBus.sol"; import "../../interfaces/IWETH.sol"; /** @title rfq contract */ contract RFQ is MessageSenderApp, MessageReceiverApp, Pauser, Governor { using SafeERC20 for IERC20; using ECDSA for bytes32; struct Quote { uint64 srcChainId; address srcToken; uint256 srcAmount; uint256 srcReleaseAmount; uint64 dstChainId; address dstToken; uint256 dstAmount; uint64 deadline; uint64 nonce; address sender; address receiver; address refundTo; address liquidityProvider; } enum QuoteStatus { Null, SrcDeposited, // sender deposited SrcReleased, // released ERC20 token to liquidity provider SrcReleasedNative, // released native token to liquidity provider SrcRefunded, // refunded ERC20 token to refundTo/sender SrcRefundedNative, // refunded native token to refundTo/sender DstRefundInitiated, // refund initiated DstTransferred, // transferred ERC20 token to receiver DstTransferredNative // transferred native token to reciever } enum MessageType { Null, Release, Refund } address public nativeWrap; mapping(uint64 => address) public remoteRfqContracts; // msg => bool mapping(bytes32 => bool) public unconsumedMsg; // quoteHash => QuoteStatus mapping(bytes32 => QuoteStatus) public quotes; address public treasuryAddr; uint32 public feePercGlobal; // chainId => feePercOverride, support override fee perc of this chain mapping(uint64 => uint32) public feePercOverride; // tokenAddr => feeBalance mapping(address => uint256) public protocolFee; // market maker => allowed signer mapping(address => address) public allowedSigner; event SrcDeposited(bytes32 quoteHash, Quote quote); event DstTransferred(bytes32 quoteHash, address receiver, address dstToken, uint256 amount); event RefundInitiated(bytes32 quoteHash); event SrcReleased(bytes32 quoteHash, address liquidityProvider, address srcToken, uint256 amount); event Refunded(bytes32 quoteHash, address refundTo, address srcToken, uint256 amount); event RfqContractsUpdated(uint64[] chainIds, address[] remoteRfqContracts); event FeePercUpdated(uint64[] chainIds, uint32[] feePercs); event TreasuryAddrUpdated(address treasuryAddr); event FeeCollected(address treasuryAddr, address token, uint256 amount); constructor(address _messageBus) { messageBus = _messageBus; } function srcDeposit(Quote calldata _quote, uint64 _submissionDeadline) external payable whenNotPaused returns (bytes32) { bytes32 quoteHash = _srcDeposit(_quote, _submissionDeadline, msg.value); IERC20(_quote.srcToken).safeTransferFrom(msg.sender, address(this), _quote.srcAmount); return quoteHash; } function srcDepositNative(Quote calldata _quote, uint64 _submissionDeadline) external payable whenNotPaused returns (bytes32) { require(nativeWrap != address(0), "Rfq: native wrap not set"); require(_quote.srcToken == nativeWrap, "Rfq: src token mismatch"); require(msg.value >= _quote.srcAmount, "Rfq: insufficient amount"); bytes32 quoteHash = _srcDeposit(_quote, _submissionDeadline, msg.value - _quote.srcAmount); IWETH(nativeWrap).deposit{value: _quote.srcAmount}(); return quoteHash; } function _srcDeposit( Quote calldata _quote, uint64 _submissionDeadline, uint256 _msgFee ) private returns (bytes32) { require( _submissionDeadline > block.timestamp && _quote.deadline > _submissionDeadline, "Rfq: inappropriate deadline" ); require( _quote.receiver != address(0) && _quote.liquidityProvider != address(0), "Rfq: invalid receiver or liquidityProvider" ); require(_quote.srcChainId == uint64(block.chainid), "Rfq: src chainId mismatch"); require(_quote.sender == msg.sender, "Rfq: sender mismatch"); bytes32 quoteHash = getQuoteHash(_quote); require(quotes[quoteHash] == QuoteStatus.Null, "Rfq: quote hash exists"); uint256 rfqFee = getRfqFee(_quote.dstChainId, _quote.srcAmount); require(rfqFee <= _quote.srcAmount - _quote.srcReleaseAmount, "Rfq: insufficient protocol fee"); quotes[quoteHash] = QuoteStatus.SrcDeposited; if (_quote.srcChainId != _quote.dstChainId) { address msgReceiver = remoteRfqContracts[_quote.dstChainId]; require(msgReceiver != address(0), "Rfq: dst contract not set"); bytes memory message = abi.encodePacked(quoteHash); sendMessage(msgReceiver, _quote.dstChainId, message, _msgFee); } emit SrcDeposited(quoteHash, _quote); return quoteHash; } function dstTransfer(Quote calldata _quote) external payable whenNotPaused { (bytes32 quoteHash, address msgReceiver) = _dstTransferCheck(_quote); quotes[quoteHash] = QuoteStatus.DstTransferred; bytes memory message = abi.encodePacked(keccak256(abi.encodePacked(quoteHash, MessageType.Release))); sendMessage(msgReceiver, _quote.srcChainId, message, msg.value); IERC20(_quote.dstToken).safeTransferFrom(msg.sender, _quote.receiver, _quote.dstAmount); emit DstTransferred(quoteHash, _quote.receiver, _quote.dstToken, _quote.dstAmount); } function dstTransferNative(Quote calldata _quote) external payable whenNotPaused { require(_quote.dstToken == nativeWrap, "Rfq: dst token mismatch"); require(msg.value >= _quote.dstAmount, "Rfq: insufficient amount"); (bytes32 quoteHash, address msgReceiver) = _dstTransferCheck(_quote); quotes[quoteHash] = QuoteStatus.DstTransferredNative; bytes memory message = abi.encodePacked(keccak256(abi.encodePacked(quoteHash, MessageType.Release))); sendMessage(msgReceiver, _quote.srcChainId, message, msg.value - _quote.dstAmount); _transferNativeToken(_quote.receiver, _quote.dstAmount); emit DstTransferred(quoteHash, _quote.receiver, _quote.dstToken, _quote.dstAmount); } // As transferFrom is not available for native token, dstTransferNativeWithSig is not supported function dstTransferWithSig(Quote calldata _quote, bytes calldata _sig) external payable whenNotPaused { (bytes32 quoteHash, address msgReceiver) = _dstTransferCheck(_quote); verifySigOfQuoteHash(_quote.liquidityProvider, quoteHash, _sig); quotes[quoteHash] = QuoteStatus.DstTransferred; bytes memory message = abi.encodePacked(keccak256(abi.encodePacked(quoteHash, MessageType.Release))); sendMessage(msgReceiver, _quote.srcChainId, message, msg.value); IERC20(_quote.dstToken).safeTransferFrom(_quote.liquidityProvider, _quote.receiver, _quote.dstAmount); emit DstTransferred(quoteHash, _quote.receiver, _quote.dstToken, _quote.dstAmount); } function sameChainTransfer(Quote calldata _quote, bool _releaseNative) external payable whenNotPaused { require(_quote.srcChainId == _quote.dstChainId, "Rfq: not same chain swap"); (bytes32 quoteHash, ) = _dstTransferCheck(_quote); IERC20(_quote.dstToken).safeTransferFrom(msg.sender, _quote.receiver, _quote.dstAmount); _srcRelease(_quote, quoteHash, _releaseNative); emit DstTransferred(quoteHash, _quote.receiver, _quote.dstToken, _quote.dstAmount); } function sameChainTransferNative(Quote calldata _quote, bool _releaseNative) external payable whenNotPaused { require(_quote.srcChainId == _quote.dstChainId, "Rfq: not same chain swap"); require(_quote.dstToken == nativeWrap, "Rfq: dst token mismatch"); require(msg.value == _quote.dstAmount, "Rfq: native token amount mismatch"); (bytes32 quoteHash, ) = _dstTransferCheck(_quote); _transferNativeToken(_quote.receiver, _quote.dstAmount); _srcRelease(_quote, quoteHash, _releaseNative); emit DstTransferred(quoteHash, _quote.receiver, _quote.dstToken, _quote.dstAmount); } // As transferFrom is not available for native token, sameChainTransferNativeWithSig is not supported function sameChainTransferWithSig( Quote calldata _quote, bool _releaseNative, bytes calldata _sig ) external payable whenNotPaused { require(_quote.srcChainId == _quote.dstChainId, "Rfq: not same chain swap"); (bytes32 quoteHash, ) = _dstTransferCheck(_quote); verifySigOfQuoteHash(_quote.liquidityProvider, quoteHash, _sig); IERC20(_quote.dstToken).safeTransferFrom(_quote.liquidityProvider, _quote.receiver, _quote.dstAmount); _srcRelease(_quote, quoteHash, _releaseNative); emit DstTransferred(quoteHash, _quote.receiver, _quote.dstToken, _quote.dstAmount); } function _dstTransferCheck(Quote calldata _quote) private view returns (bytes32, address) { require(_quote.deadline > block.timestamp, "Rfq: transfer deadline passed"); require(_quote.dstChainId == uint64(block.chainid), "Rfq: dst chainId mismatch"); bytes32 quoteHash = getQuoteHash(_quote); address msgReceiver = remoteRfqContracts[_quote.srcChainId]; if (_quote.srcChainId != _quote.dstChainId) { require(quotes[quoteHash] == QuoteStatus.Null, "Rfq: quote already executed"); require(msgReceiver != address(0), "Rfq: dst rfq contract not set"); } else { require(quotes[quoteHash] == QuoteStatus.SrcDeposited, "Rfq: no deposit on same chain"); } return (quoteHash, msgReceiver); } function srcRelease(Quote calldata _quote, bytes calldata _execMsgCallData) external whenNotPaused { bytes32 quoteHash = _srcReleaseCheck(_quote, _execMsgCallData); _srcRelease(_quote, quoteHash, false); } function srcReleaseNative(Quote calldata _quote, bytes calldata _execMsgCallData) external whenNotPaused { require(_quote.srcToken == nativeWrap, "Rfq: src token mismatch"); bytes32 quoteHash = _srcReleaseCheck(_quote, _execMsgCallData); _srcRelease(_quote, quoteHash, true); } function _srcReleaseCheck(Quote calldata _quote, bytes calldata _execMsgCallData) private returns (bytes32) { bytes32 quoteHash = getQuoteHash(_quote); require(quotes[quoteHash] == QuoteStatus.SrcDeposited, "Rfq: incorrect quote hash"); _receiveMessage(_execMsgCallData, quoteHash, MessageType.Release); return quoteHash; } function _srcRelease( Quote calldata _quote, bytes32 _quoteHash, bool _releaseNative ) private { protocolFee[_quote.srcToken] += (_quote.srcAmount - _quote.srcReleaseAmount); if (_releaseNative) { quotes[_quoteHash] = QuoteStatus.SrcReleasedNative; _withdrawNativeToken(_quote.liquidityProvider, _quote.srcReleaseAmount); } else { quotes[_quoteHash] = QuoteStatus.SrcReleased; IERC20(_quote.srcToken).safeTransfer(_quote.liquidityProvider, _quote.srcReleaseAmount); } emit SrcReleased(_quoteHash, _quote.liquidityProvider, _quote.srcToken, _quote.srcReleaseAmount); } function requestRefund(Quote calldata _quote) external payable whenNotPaused { require(_quote.deadline < block.timestamp, "Rfq: transfer deadline not passed"); require(_quote.dstChainId == uint64(block.chainid), "Rfq: dst chainId mismatch"); address _receiver = remoteRfqContracts[_quote.srcChainId]; require(_receiver != address(0), "Rfq: src rfq contract not set"); bytes32 quoteHash = getQuoteHash(_quote); require(quotes[quoteHash] == QuoteStatus.Null, "Rfq: quote already executed"); quotes[quoteHash] = QuoteStatus.DstRefundInitiated; bytes memory message = abi.encodePacked(keccak256(abi.encodePacked(quoteHash, MessageType.Refund))); sendMessage(_receiver, _quote.srcChainId, message, msg.value); emit RefundInitiated(quoteHash); } function executeRefund(Quote calldata _quote, bytes calldata _execMsgCallData) external whenNotPaused { (bytes32 quoteHash, address receiver) = _executeRefund(_quote, _execMsgCallData); quotes[quoteHash] = QuoteStatus.SrcRefunded; IERC20(_quote.srcToken).safeTransfer(receiver, _quote.srcAmount); emit Refunded(quoteHash, receiver, _quote.srcToken, _quote.srcAmount); } function executeRefundNative(Quote calldata _quote, bytes calldata _execMsgCallData) external whenNotPaused { require(_quote.srcToken == nativeWrap, "Rfq: src token mismatch"); (bytes32 quoteHash, address receiver) = _executeRefund(_quote, _execMsgCallData); quotes[quoteHash] = QuoteStatus.SrcRefundedNative; _withdrawNativeToken(_quote.receiver, _quote.srcAmount); emit Refunded(quoteHash, receiver, _quote.srcToken, _quote.srcAmount); } function _executeRefund(Quote calldata _quote, bytes calldata _execMsgCallData) private returns (bytes32, address) { bytes32 quoteHash = getQuoteHash(_quote); require(quotes[quoteHash] == QuoteStatus.SrcDeposited, "Rfq: incorrect quote hash"); if (_quote.srcChainId != _quote.dstChainId) { _receiveMessage(_execMsgCallData, quoteHash, MessageType.Refund); } else { require(_quote.deadline < block.timestamp, "Rfq: transfer deadline not passed"); } address receiver = (_quote.refundTo == address(0)) ? _quote.sender : _quote.refundTo; return (quoteHash, receiver); } function executeMessage( address _sender, uint64 _srcChainId, bytes calldata _message, address // executor ) external payable override onlyMessageBus returns (ExecutionStatus) { require(_message.length == 32, "Rfq: incorrect message length"); address expectedSender = remoteRfqContracts[_srcChainId]; if (expectedSender != _sender) { return ExecutionStatus.Retry; } unconsumedMsg[bytes32(_message)] = true; return ExecutionStatus.Success; } function collectFee(address _token) external { require(treasuryAddr != address(0), "Rfq: treasury address not set"); uint256 feeAmount = protocolFee[_token]; protocolFee[_token] = 0; IERC20(_token).safeTransfer(treasuryAddr, feeAmount); emit FeeCollected(treasuryAddr, _token, feeAmount); } function registerAllowedSigner(address _signer) external { if (_signer == address(0)) { delete (allowedSigner[msg.sender]); } else { allowedSigner[msg.sender] = _signer; } } // This is needed to receive ETH receive() external payable {} //=========================== helper functions ========================== function getQuoteHash(Quote calldata _quote) public pure returns (bytes32) { return keccak256( abi.encodePacked( _quote.srcChainId, _quote.srcToken, _quote.srcAmount, _quote.srcReleaseAmount, _quote.dstChainId, _quote.dstToken, _quote.dstAmount, _quote.deadline, _quote.nonce, _quote.sender, _quote.receiver, _quote.refundTo, _quote.liquidityProvider ) ); } function getRfqFee(uint64 _chainId, uint256 _amount) public view returns (uint256) { uint32 feePerc = feePercOverride[_chainId]; if (feePerc == 0) { feePerc = feePercGlobal; } return (_amount * feePerc) / 1e6; } function getMsgFee(bytes calldata _message) public view returns (uint256) { return IMessageBus(messageBus).calcFee(_message); } function getSignerOfQuoteHash(bytes32 _quoteHash, bytes calldata _sig) public view returns (address) { bytes32 msgHash = keccak256(abi.encodePacked(block.chainid, address(this), "AllowedTransfer", _quoteHash)) .toEthSignedMessageHash(); return msgHash.recover(_sig); } function verifySigOfQuoteHash( address _liquidityProvider, bytes32 _quoteHash, bytes calldata _sig ) public view { address signer = getSignerOfQuoteHash(_quoteHash, _sig); require( signer == _liquidityProvider || (allowedSigner[_liquidityProvider] != address(0) && signer == allowedSigner[_liquidityProvider]), "Rfq: not allowed signer" ); } function _receiveMessage( bytes calldata _execMsgCallData, bytes32 _quoteHash, MessageType _msgType ) private { bytes32 expectedMsg = keccak256(abi.encodePacked(_quoteHash, _msgType)); if (!unconsumedMsg[expectedMsg]) { (bool success, ) = messageBus.call(_execMsgCallData); require(success, "execute msg failed"); } require(unconsumedMsg[expectedMsg], "Rfq: invalid msg"); delete unconsumedMsg[expectedMsg]; } function _transferNativeToken(address _receiver, uint256 _amount) private { require(nativeWrap != address(0), "Rfq: native wrap not set"); (bool sent, ) = _receiver.call{value: _amount, gas: 50000}(""); require(sent, "Rfq: failed to transfer native token"); } function _withdrawNativeToken(address _receiver, uint256 _amount) private { require(nativeWrap != address(0), "Rfq: native wrap not set"); IWETH(nativeWrap).withdraw(_amount); (bool sent, ) = _receiver.call{value: _amount, gas: 50000}(""); require(sent, "Rfq: failed to withdraw native token"); } //=========================== admin operations ========================== function setRemoteRfqContracts(uint64[] calldata _chainIds, address[] calldata _remoteRfqContracts) external onlyOwner { require(_chainIds.length == _remoteRfqContracts.length, "Rfq: length mismatch"); for (uint256 i = 0; i < _chainIds.length; i++) { remoteRfqContracts[_chainIds[i]] = _remoteRfqContracts[i]; } emit RfqContractsUpdated(_chainIds, _remoteRfqContracts); } function setFeePerc(uint64[] calldata _chainIds, uint32[] calldata _feePercs) external onlyGovernor { require(_chainIds.length == _feePercs.length, "Rfq: length mismatch"); for (uint256 i = 0; i < _chainIds.length; i++) { require(_feePercs[i] < 1e6, "Rfq: fee percentage too large"); if (_chainIds[i] == 0) { feePercGlobal = _feePercs[i]; } else { feePercOverride[_chainIds[i]] = _feePercs[i]; } } emit FeePercUpdated(_chainIds, _feePercs); } function setTreasuryAddr(address _treasuryAddr) external onlyOwner { treasuryAddr = _treasuryAddr; emit TreasuryAddrUpdated(_treasuryAddr); } function setNativeWrap(address _nativeWrap) external onlyOwner { nativeWrap = _nativeWrap; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../libraries/MsgDataTypes.sol"; import "../libraries/MessageSenderLib.sol"; import "../messagebus/MessageBus.sol"; import "./MessageBusAddress.sol"; abstract contract MessageSenderApp is MessageBusAddress { using SafeERC20 for IERC20; // ============== Utility functions called by apps ============== /** * @notice Sends a message to a contract on another chain. * Sender needs to make sure the uniqueness of the message Id, which is computed as * hash(type.MessageOnly, sender, receiver, srcChainId, srcTxHash, dstChainId, message). * If messages with the same Id are sent, only one of them will succeed at dst chain. * @param _receiver The address of the destination app contract. * @param _dstChainId The destination chain ID. * @param _message Arbitrary message bytes to be decoded by the destination app contract. * @param _fee The fee amount to pay to MessageBus. */ function sendMessage( address _receiver, uint64 _dstChainId, bytes memory _message, uint256 _fee ) internal { MessageSenderLib.sendMessage(_receiver, _dstChainId, _message, messageBus, _fee); } // Send message to non-evm chain with bytes for receiver address, // otherwise same as above. function sendMessage( bytes calldata _receiver, uint64 _dstChainId, bytes memory _message, uint256 _fee ) internal { MessageSenderLib.sendMessage(_receiver, _dstChainId, _message, messageBus, _fee); } /** * @notice Sends a message associated with a transfer to a contract on another chain. * @param _receiver The address of the destination app contract. * @param _token The address of the token to be sent. * @param _amount The amount of tokens to be sent. * @param _dstChainId The destination chain ID. * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice. * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%. * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least * (100% - max slippage percentage) * amount or the transfer can be refunded. * Only applicable to the {MsgDataTypes.BridgeSendType.Liquidity}. * @param _message Arbitrary message bytes to be decoded by the destination app contract. * If message is empty, only the token transfer will be sent * @param _bridgeSendType One of the {BridgeSendType} enum. * @param _fee The fee amount to pay to MessageBus. * @return The transfer ID. */ function sendMessageWithTransfer( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSlippage, bytes memory _message, MsgDataTypes.BridgeSendType _bridgeSendType, uint256 _fee ) internal returns (bytes32) { return MessageSenderLib.sendMessageWithTransfer( _receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage, _message, _bridgeSendType, messageBus, _fee ); } /** * @notice Sends a token transfer via a bridge. * @dev sendMessageWithTransfer with empty message * @param _receiver The address of the destination app contract. * @param _token The address of the token to be sent. * @param _amount The amount of tokens to be sent. * @param _dstChainId The destination chain ID. * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice. * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%. * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least * (100% - max slippage percentage) * amount or the transfer can be refunded. * Only applicable to the {MsgDataTypes.BridgeSendType.Liquidity}. * @param _bridgeSendType One of the {BridgeSendType} enum. */ function sendTokenTransfer( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSlippage, MsgDataTypes.BridgeSendType _bridgeSendType ) internal returns (bytes32) { return MessageSenderLib.sendMessageWithTransfer( _receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage, "", // empty message, which will not trigger sendMessage _bridgeSendType, messageBus, 0 ); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; library MsgDataTypes { string constant ABORT_PREFIX = "MSG::ABORT:"; // bridge operation type at the sender side (src chain) enum BridgeSendType { Null, Liquidity, PegDeposit, PegBurn, PegV2Deposit, PegV2Burn, PegV2BurnFrom } // bridge operation type at the receiver side (dst chain) enum TransferType { Null, LqRelay, // relay through liquidity bridge LqWithdraw, // withdraw from liquidity bridge PegMint, // mint through pegged token bridge PegWithdraw, // withdraw from original token vault PegV2Mint, // mint through pegged token bridge v2 PegV2Withdraw // withdraw from original token vault v2 } enum MsgType { MessageWithTransfer, MessageOnly } enum TxStatus { Null, Success, Fail, Fallback, Pending // transient state within a transaction } struct TransferInfo { TransferType t; address sender; address receiver; address token; uint256 amount; uint64 wdseq; // only needed for LqWithdraw (refund) uint64 srcChainId; bytes32 refId; bytes32 srcTxHash; // src chain msg tx hash } struct RouteInfo { address sender; address receiver; uint64 srcChainId; bytes32 srcTxHash; // src chain msg tx hash } // used for msg from non-evm chains with longer-bytes address struct RouteInfo2 { bytes sender; address receiver; uint64 srcChainId; bytes32 srcTxHash; } // combination of RouteInfo and RouteInfo2 for easier processing struct Route { address sender; // from RouteInfo bytes senderBytes; // from RouteInfo2 address receiver; uint64 srcChainId; bytes32 srcTxHash; } struct MsgWithTransferExecutionParams { bytes message; TransferInfo transfer; bytes[] sigs; address[] signers; uint256[] powers; } struct BridgeTransferParams { bytes request; bytes[] sigs; address[] signers; uint256[] powers; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../../interfaces/IBridge.sol"; import "../../interfaces/IOriginalTokenVault.sol"; import "../../interfaces/IOriginalTokenVaultV2.sol"; import "../../interfaces/IPeggedTokenBridge.sol"; import "../../interfaces/IPeggedTokenBridgeV2.sol"; import "../interfaces/IMessageBus.sol"; import "./MsgDataTypes.sol"; library MessageSenderLib { using SafeERC20 for IERC20; // ============== Internal library functions called by apps ============== /** * @notice Sends a message to an app on another chain via MessageBus without an associated transfer. * @param _receiver The address of the destination app contract. * @param _dstChainId The destination chain ID. * @param _message Arbitrary message bytes to be decoded by the destination app contract. * @param _messageBus The address of the MessageBus on this chain. * @param _fee The fee amount to pay to MessageBus. */ function sendMessage( address _receiver, uint64 _dstChainId, bytes memory _message, address _messageBus, uint256 _fee ) internal { IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message); } // Send message to non-evm chain with bytes for receiver address, // otherwise same as above. function sendMessage( bytes calldata _receiver, uint64 _dstChainId, bytes memory _message, address _messageBus, uint256 _fee ) internal { IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message); } /** * @notice Sends a message to an app on another chain via MessageBus with an associated transfer. * @param _receiver The address of the destination app contract. * @param _token The address of the token to be sent. * @param _amount The amount of tokens to be sent. * @param _dstChainId The destination chain ID. * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice. * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%. * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the * transfer can be refunded. Only applicable to the {MsgDataTypes.BridgeSendType.Liquidity}. * @param _message Arbitrary message bytes to be decoded by the destination app contract. * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum. * @param _messageBus The address of the MessageBus on this chain. * @param _fee The fee amount to pay to MessageBus. * @return The transfer ID. */ function sendMessageWithTransfer( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSlippage, bytes memory _message, MsgDataTypes.BridgeSendType _bridgeSendType, address _messageBus, uint256 _fee ) internal returns (bytes32) { (bytes32 transferId, address bridge) = sendTokenTransfer( _receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage, _bridgeSendType, _messageBus ); if (_message.length > 0) { IMessageBus(_messageBus).sendMessageWithTransfer{value: _fee}( _receiver, _dstChainId, bridge, transferId, _message ); } return transferId; } /** * @notice Sends a token transfer via a bridge. * @param _receiver The address of the destination app contract. * @param _token The address of the token to be sent. * @param _amount The amount of tokens to be sent. * @param _dstChainId The destination chain ID. * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice. * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%. * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the * transfer can be refunded. * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum. */ function sendTokenTransfer( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSlippage, MsgDataTypes.BridgeSendType _bridgeSendType, address _messageBus ) internal returns (bytes32 transferId, address bridge) { if (_bridgeSendType == MsgDataTypes.BridgeSendType.Liquidity) { bridge = IMessageBus(_messageBus).liquidityBridge(); IERC20(_token).safeIncreaseAllowance(bridge, _amount); IBridge(bridge).send(_receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage); transferId = computeLiqBridgeTransferId(_receiver, _token, _amount, _dstChainId, _nonce); } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegDeposit) { bridge = IMessageBus(_messageBus).pegVault(); IERC20(_token).safeIncreaseAllowance(bridge, _amount); IOriginalTokenVault(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce); transferId = computePegV1DepositId(_receiver, _token, _amount, _dstChainId, _nonce); } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegBurn) { bridge = IMessageBus(_messageBus).pegBridge(); IERC20(_token).safeIncreaseAllowance(bridge, _amount); IPeggedTokenBridge(bridge).burn(_token, _amount, _receiver, _nonce); // handle cases where certain tokens do not spend allowance for role-based burn IERC20(_token).safeApprove(bridge, 0); transferId = computePegV1BurnId(_receiver, _token, _amount, _nonce); } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Deposit) { bridge = IMessageBus(_messageBus).pegVaultV2(); IERC20(_token).safeIncreaseAllowance(bridge, _amount); transferId = IOriginalTokenVaultV2(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce); } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Burn) { bridge = IMessageBus(_messageBus).pegBridgeV2(); IERC20(_token).safeIncreaseAllowance(bridge, _amount); transferId = IPeggedTokenBridgeV2(bridge).burn(_token, _amount, _dstChainId, _receiver, _nonce); // handle cases where certain tokens do not spend allowance for role-based burn IERC20(_token).safeApprove(bridge, 0); } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2BurnFrom) { bridge = IMessageBus(_messageBus).pegBridgeV2(); IERC20(_token).safeIncreaseAllowance(bridge, _amount); transferId = IPeggedTokenBridgeV2(bridge).burnFrom(_token, _amount, _dstChainId, _receiver, _nonce); // handle cases where certain tokens do not spend allowance for role-based burn IERC20(_token).safeApprove(bridge, 0); } else { revert("bridge type not supported"); } } function computeLiqBridgeTransferId( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce ) internal view returns (bytes32) { return keccak256( abi.encodePacked(address(this), _receiver, _token, _amount, _dstChainId, _nonce, uint64(block.chainid)) ); } function computePegV1DepositId( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce ) internal view returns (bytes32) { return keccak256( abi.encodePacked(address(this), _token, _amount, _dstChainId, _receiver, _nonce, uint64(block.chainid)) ); } function computePegV1BurnId( address _receiver, address _token, uint256 _amount, uint64 _nonce ) internal view returns (bytes32) { return keccak256(abi.encodePacked(address(this), _token, _amount, _receiver, _nonce, uint64(block.chainid))); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; interface IBridge { function send( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSlippage ) external; function sendNative( address _receiver, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSlippage ) external payable; function relay( bytes calldata _relayRequest, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external; function transfers(bytes32 transferId) external view returns (bool); function withdraws(bytes32 withdrawId) external view returns (bool); function withdraw( bytes calldata _wdmsg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external; /** * @notice Verifies that a message is signed by a quorum among the signers. * @param _msg signed message * @param _sigs list of signatures sorted by signer addresses in ascending order * @param _signers sorted list of current signers * @param _powers powers of current signers */ function verifySigs( bytes memory _msg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external view; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; interface IOriginalTokenVault { /** * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge * @param _token local token address * @param _amount locked token amount * @param _mintChainId destination chainId to mint tokens * @param _mintAccount destination account to receive minted tokens * @param _nonce user input to guarantee unique depositId */ function deposit( address _token, uint256 _amount, uint64 _mintChainId, address _mintAccount, uint64 _nonce ) external; /** * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge * @param _amount locked token amount * @param _mintChainId destination chainId to mint tokens * @param _mintAccount destination account to receive minted tokens * @param _nonce user input to guarantee unique depositId */ function depositNative( uint256 _amount, uint64 _mintChainId, address _mintAccount, uint64 _nonce ) external payable; /** * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge. * @param _request The serialized Withdraw protobuf. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the bridge's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function withdraw( bytes calldata _request, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external; function records(bytes32 recordId) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; interface IOriginalTokenVaultV2 { /** * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge * @param _token local token address * @param _amount locked token amount * @param _mintChainId destination chainId to mint tokens * @param _mintAccount destination account to receive minted tokens * @param _nonce user input to guarantee unique depositId */ function deposit( address _token, uint256 _amount, uint64 _mintChainId, address _mintAccount, uint64 _nonce ) external returns (bytes32); /** * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge * @param _amount locked token amount * @param _mintChainId destination chainId to mint tokens * @param _mintAccount destination account to receive minted tokens * @param _nonce user input to guarantee unique depositId */ function depositNative( uint256 _amount, uint64 _mintChainId, address _mintAccount, uint64 _nonce ) external payable returns (bytes32); /** * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge. * @param _request The serialized Withdraw protobuf. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the bridge's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function withdraw( bytes calldata _request, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external returns (bytes32); function records(bytes32 recordId) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; interface IPeggedTokenBridge { /** * @notice Burn tokens to trigger withdrawal at a remote chain's OriginalTokenVault * @param _token local token address * @param _amount locked token amount * @param _withdrawAccount account who withdraw original tokens on the remote chain * @param _nonce user input to guarantee unique depositId */ function burn( address _token, uint256 _amount, address _withdrawAccount, uint64 _nonce ) external; /** * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault. * @param _request The serialized Mint protobuf. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function mint( bytes calldata _request, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external; function records(bytes32 recordId) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; interface IPeggedTokenBridgeV2 { /** * @notice Burn pegged tokens to trigger a cross-chain withdrawal of the original tokens at a remote chain's * OriginalTokenVault, or mint at another remote chain * @param _token The pegged token address. * @param _amount The amount to burn. * @param _toChainId If zero, withdraw from original vault; otherwise, the remote chain to mint tokens. * @param _toAccount The account to receive tokens on the remote chain * @param _nonce A number to guarantee unique depositId. Can be timestamp in practice. */ function burn( address _token, uint256 _amount, uint64 _toChainId, address _toAccount, uint64 _nonce ) external returns (bytes32); // same with `burn` above, use openzeppelin ERC20Burnable interface function burnFrom( address _token, uint256 _amount, uint64 _toChainId, address _toAccount, uint64 _nonce ) external returns (bytes32); /** * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault. * @param _request The serialized Mint protobuf. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function mint( bytes calldata _request, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external returns (bytes32); function records(bytes32 recordId) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; import "../libraries/MsgDataTypes.sol"; interface IMessageBus { /** * @notice Send a message to a contract on another chain. * Sender needs to make sure the uniqueness of the message Id, which is computed as * hash(type.MessageOnly, sender, receiver, srcChainId, srcTxHash, dstChainId, message). * If messages with the same Id are sent, only one of them will succeed at dst chain.. * A fee is charged in the native gas token. * @param _receiver The address of the destination app contract. * @param _dstChainId The destination chain ID. * @param _message Arbitrary message bytes to be decoded by the destination app contract. */ function sendMessage( address _receiver, uint256 _dstChainId, bytes calldata _message ) external payable; // same as above, except that receiver is an non-evm chain address, function sendMessage( bytes calldata _receiver, uint256 _dstChainId, bytes calldata _message ) external payable; /** * @notice Send a message associated with a token transfer to a contract on another chain. * If messages with the same srcTransferId are sent, only one of them will succeed at dst chain.. * A fee is charged in the native token. * @param _receiver The address of the destination app contract. * @param _dstChainId The destination chain ID. * @param _srcBridge The bridge contract to send the transfer with. * @param _srcTransferId The transfer ID. * @param _dstChainId The destination chain ID. * @param _message Arbitrary message bytes to be decoded by the destination app contract. */ function sendMessageWithTransfer( address _receiver, uint256 _dstChainId, address _srcBridge, bytes32 _srcTransferId, bytes calldata _message ) external payable; /** * @notice Execute a message not associated with a transfer. * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function executeMessage( bytes calldata _message, MsgDataTypes.RouteInfo calldata _route, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external payable; /** * @notice Execute a message with a successful transfer. * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _transfer The transfer info. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function executeMessageWithTransfer( bytes calldata _message, MsgDataTypes.TransferInfo calldata _transfer, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external payable; /** * @notice Execute a message with a refunded transfer. * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _transfer The transfer info. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function executeMessageWithTransferRefund( bytes calldata _message, // the same message associated with the original transfer MsgDataTypes.TransferInfo calldata _transfer, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external payable; /** * @notice Withdraws message fee in the form of native gas token. * @param _account The address receiving the fee. * @param _cumulativeFee The cumulative fee credited to the account. Tracked by SGN. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A withdrawal must be * signed-off by +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function withdrawFee( address _account, uint256 _cumulativeFee, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external; /** * @notice Calculates the required fee for the message. * @param _message Arbitrary message bytes to be decoded by the destination app contract. @ @return The required fee. */ function calcFee(bytes calldata _message) external view returns (uint256); function liquidityBridge() external view returns (address); function pegBridge() external view returns (address); function pegBridgeV2() external view returns (address); function pegVault() external view returns (address); function pegVaultV2() external view returns (address); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; import "./MessageBusSender.sol"; import "./MessageBusReceiver.sol"; contract MessageBus is MessageBusSender, MessageBusReceiver { constructor( ISigsVerifier _sigsVerifier, address _liquidityBridge, address _pegBridge, address _pegVault, address _pegBridgeV2, address _pegVaultV2 ) MessageBusSender(_sigsVerifier) MessageBusReceiver(_liquidityBridge, _pegBridge, _pegVault, _pegBridgeV2, _pegVaultV2) {} // this is only to be called by Proxy via delegateCall as initOwner will require _owner is 0. // so calling init on this contract directly will guarantee to fail function init( address _liquidityBridge, address _pegBridge, address _pegVault, address _pegBridgeV2, address _pegVaultV2 ) external { // MUST manually call ownable init and must only call once initOwner(); // we don't need sender init as _sigsVerifier is immutable so already in the deployed code initReceiver(_liquidityBridge, _pegBridge, _pegVault, _pegBridgeV2, _pegVaultV2); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; import "../../safeguard/Ownable.sol"; import "../../interfaces/ISigsVerifier.sol"; contract MessageBusSender is Ownable { ISigsVerifier public immutable sigsVerifier; uint256 public feeBase; uint256 public feePerByte; mapping(address => uint256) public withdrawnFees; event Message(address indexed sender, address receiver, uint256 dstChainId, bytes message, uint256 fee); // message to non-evm chain with >20 bytes addr event Message2(address indexed sender, bytes receiver, uint256 dstChainId, bytes message, uint256 fee); event MessageWithTransfer( address indexed sender, address receiver, uint256 dstChainId, address bridge, bytes32 srcTransferId, bytes message, uint256 fee ); event FeeWithdrawn(address receiver, uint256 amount); event FeeBaseUpdated(uint256 feeBase); event FeePerByteUpdated(uint256 feePerByte); constructor(ISigsVerifier _sigsVerifier) { sigsVerifier = _sigsVerifier; } /** * @notice Sends a message to a contract on another chain. * Sender needs to make sure the uniqueness of the message Id, which is computed as * hash(type.MessageOnly, sender, receiver, srcChainId, srcTxHash, dstChainId, message). * If messages with the same Id are sent, only one of them will succeed at dst chain. * A fee is charged in the native gas token. * @param _receiver The address of the destination app contract. * @param _dstChainId The destination chain ID. * @param _message Arbitrary message bytes to be decoded by the destination app contract. */ function sendMessage( address _receiver, uint256 _dstChainId, bytes calldata _message ) external payable { _sendMessage(_dstChainId, _message); emit Message(msg.sender, _receiver, _dstChainId, _message, msg.value); } // Send message to non-evm chain with bytes for receiver address, // otherwise same as above. function sendMessage( bytes calldata _receiver, uint256 _dstChainId, bytes calldata _message ) external payable { _sendMessage(_dstChainId, _message); emit Message2(msg.sender, _receiver, _dstChainId, _message, msg.value); } function _sendMessage(uint256 _dstChainId, bytes calldata _message) private { require(_dstChainId != block.chainid, "Invalid chainId"); uint256 minFee = calcFee(_message); require(msg.value >= minFee, "Insufficient fee"); } /** * @notice Sends a message associated with a transfer to a contract on another chain. * If messages with the same srcTransferId are sent, only one of them will succeed. * A fee is charged in the native token. * @param _receiver The address of the destination app contract. * @param _dstChainId The destination chain ID. * @param _srcBridge The bridge contract to send the transfer with. * @param _srcTransferId The transfer ID. * @param _dstChainId The destination chain ID. * @param _message Arbitrary message bytes to be decoded by the destination app contract. */ function sendMessageWithTransfer( address _receiver, uint256 _dstChainId, address _srcBridge, bytes32 _srcTransferId, bytes calldata _message ) external payable { require(_dstChainId != block.chainid, "Invalid chainId"); uint256 minFee = calcFee(_message); require(msg.value >= minFee, "Insufficient fee"); // SGN needs to verify // 1. msg.sender matches sender of the src transfer // 2. dstChainId matches dstChainId of the src transfer // 3. bridge is either liquidity bridge, peg src vault, or peg dst bridge emit MessageWithTransfer(msg.sender, _receiver, _dstChainId, _srcBridge, _srcTransferId, _message, msg.value); } /** * @notice Withdraws message fee in the form of native gas token. * @param _account The address receiving the fee. * @param _cumulativeFee The cumulative fee credited to the account. Tracked by SGN. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A withdrawal must be * signed-off by +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function withdrawFee( address _account, uint256 _cumulativeFee, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external { bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "withdrawFee")); sigsVerifier.verifySigs(abi.encodePacked(domain, _account, _cumulativeFee), _sigs, _signers, _powers); uint256 amount = _cumulativeFee - withdrawnFees[_account]; require(amount > 0, "No new amount to withdraw"); withdrawnFees[_account] = _cumulativeFee; (bool sent, ) = _account.call{value: amount, gas: 50000}(""); require(sent, "failed to withdraw fee"); emit FeeWithdrawn(_account, amount); } /** * @notice Calculates the required fee for the message. * @param _message Arbitrary message bytes to be decoded by the destination app contract. @ @return The required fee. */ function calcFee(bytes calldata _message) public view returns (uint256) { return feeBase + _message.length * feePerByte; } // -------------------- Admin -------------------- function setFeePerByte(uint256 _fee) external onlyOwner { feePerByte = _fee; emit FeePerByteUpdated(feePerByte); } function setFeeBase(uint256 _fee) external onlyOwner { feeBase = _fee; emit FeeBaseUpdated(feeBase); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. * * This adds a normal func that setOwner if _owner is address(0). So we can't allow * renounceOwnership. So we can support Proxy based upgradable contract */ abstract contract Ownable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(msg.sender); } /** * @dev Only to be called by inherit contracts, in their init func called by Proxy * we require _owner == address(0), which is only possible when it's a delegateCall * because constructor sets _owner in contract state. */ function initOwner() internal { require(_owner == address(0), "owner already set"); _setOwner(msg.sender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == msg.sender, "Ownable: caller is not the owner"); _; } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; interface ISigsVerifier { /** * @notice Verifies that a message is signed by a quorum among the signers. * @param _msg signed message * @param _sigs list of signatures sorted by signer addresses in ascending order * @param _signers sorted list of current signers * @param _powers powers of current signers */ function verifySigs( bytes memory _msg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external view; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.9; import "../libraries/MsgDataTypes.sol"; import "../interfaces/IMessageReceiverApp.sol"; import "../../interfaces/IBridge.sol"; import "../../interfaces/IOriginalTokenVault.sol"; import "../../interfaces/IOriginalTokenVaultV2.sol"; import "../../interfaces/IPeggedTokenBridge.sol"; import "../../interfaces/IPeggedTokenBridgeV2.sol"; import "../../safeguard/Ownable.sol"; import "../../libraries/Utils.sol"; contract MessageBusReceiver is Ownable { mapping(bytes32 => MsgDataTypes.TxStatus) public executedMessages; address public liquidityBridge; // liquidity bridge address address public pegBridge; // peg bridge address address public pegVault; // peg original vault address address public pegBridgeV2; // peg bridge address address public pegVaultV2; // peg original vault address // minimum amount of gas needed by this contract before it tries to // deliver a message to the target contract. uint256 public preExecuteMessageGasUsage; event Executed( MsgDataTypes.MsgType msgType, bytes32 msgId, MsgDataTypes.TxStatus status, address indexed receiver, uint64 srcChainId, bytes32 srcTxHash ); event NeedRetry(MsgDataTypes.MsgType msgType, bytes32 msgId, uint64 srcChainId, bytes32 srcTxHash); event CallReverted(string reason); // help debug event LiquidityBridgeUpdated(address liquidityBridge); event PegBridgeUpdated(address pegBridge); event PegVaultUpdated(address pegVault); event PegBridgeV2Updated(address pegBridgeV2); event PegVaultV2Updated(address pegVaultV2); constructor( address _liquidityBridge, address _pegBridge, address _pegVault, address _pegBridgeV2, address _pegVaultV2 ) { liquidityBridge = _liquidityBridge; pegBridge = _pegBridge; pegVault = _pegVault; pegBridgeV2 = _pegBridgeV2; pegVaultV2 = _pegVaultV2; } function initReceiver( address _liquidityBridge, address _pegBridge, address _pegVault, address _pegBridgeV2, address _pegVaultV2 ) internal { require(liquidityBridge == address(0), "liquidityBridge already set"); liquidityBridge = _liquidityBridge; pegBridge = _pegBridge; pegVault = _pegVault; pegBridgeV2 = _pegBridgeV2; pegVaultV2 = _pegVaultV2; } // ============== functions called by executor ============== /** * @notice Execute a message with a successful transfer. * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _transfer The transfer info. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function executeMessageWithTransfer( bytes calldata _message, MsgDataTypes.TransferInfo calldata _transfer, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) public payable { // For message with token transfer, message Id is computed through transfer info // in order to guarantee that each transfer can only be used once. bytes32 messageId = verifyTransfer(_transfer); require(executedMessages[messageId] == MsgDataTypes.TxStatus.Null, "transfer already executed"); executedMessages[messageId] = MsgDataTypes.TxStatus.Pending; bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "MessageWithTransfer")); IBridge(liquidityBridge).verifySigs( abi.encodePacked(domain, messageId, _message, _transfer.srcTxHash), _sigs, _signers, _powers ); MsgDataTypes.TxStatus status; IMessageReceiverApp.ExecutionStatus est = executeMessageWithTransfer(_transfer, _message); if (est == IMessageReceiverApp.ExecutionStatus.Success) { status = MsgDataTypes.TxStatus.Success; } else if (est == IMessageReceiverApp.ExecutionStatus.Retry) { executedMessages[messageId] = MsgDataTypes.TxStatus.Null; emit NeedRetry( MsgDataTypes.MsgType.MessageWithTransfer, messageId, _transfer.srcChainId, _transfer.srcTxHash ); return; } else { est = executeMessageWithTransferFallback(_transfer, _message); if (est == IMessageReceiverApp.ExecutionStatus.Success) { status = MsgDataTypes.TxStatus.Fallback; } else { status = MsgDataTypes.TxStatus.Fail; } } executedMessages[messageId] = status; emitMessageWithTransferExecutedEvent(messageId, status, _transfer); } /** * @notice Execute a message with a refunded transfer. * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _transfer The transfer info. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function executeMessageWithTransferRefund( bytes calldata _message, // the same message associated with the original transfer MsgDataTypes.TransferInfo calldata _transfer, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) public payable { // similar to executeMessageWithTransfer bytes32 messageId = verifyTransfer(_transfer); require(executedMessages[messageId] == MsgDataTypes.TxStatus.Null, "transfer already executed"); executedMessages[messageId] = MsgDataTypes.TxStatus.Pending; bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "MessageWithTransferRefund")); IBridge(liquidityBridge).verifySigs( abi.encodePacked(domain, messageId, _message, _transfer.srcTxHash), _sigs, _signers, _powers ); MsgDataTypes.TxStatus status; IMessageReceiverApp.ExecutionStatus est = executeMessageWithTransferRefund(_transfer, _message); if (est == IMessageReceiverApp.ExecutionStatus.Success) { status = MsgDataTypes.TxStatus.Success; } else if (est == IMessageReceiverApp.ExecutionStatus.Retry) { executedMessages[messageId] = MsgDataTypes.TxStatus.Null; emit NeedRetry( MsgDataTypes.MsgType.MessageWithTransfer, messageId, _transfer.srcChainId, _transfer.srcTxHash ); return; } else { status = MsgDataTypes.TxStatus.Fail; } executedMessages[messageId] = status; emitMessageWithTransferExecutedEvent(messageId, status, _transfer); } /** * @notice Execute a message not associated with a transfer. * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _route The info about the sender and the receiver. * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by * +2/3 of the sigsVerifier's current signing power to be delivered. * @param _signers The sorted list of signers. * @param _powers The signing powers of the signers. */ function executeMessage( bytes calldata _message, MsgDataTypes.RouteInfo calldata _route, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external payable { MsgDataTypes.Route memory route = getRouteInfo(_route); executeMessage(_message, route, _sigs, _signers, _powers, "Message"); } // execute message from non-evm chain with bytes for sender address, // otherwise same as above. function executeMessage( bytes calldata _message, MsgDataTypes.RouteInfo2 calldata _route, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external payable { MsgDataTypes.Route memory route = getRouteInfo(_route); executeMessage(_message, route, _sigs, _signers, _powers, "Message2"); } function executeMessage( bytes calldata _message, MsgDataTypes.Route memory _route, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers, string memory domainName ) private { // For message without associated token transfer, message Id is computed through message info, // in order to guarantee that each message can only be applied once bytes32 messageId = computeMessageOnlyId(_route, _message); require(executedMessages[messageId] == MsgDataTypes.TxStatus.Null, "message already executed"); executedMessages[messageId] = MsgDataTypes.TxStatus.Pending; bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), domainName)); IBridge(liquidityBridge).verifySigs(abi.encodePacked(domain, messageId), _sigs, _signers, _powers); MsgDataTypes.TxStatus status; IMessageReceiverApp.ExecutionStatus est = executeMessage(_route, _message); if (est == IMessageReceiverApp.ExecutionStatus.Success) { status = MsgDataTypes.TxStatus.Success; } else if (est == IMessageReceiverApp.ExecutionStatus.Retry) { executedMessages[messageId] = MsgDataTypes.TxStatus.Null; emit NeedRetry(MsgDataTypes.MsgType.MessageOnly, messageId, _route.srcChainId, _route.srcTxHash); return; } else { status = MsgDataTypes.TxStatus.Fail; } executedMessages[messageId] = status; emitMessageOnlyExecutedEvent(messageId, status, _route); } // ================= utils (to avoid stack too deep) ================= function emitMessageWithTransferExecutedEvent( bytes32 _messageId, MsgDataTypes.TxStatus _status, MsgDataTypes.TransferInfo calldata _transfer ) private { emit Executed( MsgDataTypes.MsgType.MessageWithTransfer, _messageId, _status, _transfer.receiver, _transfer.srcChainId, _transfer.srcTxHash ); } function emitMessageOnlyExecutedEvent( bytes32 _messageId, MsgDataTypes.TxStatus _status, MsgDataTypes.Route memory _route ) private { emit Executed( MsgDataTypes.MsgType.MessageOnly, _messageId, _status, _route.receiver, _route.srcChainId, _route.srcTxHash ); } function executeMessageWithTransfer(MsgDataTypes.TransferInfo calldata _transfer, bytes calldata _message) private returns (IMessageReceiverApp.ExecutionStatus) { uint256 gasLeftBeforeExecution = gasleft(); (bool ok, bytes memory res) = address(_transfer.receiver).call{value: msg.value}( abi.encodeWithSelector( IMessageReceiverApp.executeMessageWithTransfer.selector, _transfer.sender, _transfer.token, _transfer.amount, _transfer.srcChainId, _message, msg.sender ) ); if (ok) { return abi.decode((res), (IMessageReceiverApp.ExecutionStatus)); } handleExecutionRevert(gasLeftBeforeExecution, res); return IMessageReceiverApp.ExecutionStatus.Fail; } function executeMessageWithTransferFallback(MsgDataTypes.TransferInfo calldata _transfer, bytes calldata _message) private returns (IMessageReceiverApp.ExecutionStatus) { uint256 gasLeftBeforeExecution = gasleft(); (bool ok, bytes memory res) = address(_transfer.receiver).call{value: msg.value}( abi.encodeWithSelector( IMessageReceiverApp.executeMessageWithTransferFallback.selector, _transfer.sender, _transfer.token, _transfer.amount, _transfer.srcChainId, _message, msg.sender ) ); if (ok) { return abi.decode((res), (IMessageReceiverApp.ExecutionStatus)); } handleExecutionRevert(gasLeftBeforeExecution, res); return IMessageReceiverApp.ExecutionStatus.Fail; } function executeMessageWithTransferRefund(MsgDataTypes.TransferInfo calldata _transfer, bytes calldata _message) private returns (IMessageReceiverApp.ExecutionStatus) { uint256 gasLeftBeforeExecution = gasleft(); (bool ok, bytes memory res) = address(_transfer.receiver).call{value: msg.value}( abi.encodeWithSelector( IMessageReceiverApp.executeMessageWithTransferRefund.selector, _transfer.token, _transfer.amount, _message, msg.sender ) ); if (ok) { return abi.decode((res), (IMessageReceiverApp.ExecutionStatus)); } handleExecutionRevert(gasLeftBeforeExecution, res); return IMessageReceiverApp.ExecutionStatus.Fail; } function verifyTransfer(MsgDataTypes.TransferInfo calldata _transfer) private view returns (bytes32) { bytes32 transferId; address bridgeAddr; if (_transfer.t == MsgDataTypes.TransferType.LqRelay) { transferId = keccak256( abi.encodePacked( _transfer.sender, _transfer.receiver, _transfer.token, _transfer.amount, _transfer.srcChainId, uint64(block.chainid), _transfer.refId ) ); bridgeAddr = liquidityBridge; require(IBridge(bridgeAddr).transfers(transferId) == true, "bridge relay not exist"); } else if (_transfer.t == MsgDataTypes.TransferType.LqWithdraw) { transferId = keccak256( abi.encodePacked( uint64(block.chainid), _transfer.wdseq, _transfer.receiver, _transfer.token, _transfer.amount ) ); bridgeAddr = liquidityBridge; require(IBridge(bridgeAddr).withdraws(transferId) == true, "bridge withdraw not exist"); } else if ( _transfer.t == MsgDataTypes.TransferType.PegMint || _transfer.t == MsgDataTypes.TransferType.PegWithdraw ) { transferId = keccak256( abi.encodePacked( _transfer.receiver, _transfer.token, _transfer.amount, _transfer.sender, _transfer.srcChainId, _transfer.refId ) ); if (_transfer.t == MsgDataTypes.TransferType.PegMint) { bridgeAddr = pegBridge; require(IPeggedTokenBridge(bridgeAddr).records(transferId) == true, "mint record not exist"); } else { // _transfer.t == MsgDataTypes.TransferType.PegWithdraw bridgeAddr = pegVault; require(IOriginalTokenVault(bridgeAddr).records(transferId) == true, "withdraw record not exist"); } } else if ( _transfer.t == MsgDataTypes.TransferType.PegV2Mint || _transfer.t == MsgDataTypes.TransferType.PegV2Withdraw ) { if (_transfer.t == MsgDataTypes.TransferType.PegV2Mint) { bridgeAddr = pegBridgeV2; } else { // MsgDataTypes.TransferType.PegV2Withdraw bridgeAddr = pegVaultV2; } transferId = keccak256( abi.encodePacked( _transfer.receiver, _transfer.token, _transfer.amount, _transfer.sender, _transfer.srcChainId, _transfer.refId, bridgeAddr ) ); if (_transfer.t == MsgDataTypes.TransferType.PegV2Mint) { require(IPeggedTokenBridgeV2(bridgeAddr).records(transferId) == true, "mint record not exist"); } else { // MsgDataTypes.TransferType.PegV2Withdraw require(IOriginalTokenVaultV2(bridgeAddr).records(transferId) == true, "withdraw record not exist"); } } return keccak256(abi.encodePacked(MsgDataTypes.MsgType.MessageWithTransfer, bridgeAddr, transferId)); } function computeMessageOnlyId(MsgDataTypes.Route memory _route, bytes calldata _message) private view returns (bytes32) { bytes memory sender = _route.senderBytes; if (sender.length == 0) { sender = abi.encodePacked(_route.sender); } return keccak256( abi.encodePacked( MsgDataTypes.MsgType.MessageOnly, sender, _route.receiver, _route.srcChainId, _route.srcTxHash, uint64(block.chainid), _message ) ); } function executeMessage(MsgDataTypes.Route memory _route, bytes calldata _message) private returns (IMessageReceiverApp.ExecutionStatus) { uint256 gasLeftBeforeExecution = gasleft(); bool ok; bytes memory res; if (_route.senderBytes.length == 0) { (ok, res) = address(_route.receiver).call{value: msg.value}( abi.encodeWithSelector( bytes4(keccak256(bytes("executeMessage(address,uint64,bytes,address)"))), _route.sender, _route.srcChainId, _message, msg.sender ) ); } else { (ok, res) = address(_route.receiver).call{value: msg.value}( abi.encodeWithSelector( bytes4(keccak256(bytes("executeMessage(bytes,uint64,bytes,address)"))), _route.senderBytes, _route.srcChainId, _message, msg.sender ) ); } if (ok) { return abi.decode((res), (IMessageReceiverApp.ExecutionStatus)); } handleExecutionRevert(gasLeftBeforeExecution, res); return IMessageReceiverApp.ExecutionStatus.Fail; } function handleExecutionRevert(uint256 _gasLeftBeforeExecution, bytes memory _returnData) private { uint256 gasLeftAfterExecution = gasleft(); uint256 maxTargetGasLimit = block.gaslimit - preExecuteMessageGasUsage; if (_gasLeftBeforeExecution < maxTargetGasLimit && gasLeftAfterExecution <= _gasLeftBeforeExecution / 64) { // if this happens, the executor must have not provided sufficient gas limit, // then the tx should revert instead of recording a non-retryable failure status // https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-f-gas-to-send-with-call-operations assembly { invalid() } } string memory revertMsg = Utils.getRevertMsg(_returnData); // revert the execution if the revert message has the ABORT prefix checkAbortPrefix(revertMsg); // otherwiase, emit revert message, return and mark the execution as failed (non-retryable) emit CallReverted(revertMsg); } function checkAbortPrefix(string memory _revertMsg) private pure { bytes memory prefixBytes = bytes(MsgDataTypes.ABORT_PREFIX); bytes memory msgBytes = bytes(_revertMsg); if (msgBytes.length >= prefixBytes.length) { for (uint256 i = 0; i < prefixBytes.length; i++) { if (msgBytes[i] != prefixBytes[i]) { return; // prefix not match, return } } revert(_revertMsg); // prefix match, revert } } function getRouteInfo(MsgDataTypes.RouteInfo calldata _route) private pure returns (MsgDataTypes.Route memory) { return MsgDataTypes.Route(_route.sender, "", _route.receiver, _route.srcChainId, _route.srcTxHash); } function getRouteInfo(MsgDataTypes.RouteInfo2 calldata _route) private pure returns (MsgDataTypes.Route memory) { return MsgDataTypes.Route(address(0), _route.sender, _route.receiver, _route.srcChainId, _route.srcTxHash); } // ================= helper functions ===================== /** * @notice combine bridge transfer and msg execution calls into a single tx * @dev caller needs to get the required input params from SGN * @param _transferParams params to call bridge transfer * @param _msgParams params to execute message */ function transferAndExecuteMsg( MsgDataTypes.BridgeTransferParams calldata _transferParams, MsgDataTypes.MsgWithTransferExecutionParams calldata _msgParams ) external { _bridgeTransfer(_msgParams.transfer.t, _transferParams); executeMessageWithTransfer( _msgParams.message, _msgParams.transfer, _msgParams.sigs, _msgParams.signers, _msgParams.powers ); } /** * @notice combine bridge refund and msg execution calls into a single tx * @dev caller needs to get the required input params from SGN * @param _transferParams params to call bridge transfer for refund * @param _msgParams params to execute message for refund */ function refundAndExecuteMsg( MsgDataTypes.BridgeTransferParams calldata _transferParams, MsgDataTypes.MsgWithTransferExecutionParams calldata _msgParams ) external { _bridgeTransfer(_msgParams.transfer.t, _transferParams); executeMessageWithTransferRefund( _msgParams.message, _msgParams.transfer, _msgParams.sigs, _msgParams.signers, _msgParams.powers ); } function _bridgeTransfer(MsgDataTypes.TransferType t, MsgDataTypes.BridgeTransferParams calldata _transferParams) private { if (t == MsgDataTypes.TransferType.LqRelay) { IBridge(liquidityBridge).relay( _transferParams.request, _transferParams.sigs, _transferParams.signers, _transferParams.powers ); } else if (t == MsgDataTypes.TransferType.LqWithdraw) { IBridge(liquidityBridge).withdraw( _transferParams.request, _transferParams.sigs, _transferParams.signers, _transferParams.powers ); } else if (t == MsgDataTypes.TransferType.PegMint) { IPeggedTokenBridge(pegBridge).mint( _transferParams.request, _transferParams.sigs, _transferParams.signers, _transferParams.powers ); } else if (t == MsgDataTypes.TransferType.PegV2Mint) { IPeggedTokenBridgeV2(pegBridgeV2).mint( _transferParams.request, _transferParams.sigs, _transferParams.signers, _transferParams.powers ); } else if (t == MsgDataTypes.TransferType.PegWithdraw) { IOriginalTokenVault(pegVault).withdraw( _transferParams.request, _transferParams.sigs, _transferParams.signers, _transferParams.powers ); } else if (t == MsgDataTypes.TransferType.PegV2Withdraw) { IOriginalTokenVaultV2(pegVaultV2).withdraw( _transferParams.request, _transferParams.sigs, _transferParams.signers, _transferParams.powers ); } } // ================= contract config ================= function setLiquidityBridge(address _addr) public onlyOwner { require(_addr != address(0), "invalid address"); liquidityBridge = _addr; emit LiquidityBridgeUpdated(liquidityBridge); } function setPegBridge(address _addr) public onlyOwner { require(_addr != address(0), "invalid address"); pegBridge = _addr; emit PegBridgeUpdated(pegBridge); } function setPegVault(address _addr) public onlyOwner { require(_addr != address(0), "invalid address"); pegVault = _addr; emit PegVaultUpdated(pegVault); } function setPegBridgeV2(address _addr) public onlyOwner { require(_addr != address(0), "invalid address"); pegBridgeV2 = _addr; emit PegBridgeV2Updated(pegBridgeV2); } function setPegVaultV2(address _addr) public onlyOwner { require(_addr != address(0), "invalid address"); pegVaultV2 = _addr; emit PegVaultV2Updated(pegVaultV2); } function setPreExecuteMessageGasUsage(uint256 _usage) public onlyOwner { preExecuteMessageGasUsage = _usage; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; interface IMessageReceiverApp { enum ExecutionStatus { Fail, // execution failed, finalized Success, // execution succeeded, finalized Retry // execution rejected, can retry later } /** * @notice Called by MessageBus to execute a message * @param _sender The address of the source app contract * @param _srcChainId The source chain ID where the transfer is originated from * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _executor Address who called the MessageBus execution function */ function executeMessage( address _sender, uint64 _srcChainId, bytes calldata _message, address _executor ) external payable returns (ExecutionStatus); // same as above, except that sender is an non-evm chain address, // otherwise same as above. function executeMessage( bytes calldata _sender, uint64 _srcChainId, bytes calldata _message, address _executor ) external payable returns (ExecutionStatus); /** * @notice Called by MessageBus to execute a message with an associated token transfer. * The contract is guaranteed to have received the right amount of tokens before this function is called. * @param _sender The address of the source app contract * @param _token The address of the token that comes out of the bridge * @param _amount The amount of tokens received at this contract through the cross-chain bridge. * @param _srcChainId The source chain ID where the transfer is originated from * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _executor Address who called the MessageBus execution function */ function executeMessageWithTransfer( address _sender, address _token, uint256 _amount, uint64 _srcChainId, bytes calldata _message, address _executor ) external payable returns (ExecutionStatus); /** * @notice Only called by MessageBus if * 1. executeMessageWithTransfer reverts, or * 2. executeMessageWithTransfer returns ExecutionStatus.Fail * The contract is guaranteed to have received the right amount of tokens before this function is called. * @param _sender The address of the source app contract * @param _token The address of the token that comes out of the bridge * @param _amount The amount of tokens received at this contract through the cross-chain bridge. * @param _srcChainId The source chain ID where the transfer is originated from * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _executor Address who called the MessageBus execution function */ function executeMessageWithTransferFallback( address _sender, address _token, uint256 _amount, uint64 _srcChainId, bytes calldata _message, address _executor ) external payable returns (ExecutionStatus); /** * @notice Called by MessageBus to process refund of the original transfer from this contract. * The contract is guaranteed to have received the refund before this function is called. * @param _token The token address of the original transfer * @param _amount The amount of the original transfer * @param _message The same message associated with the original transfer * @param _executor Address who called the MessageBus execution function */ function executeMessageWithTransferRefund( address _token, uint256 _amount, bytes calldata _message, address _executor ) external payable returns (ExecutionStatus); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; library Utils { // https://ethereum.stackexchange.com/a/83577 // https://github.com/Uniswap/v3-periphery/blob/v1.0.0/contracts/base/Multicall.sol function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (_returnData.length < 68) return "Transaction reverted silently"; assembly { // Slice the sighash. _returnData := add(_returnData, 0x04) } return abi.decode(_returnData, (string)); // All that remains is the revert string } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; import "../../safeguard/Ownable.sol"; abstract contract MessageBusAddress is Ownable { event MessageBusUpdated(address messageBus); address public messageBus; function setMessageBus(address _messageBus) public onlyOwner { messageBus = _messageBus; emit MessageBusUpdated(messageBus); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; import "../interfaces/IMessageReceiverApp.sol"; import "./MessageBusAddress.sol"; abstract contract MessageReceiverApp is IMessageReceiverApp, MessageBusAddress { modifier onlyMessageBus() { require(msg.sender == messageBus, "caller is not message bus"); _; } /** * @notice Called by MessageBus to execute a message * @param _sender The address of the source app contract * @param _srcChainId The source chain ID where the transfer is originated from * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _executor Address who called the MessageBus execution function */ function executeMessage( address _sender, uint64 _srcChainId, bytes calldata _message, address _executor ) external payable virtual override onlyMessageBus returns (ExecutionStatus) {} // execute message from non-evm chain with bytes for sender address, // otherwise same as above. function executeMessage( bytes calldata _sender, uint64 _srcChainId, bytes calldata _message, address _executor ) external payable virtual override onlyMessageBus returns (ExecutionStatus) {} /** * @notice Called by MessageBus to execute a message with an associated token transfer. * The contract is guaranteed to have received the right amount of tokens before this function is called. * @param _sender The address of the source app contract * @param _token The address of the token that comes out of the bridge * @param _amount The amount of tokens received at this contract through the cross-chain bridge. * @param _srcChainId The source chain ID where the transfer is originated from * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _executor Address who called the MessageBus execution function */ function executeMessageWithTransfer( address _sender, address _token, uint256 _amount, uint64 _srcChainId, bytes calldata _message, address _executor ) external payable virtual override onlyMessageBus returns (ExecutionStatus) {} /** * @notice Only called by MessageBus if * 1. executeMessageWithTransfer reverts, or * 2. executeMessageWithTransfer returns ExecutionStatus.Fail * The contract is guaranteed to have received the right amount of tokens before this function is called. * @param _sender The address of the source app contract * @param _token The address of the token that comes out of the bridge * @param _amount The amount of tokens received at this contract through the cross-chain bridge. * @param _srcChainId The source chain ID where the transfer is originated from * @param _message Arbitrary message bytes originated from and encoded by the source app contract * @param _executor Address who called the MessageBus execution function */ function executeMessageWithTransferFallback( address _sender, address _token, uint256 _amount, uint64 _srcChainId, bytes calldata _message, address _executor ) external payable virtual override onlyMessageBus returns (ExecutionStatus) {} /** * @notice Called by MessageBus to process refund of the original transfer from this contract. * The contract is guaranteed to have received the refund before this function is called. * @param _token The token address of the original transfer * @param _amount The amount of the original transfer * @param _message The same message associated with the original transfer * @param _executor Address who called the MessageBus execution function */ function executeMessageWithTransferRefund( address _token, uint256 _amount, bytes calldata _message, address _executor ) external payable virtual override onlyMessageBus returns (ExecutionStatus) {} }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; import "@openzeppelin/contracts/security/Pausable.sol"; import "./Ownable.sol"; abstract contract Pauser is Ownable, Pausable { mapping(address => bool) public pausers; event PauserAdded(address account); event PauserRemoved(address account); constructor() { _addPauser(msg.sender); } modifier onlyPauser() { require(isPauser(msg.sender), "Caller is not pauser"); _; } function pause() public onlyPauser { _pause(); } function unpause() public onlyPauser { _unpause(); } function isPauser(address account) public view returns (bool) { return pausers[account]; } function addPauser(address account) public onlyOwner { _addPauser(account); } function removePauser(address account) public onlyOwner { _removePauser(account); } function renouncePauser() public { _removePauser(msg.sender); } function _addPauser(address account) private { require(!isPauser(account), "Account is already pauser"); pausers[account] = true; emit PauserAdded(account); } function _removePauser(address account) private { require(isPauser(account), "Account is not pauser"); pausers[account] = false; emit PauserRemoved(account); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; import "./Ownable.sol"; abstract contract Governor is Ownable { mapping(address => bool) public governors; event GovernorAdded(address account); event GovernorRemoved(address account); modifier onlyGovernor() { require(isGovernor(msg.sender), "Caller is not governor"); _; } constructor() { _addGovernor(msg.sender); } function isGovernor(address _account) public view returns (bool) { return governors[_account]; } function addGovernor(address _account) public onlyOwner { _addGovernor(_account); } function removeGovernor(address _account) public onlyOwner { _removeGovernor(_account); } function renounceGovernor() public { _removeGovernor(msg.sender); } function _addGovernor(address _account) private { require(!isGovernor(_account), "Account is already governor"); governors[_account] = true; emit GovernorAdded(_account); } function _removeGovernor(address _account) private { require(isGovernor(_account), "Account is not governor"); governors[_account] = false; emit GovernorRemoved(_account); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; interface IWETH { function deposit() external payable; function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "metadata": { "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 800 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_messageBus","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"quoteHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"dstToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DstTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"treasuryAddr","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeeCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64[]","name":"chainIds","type":"uint64[]"},{"indexed":false,"internalType":"uint32[]","name":"feePercs","type":"uint32[]"}],"name":"FeePercUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"GovernorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"GovernorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"messageBus","type":"address"}],"name":"MessageBusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"quoteHash","type":"bytes32"}],"name":"RefundInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"quoteHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"refundTo","type":"address"},{"indexed":false,"internalType":"address","name":"srcToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Refunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64[]","name":"chainIds","type":"uint64[]"},{"indexed":false,"internalType":"address[]","name":"remoteRfqContracts","type":"address[]"}],"name":"RfqContractsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"quoteHash","type":"bytes32"},{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"indexed":false,"internalType":"struct RFQ.Quote","name":"quote","type":"tuple"}],"name":"SrcDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"quoteHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"liquidityProvider","type":"address"},{"indexed":false,"internalType":"address","name":"srcToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SrcReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"treasuryAddr","type":"address"}],"name":"TreasuryAddrUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addPauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"collectFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"}],"name":"dstTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"}],"name":"dstTransferNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"bytes","name":"_sig","type":"bytes"}],"name":"dstTransferWithSig","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_sender","type":"bytes"},{"internalType":"uint64","name":"_srcChainId","type":"uint64"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"}],"name":"executeMessage","outputs":[{"internalType":"enum IMessageReceiverApp.ExecutionStatus","name":"","type":"uint8"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"uint64","name":"_srcChainId","type":"uint64"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"","type":"address"}],"name":"executeMessage","outputs":[{"internalType":"enum IMessageReceiverApp.ExecutionStatus","name":"","type":"uint8"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint64","name":"_srcChainId","type":"uint64"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"}],"name":"executeMessageWithTransfer","outputs":[{"internalType":"enum IMessageReceiverApp.ExecutionStatus","name":"","type":"uint8"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint64","name":"_srcChainId","type":"uint64"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"}],"name":"executeMessageWithTransferFallback","outputs":[{"internalType":"enum IMessageReceiverApp.ExecutionStatus","name":"","type":"uint8"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"}],"name":"executeMessageWithTransferRefund","outputs":[{"internalType":"enum IMessageReceiverApp.ExecutionStatus","name":"","type":"uint8"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"bytes","name":"_execMsgCallData","type":"bytes"}],"name":"executeRefund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"bytes","name":"_execMsgCallData","type":"bytes"}],"name":"executeRefundNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feePercGlobal","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"feePercOverride","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"getMsgFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"}],"name":"getQuoteHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getRfqFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_quoteHash","type":"bytes32"},{"internalType":"bytes","name":"_sig","type":"bytes"}],"name":"getSignerOfQuoteHash","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"governors","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messageBus","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nativeWrap","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pausers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"protocolFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"quotes","outputs":[{"internalType":"enum RFQ.QuoteStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"registerAllowedSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"remoteRfqContracts","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renouncePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"}],"name":"requestRefund","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"bool","name":"_releaseNative","type":"bool"}],"name":"sameChainTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"bool","name":"_releaseNative","type":"bool"}],"name":"sameChainTransferNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"bool","name":"_releaseNative","type":"bool"},{"internalType":"bytes","name":"_sig","type":"bytes"}],"name":"sameChainTransferWithSig","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"_chainIds","type":"uint64[]"},{"internalType":"uint32[]","name":"_feePercs","type":"uint32[]"}],"name":"setFeePerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_messageBus","type":"address"}],"name":"setMessageBus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nativeWrap","type":"address"}],"name":"setNativeWrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"_chainIds","type":"uint64[]"},{"internalType":"address[]","name":"_remoteRfqContracts","type":"address[]"}],"name":"setRemoteRfqContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasuryAddr","type":"address"}],"name":"setTreasuryAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"uint64","name":"_submissionDeadline","type":"uint64"}],"name":"srcDeposit","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"uint64","name":"_submissionDeadline","type":"uint64"}],"name":"srcDepositNative","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"bytes","name":"_execMsgCallData","type":"bytes"}],"name":"srcRelease","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"srcChainId","type":"uint64"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"srcReleaseAmount","type":"uint256"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"refundTo","type":"address"},{"internalType":"address","name":"liquidityProvider","type":"address"}],"internalType":"struct RFQ.Quote","name":"_quote","type":"tuple"},{"internalType":"bytes","name":"_execMsgCallData","type":"bytes"}],"name":"srcReleaseNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"unconsumedMsg","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_liquidityProvider","type":"address"},{"internalType":"bytes32","name":"_quoteHash","type":"bytes32"},{"internalType":"bytes","name":"_sig","type":"bytes"}],"name":"verifySigOfQuoteHash","outputs":[],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620055ff380380620055ff833981016040819052620000349162000262565b6200003f3362000088565b6001805460ff60a01b191690556200005733620000d8565b6200006233620001a2565b600180546001600160a01b0319166001600160a01b039290921691909117905562000294565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811660009081526002602052604090205460ff1615620001475760405162461bcd60e51b815260206004820152601960248201527f4163636f756e7420697320616c7265616479207061757365720000000000000060448201526064015b60405180910390fd5b6001600160a01b038116600081815260026020908152604091829020805460ff1916600117905590519182527f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f891015b60405180910390a150565b6001600160a01b03811660009081526003602052604090205460ff16156200020d5760405162461bcd60e51b815260206004820152601b60248201527f4163636f756e7420697320616c726561647920676f7665726e6f72000000000060448201526064016200013e565b6001600160a01b038116600081815260036020908152604091829020805460ff1916600117905590519182527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5910162000197565b6000602082840312156200027557600080fd5b81516001600160a01b03811681146200028d57600080fd5b9392505050565b61535b80620002a46000396000f3fe6080604052600436106103645760003560e01c806382dc1ec4116101c6578063bbf3b98f116100f7578063e3eece2611610095578063eecdac881161006f578063eecdac8814610a0a578063f2fde38b14610a2a578063f8b839e514610a4a578063fbe42fea14610a6a57600080fd5b8063e3eece261461098e578063e43581b8146109be578063ed9830bb146109f757600080fd5b8063cc47e400116100d1578063cc47e400146108f3578063d1ce8b4514610929578063df1f64ef14610949578063e026049c1461097957600080fd5b8063bbf3b98f1461088a578063c78e33a2146108c0578063cbac44df146108d357600080fd5b8063a5ea10cb11610164578063ae6c218e1161013e578063ae6c218e14610817578063af4ab1381461082a578063b1a7d13f1461084a578063b62b31e41461085d57600080fd5b8063a5ea10cb146107c4578063a7e05b9c146107d7578063ab9341fd146107f757600080fd5b80639c649fdf116101a05780639c649fdf14610751578063a1a227fa14610764578063a2bdb89914610784578063a2f6531e146107a457600080fd5b806382dc1ec4146106fe5780638456cb591461071e5780638da5cb5b1461073357600080fd5b806346fbf68e116102a05780636609870d1161023e5780636ef8d66d116102185780636ef8d66d146106a657806379c7efd3146106bb5780637cd2bffc146105f457806380f51c12146106ce57600080fd5b80636609870d1461064657806369b59e75146106665780636b2c0f551461068657600080fd5b80635aa15a4b1161027a5780635aa15a4b146105d45780635ab7afc6146105f45780635b5a66a7146106075780635c975abb1461062757600080fd5b806346fbf68e1461054b578063547cad121461059457806355e9e3d2146105b457600080fd5b806325329eaf1161030d5780633c4a25d0116102e75780633c4a25d0146104c35780633e07d172146104e35780633f4ba83a14610516578063457bfa2f1461052b57600080fd5b806325329eaf1461042e5780632a37cf711461046b57806330d9a62a1461048b57600080fd5b80630bd930b41161033e5780630bd930b4146103cd5780631000cd9e146104065780631e9c57481461041b57600080fd5b8063063ce4e5146103705780630a54aacd146103995780630bcb4982146103ba57600080fd5b3661036b57005b600080fd5b61038361037e3660046147cd565b610a8a565b6040516103909190614885565b60405180910390f35b6103ac6103a73660046148b1565b610af6565b604051908152602001610390565b6103836103c83660046148e7565b610cf7565b3480156103d957600080fd5b506008546103f190600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610390565b610419610414366004614955565b610d5d565b005b610419610429366004614980565b610f9f565b34801561043a57600080fd5b5061045e6104493660046149ba565b60076020526000908152604090205460ff1681565b60405161039091906149d3565b34801561047757600080fd5b506104196104863660046149e7565b6111eb565b34801561049757600080fd5b506008546104ab906001600160a01b031681565b6040516001600160a01b039091168152602001610390565b3480156104cf57600080fd5b506104196104de366004614a40565b6112ad565b3480156104ef57600080fd5b506103f16104fe366004614a5b565b60096020526000908152604090205463ffffffff1681565b34801561052257600080fd5b50610419611310565b34801561053757600080fd5b506004546104ab906001600160a01b031681565b34801561055757600080fd5b50610584610566366004614a40565b6001600160a01b031660009081526002602052604090205460ff1690565b6040519015158152602001610390565b3480156105a057600080fd5b506104196105af366004614a40565b611379565b3480156105c057600080fd5b506103ac6105cf366004614a76565b611425565b3480156105e057600080fd5b506104196105ef366004614a40565b6114a0565b610383610602366004614ab7565b6114fb565b34801561061357600080fd5b50610419610622366004614a40565b611563565b34801561063357600080fd5b50600154600160a01b900460ff16610584565b34801561065257600080fd5b50610419610661366004614b46565b6115dc565b34801561067257600080fd5b50610419610681366004614a40565b611751565b34801561069257600080fd5b506104196106a1366004614a40565b61182a565b3480156106b257600080fd5b5061041961188a565b6104196106c9366004614955565b611893565b3480156106da57600080fd5b506105846106e9366004614a40565b60026020526000908152604090205460ff1681565b34801561070a57600080fd5b50610419610719366004614a40565b611b67565b34801561072a57600080fd5b50610419611bc7565b34801561073f57600080fd5b506000546001600160a01b03166104ab565b61038361075f366004614b9b565b611c2e565b34801561077057600080fd5b506001546104ab906001600160a01b031681565b34801561079057600080fd5b5061041961079f366004614b46565b611d4e565b3480156107b057600080fd5b506104ab6107bf366004614be5565b611dbc565b6104196107d2366004614955565b611e78565b3480156107e357600080fd5b506104196107f2366004614a40565b611f81565b34801561080357600080fd5b50610419610812366004614c5b565b612026565b610419610825366004614b46565b6122ac565b34801561083657600080fd5b50610419610845366004614b46565b61244e565b610419610858366004614cba565b612528565b34801561086957600080fd5b506103ac610878366004614a40565b600a6020526000908152604090205481565b34801561089657600080fd5b506104ab6108a5366004614a40565b600b602052600090815260409020546001600160a01b031681565b6104196108ce366004614980565b6126d5565b3480156108df57600080fd5b506104196108ee366004614c5b565b6127d6565b3480156108ff57600080fd5b506104ab61090e366004614a5b565b6005602052600090815260409020546001600160a01b031681565b34801561093557600080fd5b506103ac610944366004614955565b612958565b34801561095557600080fd5b506105846109643660046149ba565b60066020526000908152604090205460ff1681565b34801561098557600080fd5b50610419612a4c565b34801561099a57600080fd5b506105846109a9366004614a40565b60036020526000908152604090205460ff1681565b3480156109ca57600080fd5b506105846109d9366004614a40565b6001600160a01b031660009081526003602052604090205460ff1690565b6103ac610a053660046148b1565b612a55565b348015610a1657600080fd5b50610419610a25366004614a40565b612acd565b348015610a3657600080fd5b50610419610a45366004614a40565b612b2d565b348015610a5657600080fd5b50610419610a65366004614b46565b612c09565b348015610a7657600080fd5b506103ac610a85366004614d08565b612cb1565b6001546000906001600160a01b03163314610aec5760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206973206e6f74206d657373616765206275730000000000000060448201526064015b60405180910390fd5b9695505050505050565b600154600090600160a01b900460ff1615610b465760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6004546001600160a01b0316610b9e5760405162461bcd60e51b815260206004820152601860248201527f5266713a206e61746976652077726170206e6f742073657400000000000000006044820152606401610ae3565b6004546001600160a01b0316610bba6040850160208601614a40565b6001600160a01b031614610c105760405162461bcd60e51b815260206004820152601760248201527f5266713a2073726320746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b8260400135341015610c645760405162461bcd60e51b815260206004820152601860248201527f5266713a20696e73756666696369656e7420616d6f756e7400000000000000006044820152606401610ae3565b6000610c7e8484610c79604083013534614d48565b612d0f565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663d0e30db085604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015610cd457600080fd5b505af1158015610ce8573d6000803e3d6000fd5b50939450505050505b92915050565b6001546000906001600160a01b03163314610d545760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206973206e6f74206d65737361676520627573000000000000006044820152606401610ae3565b95945050505050565b600154600160a01b900460ff1615610daa5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6004546001600160a01b0316610dc660c0830160a08401614a40565b6001600160a01b031614610e1c5760405162461bcd60e51b815260206004820152601760248201527f5266713a2064737420746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b8060c00135341015610e705760405162461bcd60e51b815260206004820152601860248201527f5266713a20696e73756666696369656e7420616d6f756e7400000000000000006044820152606401610ae3565b600080610e7c8361317f565b6000828152600760209081526040808320805460ff191660081790555193955091935091610eaf91859160019101614d5b565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529190529050610f0382610eef6020870187614a5b565b83610efe60c089013534614d48565b613419565b610f22610f1861016086016101408701614a40565b8560c00135613435565b7fb97bb040c4582b3252c1079bcea2a781f656ef09ceb53be48b2d615c61198bc583610f5661016087016101408801614a40565b610f6660c0880160a08901614a40565b604080519384526001600160a01b03928316602085015291169082015260c086013560608201526080015b60405180910390a150505050565b600154600160a01b900460ff1615610fec5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b610ffc60a0830160808401614a5b565b6001600160401b03166110126020840184614a5b565b6001600160401b0316146110685760405162461bcd60e51b815260206004820152601860248201527f5266713a206e6f742073616d6520636861696e207377617000000000000000006044820152606401610ae3565b6004546001600160a01b031661108460c0840160a08501614a40565b6001600160a01b0316146110da5760405162461bcd60e51b815260206004820152601760248201527f5266713a2064737420746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b8160c0013534146111375760405162461bcd60e51b815260206004820152602160248201527f5266713a206e617469766520746f6b656e20616d6f756e74206d69736d6174636044820152600d60fb1b6064820152608401610ae3565b60006111428361317f565b50905061116461115a61016085016101408601614a40565b8460c00135613435565b61116f838284613546565b7fb97bb040c4582b3252c1079bcea2a781f656ef09ceb53be48b2d615c61198bc5816111a361016086016101408701614a40565b6111b360c0870160a08801614a40565b604080519384526001600160a01b03928316602085015291169082015260c085013560608201526080015b60405180910390a1505050565b60006111f8848484611dbc565b9050846001600160a01b0316816001600160a01b0316148061125a57506001600160a01b038581166000908152600b6020526040902054161580159061125a57506001600160a01b038086166000908152600b60205260409020548282169116145b6112a65760405162461bcd60e51b815260206004820152601760248201527f5266713a206e6f7420616c6c6f776564207369676e65720000000000000000006044820152606401610ae3565b5050505050565b336112c06000546001600160a01b031690565b6001600160a01b0316146113045760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b61130d81613699565b50565b3360009081526002602052604090205460ff1661136f5760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610ae3565b611377613756565b565b3361138c6000546001600160a01b031690565b6001600160a01b0316146113d05760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f3f8223bcd8b3b875473e9f9e14e1ad075451a2b5ffd31591655da9a01516bf5e906020015b60405180910390a150565b60015460405163299aee5160e11b81526000916001600160a01b031690635335dca2906114589086908690600401614d7a565b602060405180830381865afa158015611475573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114999190614da9565b9392505050565b6001600160a01b0381166114ce57336000908152600b6020526040902080546001600160a01b031916905550565b336000908152600b6020526040902080546001600160a01b0383166001600160a01b031990911617905550565b6001546000906001600160a01b031633146115585760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206973206e6f74206d65737361676520627573000000000000006044820152606401610ae3565b979650505050505050565b336115766000546001600160a01b031690565b6001600160a01b0316146115ba5760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b600154600160a01b900460ff16156116295760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6004546001600160a01b03166116456040850160208601614a40565b6001600160a01b03161461169b5760405162461bcd60e51b815260206004820152601760248201527f5266713a2073726320746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b6000806116a98585856137fc565b6000828152600760205260409020805460ff1916600517905590925090506116e66116dc61016087016101408801614a40565b8660400135613990565b7f2e0668a62a5f556368dca9c7113e20f2852c05155548243804bf714ce72b25a682826117196040890160208a01614a40565b604080519384526001600160a01b03928316602085015291168282015287013560608201526080015b60405180910390a15050505050565b6008546001600160a01b03166117a95760405162461bcd60e51b815260206004820152601d60248201527f5266713a2074726561737572792061646472657373206e6f74207365740000006044820152606401610ae3565b6001600160a01b038082166000818152600a60205260408120805491905560085490926117d892911683613af8565b600854604080516001600160a01b039283168152918416602083015281018290527ff228de527fc1b9843baac03b9a04565473a263375950e63435d4138464386f469060600160405180910390a15050565b3361183d6000546001600160a01b031690565b6001600160a01b0316146118815760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b61130d81613b88565b61137733613b88565b600154600160a01b900460ff16156118e05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b426118f2610100830160e08401614a5b565b6001600160401b0316106119525760405162461bcd60e51b815260206004820152602160248201527f5266713a207472616e7366657220646561646c696e65206e6f742070617373656044820152601960fa1b6064820152608401610ae3565b6001600160401b03461661196c60a0830160808401614a5b565b6001600160401b0316146119c25760405162461bcd60e51b815260206004820152601960248201527f5266713a2064737420636861696e4964206d69736d61746368000000000000006044820152606401610ae3565b60006005816119d46020850185614a5b565b6001600160401b031681526020810191909152604001600020546001600160a01b0316905080611a465760405162461bcd60e51b815260206004820152601d60248201527f5266713a207372632072667120636f6e7472616374206e6f74207365740000006044820152606401610ae3565b6000611a5183612958565b90506000808281526007602052604090205460ff166008811115611a7757611a7761485f565b14611ac45760405162461bcd60e51b815260206004820152601b60248201527f5266713a2071756f746520616c726561647920657865637574656400000000006044820152606401610ae3565b6000818152600760209081526040808320805460ff1916600617905551611af091849160029101614d5b565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529190529050611b3783611b306020870187614a5b565b8334613419565b6040518281527f7cdd4403cff3a09d96c1ffe4ad1cc5c195e9053463a55edfc2944644ec02211890602001610f91565b33611b7a6000546001600160a01b031690565b6001600160a01b031614611bbe5760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b61130d81613c41565b3360009081526002602052604090205460ff16611c265760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610ae3565b611377613cfe565b6001546000906001600160a01b03163314611c8b5760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206973206e6f74206d65737361676520627573000000000000006044820152606401610ae3565b60208314611cdb5760405162461bcd60e51b815260206004820152601d60248201527f5266713a20696e636f7272656374206d657373616765206c656e6774680000006044820152606401610ae3565b6001600160401b0385166000908152600560205260409020546001600160a01b039081169087168114611d12576002915050610d54565b600160066000611d228789614dc2565b81526020810191909152604001600020805460ff19169115159190911790555060019695505050505050565b600154600160a01b900460ff1615611d9b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6000611da8848484613d86565b9050611db684826000613546565b50505050565b604080514660208201526bffffffffffffffffffffffff193060601b16918101919091527f416c6c6f7765645472616e7366657200000000000000000000000000000000006054820152606381018490526000908190611e349060830160405160208183030381529060405280519060200120613e13565b9050610d5484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508593925050613e4e9050565b600154600160a01b900460ff1615611ec55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b600080611ed18361317f565b6000828152600760208181526040808420805460ff1916909317909255905193955091935091611f0691859160019101614d5b565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529190529050611f4682611b306020870187614a5b565b610f2233611f5c61016087016101408801614a40565b60c08701803590611f709060a08a01614a40565b6001600160a01b0316929190613e72565b33611f946000546001600160a01b031690565b6001600160a01b031614611fd85760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527fb17659014001857e7557191ad74dc9e967b181eaed0895975325e3848debbc429060200161141a565b3360009081526003602052604090205460ff166120855760405162461bcd60e51b815260206004820152601660248201527f43616c6c6572206973206e6f7420676f7665726e6f72000000000000000000006044820152606401610ae3565b8281146120d45760405162461bcd60e51b815260206004820152601460248201527f5266713a206c656e677468206d69736d617463680000000000000000000000006044820152606401610ae3565b60005b8381101561227657620f42408383838181106120f5576120f5614de0565b905060200201602081019061210a9190614e0a565b63ffffffff161061215d5760405162461bcd60e51b815260206004820152601d60248201527f5266713a206665652070657263656e7461676520746f6f206c617267650000006044820152606401610ae3565b84848281811061216f5761216f614de0565b90506020020160208101906121849190614a5b565b6001600160401b03166000036121e0578282828181106121a6576121a6614de0565b90506020020160208101906121bb9190614e0a565b600860146101000a81548163ffffffff021916908363ffffffff160217905550612264565b8282828181106121f2576121f2614de0565b90506020020160208101906122079190614e0a565b6009600087878581811061221d5761221d614de0565b90506020020160208101906122329190614a5b565b6001600160401b031681526020810191909152604001600020805463ffffffff191663ffffffff929092169190911790555b8061226e81614e25565b9150506120d7565b507f541df5e570cf10ffe04899eebd9eebebd1c54e2bd4af9f24b23fb4a40c6ea00b84848484604051610f919493929190614e85565b600154600160a01b900460ff16156122f95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6000806123058561317f565b909250905061232761231f6101a087016101808801614a40565b8386866111eb565b6000828152600760208181526040808420805460ff1916909317909255905161235591859160019101614d5b565b60408051601f198184030181528282528051602091820120908301520160408051601f19818403018152919052905061239582611b306020890189614a5b565b6123d06123aa6101a088016101808901614a40565b6123bc61016089016101408a01614a40565b60c08901803590611f709060a08c01614a40565b7fb97bb040c4582b3252c1079bcea2a781f656ef09ceb53be48b2d615c61198bc58361240461016089016101408a01614a40565b61241460c08a0160a08b01614a40565b604080519384526001600160a01b03928316602085015291169082015260c0880135606082015260800160405180910390a1505050505050565b600154600160a01b900460ff161561249b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6004546001600160a01b03166124b76040850160208601614a40565b6001600160a01b03161461250d5760405162461bcd60e51b815260206004820152601760248201527f5266713a2073726320746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b600061251a848484613d86565b9050611db684826001613546565b600154600160a01b900460ff16156125755760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b61258560a0850160808601614a5b565b6001600160401b031661259b6020860186614a5b565b6001600160401b0316146125f15760405162461bcd60e51b815260206004820152601860248201527f5266713a206e6f742073616d6520636861696e207377617000000000000000006044820152606401610ae3565b60006125fc8561317f565b50905061261c6126146101a087016101808801614a40565b8285856111eb565b6126576126316101a087016101808801614a40565b61264361016088016101408901614a40565b60c08801803590611f709060a08b01614a40565b612662858286613546565b7fb97bb040c4582b3252c1079bcea2a781f656ef09ceb53be48b2d615c61198bc58161269661016088016101408901614a40565b6126a660c0890160a08a01614a40565b604080519384526001600160a01b03928316602085015291169082015260c08701356060820152608001611742565b600154600160a01b900460ff16156127225760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b61273260a0830160808401614a5b565b6001600160401b03166127486020840184614a5b565b6001600160401b03161461279e5760405162461bcd60e51b815260206004820152601860248201527f5266713a206e6f742073616d6520636861696e207377617000000000000000006044820152606401610ae3565b60006127a98361317f565b509050611164336127c261016086016101408701614a40565b60c08601803590611f709060a08901614a40565b336127e96000546001600160a01b031690565b6001600160a01b03161461282d5760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b82811461287c5760405162461bcd60e51b815260206004820152601460248201527f5266713a206c656e677468206d69736d617463680000000000000000000000006044820152606401610ae3565b60005b838110156129225782828281811061289957612899614de0565b90506020020160208101906128ae9190614a40565b600560008787858181106128c4576128c4614de0565b90506020020160208101906128d99190614a5b565b6001600160401b03168152602081019190915260400160002080546001600160a01b0319166001600160a01b03929092169190911790558061291a81614e25565b91505061287f565b507fb4739c640c5970d8ce88b6c31f3706099efca660e282d47b0a267a0bb572d8b784848484604051610f919493929190614ee5565b60006129676020830183614a5b565b6129776040840160208501614a40565b6040840135606085013561299160a0870160808801614a5b565b6129a160c0880160a08901614a40565b60c08801356129b76101008a0160e08b01614a5b565b6129c96101208b016101008c01614a5b565b6129db6101408c016101208d01614a40565b6129ed6101608d016101408e01614a40565b6129ff6101808e016101608f01614a40565b8d610180016020810190612a139190614a40565b604051602001612a2f9d9c9b9a99989796959493929190614f3b565b604051602081830303815290604052805190602001209050919050565b61137733613eaa565b600154600090600160a01b900460ff1615612aa55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6000612ab2848434612d0f565b9050611499333060408701803590611f709060208a01614a40565b33612ae06000546001600160a01b031690565b6001600160a01b031614612b245760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b61130d81613eaa565b33612b406000546001600160a01b031690565b6001600160a01b031614612b845760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b6001600160a01b038116612c005760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610ae3565b61130d81613f63565b600154600160a01b900460ff1615612c565760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b600080612c648585856137fc565b6000828152600760205260409020805492945090925060049160ff191660018302179055506116e68160408701803590612ca19060208a01614a40565b6001600160a01b03169190613af8565b6001600160401b03821660009081526009602052604081205463ffffffff16808203612ce95750600854600160a01b900463ffffffff165b620f4240612cfd63ffffffff83168561506a565b612d079190615081565b949350505050565b600042836001600160401b0316118015612d4a57506001600160401b038316612d3f610100860160e08701614a5b565b6001600160401b0316115b612d965760405162461bcd60e51b815260206004820152601b60248201527f5266713a20696e617070726f70726961746520646561646c696e6500000000006044820152606401610ae3565b6000612daa61016086016101408701614a40565b6001600160a01b031614158015612ddc57506000612dd06101a086016101808701614a40565b6001600160a01b031614155b612e4e5760405162461bcd60e51b815260206004820152602a60248201527f5266713a20696e76616c6964207265636569766572206f72206c69717569646960448201527f747950726f7669646572000000000000000000000000000000000000000000006064820152608401610ae3565b6001600160401b034616612e656020860186614a5b565b6001600160401b031614612ebb5760405162461bcd60e51b815260206004820152601960248201527f5266713a2073726320636861696e4964206d69736d61746368000000000000006044820152606401610ae3565b33612ece61014086016101208701614a40565b6001600160a01b031614612f245760405162461bcd60e51b815260206004820152601460248201527f5266713a2073656e646572206d69736d617463680000000000000000000000006044820152606401610ae3565b6000612f2f85612958565b90506000808281526007602052604090205460ff166008811115612f5557612f5561485f565b14612fa25760405162461bcd60e51b815260206004820152601660248201527f5266713a2071756f7465206861736820657869737473000000000000000000006044820152606401610ae3565b6000612fc1612fb760a0880160808901614a5b565b8760400135612cb1565b9050612fd560608701356040880135614d48565b8111156130245760405162461bcd60e51b815260206004820152601e60248201527f5266713a20696e73756666696369656e742070726f746f636f6c2066656500006044820152606401610ae3565b6000828152600760205260409020805460ff1916600117905561304d60a0870160808801614a5b565b6001600160401b03166130636020880188614a5b565b6001600160401b03161461313d57600060058161308660a08a0160808b01614a5b565b6001600160401b031681526020810191909152604001600020546001600160a01b03169050806130f85760405162461bcd60e51b815260206004820152601960248201527f5266713a2064737420636f6e7472616374206e6f7420736574000000000000006044820152606401610ae3565b60008360405160200161310d91815260200190565b60408051601f19818403018152919052905061313a8261313360a08b0160808c01614a5b565b8389613419565b50505b7f3e4de2d1674631d426ae2a89635b421e6d40a31d27681afdf0eed67e81d07bcb828760405161316e9291906150a3565b60405180910390a150949350505050565b60008042613194610100850160e08601614a5b565b6001600160401b0316116131ea5760405162461bcd60e51b815260206004820152601d60248201527f5266713a207472616e7366657220646561646c696e65207061737365640000006044820152606401610ae3565b6001600160401b03461661320460a0850160808601614a5b565b6001600160401b03161461325a5760405162461bcd60e51b815260206004820152601960248201527f5266713a2064737420636861696e4964206d69736d61746368000000000000006044820152606401610ae3565b600061326584612958565b905060006005816132796020880188614a5b565b6001600160401b031681526020810191909152604001600020546001600160a01b031690506132ae60a0860160808701614a5b565b6001600160401b03166132c46020870187614a5b565b6001600160401b03161461339d5760008281526007602052604081205460ff1660088111156132f5576132f561485f565b146133425760405162461bcd60e51b815260206004820152601b60248201527f5266713a2071756f746520616c726561647920657865637574656400000000006044820152606401610ae3565b6001600160a01b0381166133985760405162461bcd60e51b815260206004820152601d60248201527f5266713a206473742072667120636f6e7472616374206e6f74207365740000006044820152606401610ae3565b61340f565b600160008381526007602052604090205460ff1660088111156133c2576133c261485f565b1461340f5760405162461bcd60e51b815260206004820152601d60248201527f5266713a206e6f206465706f736974206f6e2073616d6520636861696e0000006044820152606401610ae3565b9094909350915050565b600154611db6908590859085906001600160a01b031685613fb3565b6004546001600160a01b031661348d5760405162461bcd60e51b815260206004820152601860248201527f5266713a206e61746976652077726170206e6f742073657400000000000000006044820152606401610ae3565b6000826001600160a01b03168261c35090604051600060405180830381858888f193505050503d80600081146134df576040519150601f19603f3d011682016040523d82523d6000602084013e6134e4565b606091505b50509050806135415760405162461bcd60e51b8152602060048201526024808201527f5266713a206661696c656420746f207472616e73666572206e6174697665207460448201526337b5b2b760e11b6064820152608401610ae3565b505050565b61355860608401356040850135614d48565b600a600061356c6040870160208801614a40565b6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461359b9190615215565b909155505080156135e3576000828152600760205260409020805460ff191660031790556135de6135d46101a085016101808601614a40565b8460600135613990565b613626565b6000828152600760205260409020805460ff191660021790556136266136116101a085016101808601614a40565b6060850135612ca16040870160208801614a40565b7ff29b32a17c591b8b3b1216ce0ffb67c07f3478e99b50c5ccf8602878b1ee63768261365a6101a086016101808701614a40565b61366a6040870160208801614a40565b604080519384526001600160a01b039283166020850152911690820152606080860135908201526080016111de565b6001600160a01b03811660009081526003602052604090205460ff16156137025760405162461bcd60e51b815260206004820152601b60248201527f4163636f756e7420697320616c726561647920676f7665726e6f7200000000006044820152606401610ae3565b6001600160a01b038116600081815260036020908152604091829020805460ff1916600117905590519182527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5910161141a565b600154600160a01b900460ff166137af5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610ae3565b6001805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600080600061380a86612958565b9050600160008281526007602052604090205460ff1660088111156138315761383161485f565b1461387e5760405162461bcd60e51b815260206004820152601960248201527f5266713a20696e636f72726563742071756f74652068617368000000000000006044820152606401610ae3565b61388e60a0870160808801614a5b565b6001600160401b03166138a46020880188614a5b565b6001600160401b0316146138c4576138bf858583600261401e565b613936565b426138d6610100880160e08901614a5b565b6001600160401b0316106139365760405162461bcd60e51b815260206004820152602160248201527f5266713a207472616e7366657220646561646c696e65206e6f742070617373656044820152601960fa1b6064820152608401610ae3565b60008061394b61018089016101608a01614a40565b6001600160a01b0316146139705761396b61018088016101608901614a40565b613982565b61398261014088016101208901614a40565b919791965090945050505050565b6004546001600160a01b03166139e85760405162461bcd60e51b815260206004820152601860248201527f5266713a206e61746976652077726170206e6f742073657400000000000000006044820152606401610ae3565b60048054604051632e1a7d4d60e01b81529182018390526001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015613a2c57600080fd5b505af1158015613a40573d6000803e3d6000fd5b505050506000826001600160a01b03168261c35090604051600060405180830381858888f193505050503d8060008114613a96576040519150601f19603f3d011682016040523d82523d6000602084013e613a9b565b606091505b50509050806135415760405162461bcd60e51b8152602060048201526024808201527f5266713a206661696c656420746f207769746864726177206e6174697665207460448201526337b5b2b760e11b6064820152608401610ae3565b6040516001600160a01b03831660248201526044810182905261354190849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614191565b6001600160a01b03811660009081526002602052604090205460ff16613bf05760405162461bcd60e51b815260206004820152601560248201527f4163636f756e74206973206e6f742070617573657200000000000000000000006044820152606401610ae3565b6001600160a01b038116600081815260026020908152604091829020805460ff1916905590519182527fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e910161141a565b6001600160a01b03811660009081526002602052604090205460ff1615613caa5760405162461bcd60e51b815260206004820152601960248201527f4163636f756e7420697320616c726561647920706175736572000000000000006044820152606401610ae3565b6001600160a01b038116600081815260026020908152604091829020805460ff1916600117905590519182527f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f8910161141a565b600154600160a01b900460ff1615613d4b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6001805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586137df3390565b600080613d9285612958565b9050600160008281526007602052604090205460ff166008811115613db957613db961485f565b14613e065760405162461bcd60e51b815260206004820152601960248201527f5266713a20696e636f72726563742071756f74652068617368000000000000006044820152606401610ae3565b612d07848483600161401e565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01612a2f565b6000806000613e5d8585614276565b91509150613e6a816142e4565b509392505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611db69085906323b872dd60e01b90608401613b24565b6001600160a01b03811660009081526003602052604090205460ff16613f125760405162461bcd60e51b815260206004820152601760248201527f4163636f756e74206973206e6f7420676f7665726e6f720000000000000000006044820152606401610ae3565b6001600160a01b038116600081815260036020908152604091829020805460ff1916905590519182527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b910161141a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b604051634f9e72ad60e11b81526001600160a01b03831690639f3ce55a908390613fe590899089908990600401615278565b6000604051808303818588803b158015613ffe57600080fd5b505af1158015614012573d6000803e3d6000fd5b50505050505050505050565b60008282604051602001614033929190614d5b565b60408051601f1981840301815291815281516020928301206000818152600690935291205490915060ff16614117576001546040516000916001600160a01b03169061408290889088906152a9565b6000604051808303816000865af19150503d80600081146140bf576040519150601f19603f3d011682016040523d82523d6000602084013e6140c4565b606091505b50509050806141155760405162461bcd60e51b815260206004820152601260248201527f65786563757465206d7367206661696c656400000000000000000000000000006044820152606401610ae3565b505b60008181526006602052604090205460ff166141755760405162461bcd60e51b815260206004820152601060248201527f5266713a20696e76616c6964206d7367000000000000000000000000000000006044820152606401610ae3565b6000908152600660205260409020805460ff1916905550505050565b60006141e6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661449a9092919063ffffffff16565b805190915015613541578080602001905181019061420491906152b9565b6135415760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610ae3565b60008082516041036142ac5760208301516040840151606085015160001a6142a0878285856144a9565b945094505050506142dd565b82516040036142d557602083015160408401516142ca868383614596565b9350935050506142dd565b506000905060025b9250929050565b60008160048111156142f8576142f861485f565b036143005750565b60018160048111156143145761431461485f565b036143615760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610ae3565b60028160048111156143755761437561485f565b036143c25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610ae3565b60038160048111156143d6576143d661485f565b0361442e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610ae3565b60048160048111156144425761444261485f565b0361130d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610ae3565b6060612d0784846000856145e8565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156144e0575060009050600361458d565b8460ff16601b141580156144f857508460ff16601c14155b15614509575060009050600461458d565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561455d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166145865760006001925092505061458d565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316816145cc60ff86901c601b615215565b90506145da878288856144a9565b935093505050935093915050565b6060824710156146605760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610ae3565b6001600160a01b0385163b6146b75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ae3565b600080866001600160a01b031685876040516146d391906152d6565b60006040518083038185875af1925050503d8060008114614710576040519150601f19603f3d011682016040523d82523d6000602084013e614715565b606091505b50915091506115588282866060831561472f575081611499565b82511561473f5782518084602001fd5b8160405162461bcd60e51b8152600401610ae391906152f2565b60008083601f84011261476b57600080fd5b5081356001600160401b0381111561478257600080fd5b6020830191508360208285010111156142dd57600080fd5b80356001600160401b03811681146147b157600080fd5b919050565b80356001600160a01b03811681146147b157600080fd5b600080600080600080608087890312156147e657600080fd5b86356001600160401b03808211156147fd57600080fd5b6148098a838b01614759565b909850965086915061481d60208a0161479a565b9550604089013591508082111561483357600080fd5b5061484089828a01614759565b90945092506148539050606088016147b6565b90509295509295509295565b634e487b7160e01b600052602160045260246000fd5b6003811061130d5761130d61485f565b6020810161489283614875565b91905290565b60006101a082840312156148ab57600080fd5b50919050565b6000806101c083850312156148c557600080fd5b6148cf8484614898565b91506148de6101a0840161479a565b90509250929050565b6000806000806000608086880312156148ff57600080fd5b614908866147b6565b94506020860135935060408601356001600160401b0381111561492a57600080fd5b61493688828901614759565b90945092506149499050606087016147b6565b90509295509295909350565b60006101a0828403121561496857600080fd5b6114998383614898565b801515811461130d57600080fd5b6000806101c0838503121561499457600080fd5b61499e8484614898565b91506101a08301356149af81614972565b809150509250929050565b6000602082840312156149cc57600080fd5b5035919050565b60208101600983106148925761489261485f565b600080600080606085870312156149fd57600080fd5b614a06856147b6565b93506020850135925060408501356001600160401b03811115614a2857600080fd5b614a3487828801614759565b95989497509550505050565b600060208284031215614a5257600080fd5b611499826147b6565b600060208284031215614a6d57600080fd5b6114998261479a565b60008060208385031215614a8957600080fd5b82356001600160401b03811115614a9f57600080fd5b614aab85828601614759565b90969095509350505050565b600080600080600080600060c0888a031215614ad257600080fd5b614adb886147b6565b9650614ae9602089016147b6565b955060408801359450614afe6060890161479a565b935060808801356001600160401b03811115614b1957600080fd5b614b258a828b01614759565b9094509250614b38905060a089016147b6565b905092959891949750929550565b60008060006101c08486031215614b5c57600080fd5b614b668585614898565b92506101a08401356001600160401b03811115614b8257600080fd5b614b8e86828701614759565b9497909650939450505050565b600080600080600060808688031215614bb357600080fd5b614bbc866147b6565b9450614bca6020870161479a565b935060408601356001600160401b0381111561492a57600080fd5b600080600060408486031215614bfa57600080fd5b8335925060208401356001600160401b03811115614b8257600080fd5b60008083601f840112614c2957600080fd5b5081356001600160401b03811115614c4057600080fd5b6020830191508360208260051b85010111156142dd57600080fd5b60008060008060408587031215614c7157600080fd5b84356001600160401b0380821115614c8857600080fd5b614c9488838901614c17565b90965094506020870135915080821115614cad57600080fd5b50614a3487828801614c17565b6000806000806101e08587031215614cd157600080fd5b614cdb8686614898565b93506101a0850135614cec81614972565b92506101c08501356001600160401b03811115614a2857600080fd5b60008060408385031215614d1b57600080fd5b614d248361479a565b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610cf157610cf1614d32565b828152614d6782614875565b60f89190911b6020820152602101919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600060208284031215614dbb57600080fd5b5051919050565b80356020831015610cf157600019602084900360031b1b1692915050565b634e487b7160e01b600052603260045260246000fd5b803563ffffffff811681146147b157600080fd5b600060208284031215614e1c57600080fd5b61149982614df6565b600060018201614e3757614e37614d32565b5060010190565b8183526000602080850194508260005b85811015614e7a576001600160401b03614e678361479a565b1687529582019590820190600101614e4e565b509495945050505050565b604081526000614e99604083018688614e3e565b8281036020848101919091528482528591810160005b86811015614ed85763ffffffff614ec585614df6565b1682529282019290820190600101614eaf565b5098975050505050505050565b604081526000614ef9604083018688614e3e565b8281036020848101919091528482528591810160005b86811015614ed8576001600160a01b03614f28856147b6565b1682529282019290820190600101614f0f565b6001600160c01b03198e60c01b1681526bffffffffffffffffffffffff198d60601b1660088201528b601c8201528a603c820152614f88605c82018b60c01b6001600160c01b0319169052565b614fa6606482018a60601b6bffffffffffffffffffffffff19169052565b876078820152614fc5609882018860c01b6001600160c01b0319169052565b614fde60a082018760c01b6001600160c01b0319169052565b614ffc60a882018660601b6bffffffffffffffffffffffff19169052565b61501a60bc82018560601b6bffffffffffffffffffffffff19169052565b61503860d082018460601b6bffffffffffffffffffffffff19169052565b61505660e482018360601b6bffffffffffffffffffffffff19169052565b60f8019d9c50505050505050505050505050565b8082028115828204841417610cf157610cf1614d32565b60008261509e57634e487b7160e01b600052601260045260246000fd5b500490565b8281526101c081016150c8602083016150bb8561479a565b6001600160401b03169052565b6150d4602084016147b6565b6001600160a01b03811660408401525060408301356060830152606083013560808301526151046080840161479a565b6001600160401b03811660a08401525061512060a084016147b6565b6001600160a01b03811660c08401525060c083013560e083015261514660e0840161479a565b61010061515d818501836001600160401b03169052565b61516881860161479a565b915050610120615182818501836001600160401b03169052565b61518d8186016147b6565b9150506101406151a7818501836001600160a01b03169052565b6151b28186016147b6565b9150506101606151cc818501836001600160a01b03169052565b6151d78186016147b6565b9150506101806151f1818501836001600160a01b03169052565b6151fc8186016147b6565b915050613e6a6101a08401826001600160a01b03169052565b80820180821115610cf157610cf1614d32565b60005b8381101561524357818101518382015260200161522b565b50506000910152565b60008151808452615264816020860160208601615228565b601f01601f19169290920160200192915050565b6001600160a01b03841681526001600160401b0383166020820152606060408201526000610d54606083018461524c565b8183823760009101908152919050565b6000602082840312156152cb57600080fd5b815161149981614972565b600082516152e8818460208701615228565b9190910192915050565b602081526000611499602083018461524c56fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a2646970667358221220d0cf8bb66abb774cf11009a7b38b3d1b5a1d355754b34237da7d1a494fad05fb64736f6c63430008110033000000000000000000000000afdb9c40c7144022811f034ee07ce2e110093fe6
Deployed Bytecode
0x6080604052600436106103645760003560e01c806382dc1ec4116101c6578063bbf3b98f116100f7578063e3eece2611610095578063eecdac881161006f578063eecdac8814610a0a578063f2fde38b14610a2a578063f8b839e514610a4a578063fbe42fea14610a6a57600080fd5b8063e3eece261461098e578063e43581b8146109be578063ed9830bb146109f757600080fd5b8063cc47e400116100d1578063cc47e400146108f3578063d1ce8b4514610929578063df1f64ef14610949578063e026049c1461097957600080fd5b8063bbf3b98f1461088a578063c78e33a2146108c0578063cbac44df146108d357600080fd5b8063a5ea10cb11610164578063ae6c218e1161013e578063ae6c218e14610817578063af4ab1381461082a578063b1a7d13f1461084a578063b62b31e41461085d57600080fd5b8063a5ea10cb146107c4578063a7e05b9c146107d7578063ab9341fd146107f757600080fd5b80639c649fdf116101a05780639c649fdf14610751578063a1a227fa14610764578063a2bdb89914610784578063a2f6531e146107a457600080fd5b806382dc1ec4146106fe5780638456cb591461071e5780638da5cb5b1461073357600080fd5b806346fbf68e116102a05780636609870d1161023e5780636ef8d66d116102185780636ef8d66d146106a657806379c7efd3146106bb5780637cd2bffc146105f457806380f51c12146106ce57600080fd5b80636609870d1461064657806369b59e75146106665780636b2c0f551461068657600080fd5b80635aa15a4b1161027a5780635aa15a4b146105d45780635ab7afc6146105f45780635b5a66a7146106075780635c975abb1461062757600080fd5b806346fbf68e1461054b578063547cad121461059457806355e9e3d2146105b457600080fd5b806325329eaf1161030d5780633c4a25d0116102e75780633c4a25d0146104c35780633e07d172146104e35780633f4ba83a14610516578063457bfa2f1461052b57600080fd5b806325329eaf1461042e5780632a37cf711461046b57806330d9a62a1461048b57600080fd5b80630bd930b41161033e5780630bd930b4146103cd5780631000cd9e146104065780631e9c57481461041b57600080fd5b8063063ce4e5146103705780630a54aacd146103995780630bcb4982146103ba57600080fd5b3661036b57005b600080fd5b61038361037e3660046147cd565b610a8a565b6040516103909190614885565b60405180910390f35b6103ac6103a73660046148b1565b610af6565b604051908152602001610390565b6103836103c83660046148e7565b610cf7565b3480156103d957600080fd5b506008546103f190600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610390565b610419610414366004614955565b610d5d565b005b610419610429366004614980565b610f9f565b34801561043a57600080fd5b5061045e6104493660046149ba565b60076020526000908152604090205460ff1681565b60405161039091906149d3565b34801561047757600080fd5b506104196104863660046149e7565b6111eb565b34801561049757600080fd5b506008546104ab906001600160a01b031681565b6040516001600160a01b039091168152602001610390565b3480156104cf57600080fd5b506104196104de366004614a40565b6112ad565b3480156104ef57600080fd5b506103f16104fe366004614a5b565b60096020526000908152604090205463ffffffff1681565b34801561052257600080fd5b50610419611310565b34801561053757600080fd5b506004546104ab906001600160a01b031681565b34801561055757600080fd5b50610584610566366004614a40565b6001600160a01b031660009081526002602052604090205460ff1690565b6040519015158152602001610390565b3480156105a057600080fd5b506104196105af366004614a40565b611379565b3480156105c057600080fd5b506103ac6105cf366004614a76565b611425565b3480156105e057600080fd5b506104196105ef366004614a40565b6114a0565b610383610602366004614ab7565b6114fb565b34801561061357600080fd5b50610419610622366004614a40565b611563565b34801561063357600080fd5b50600154600160a01b900460ff16610584565b34801561065257600080fd5b50610419610661366004614b46565b6115dc565b34801561067257600080fd5b50610419610681366004614a40565b611751565b34801561069257600080fd5b506104196106a1366004614a40565b61182a565b3480156106b257600080fd5b5061041961188a565b6104196106c9366004614955565b611893565b3480156106da57600080fd5b506105846106e9366004614a40565b60026020526000908152604090205460ff1681565b34801561070a57600080fd5b50610419610719366004614a40565b611b67565b34801561072a57600080fd5b50610419611bc7565b34801561073f57600080fd5b506000546001600160a01b03166104ab565b61038361075f366004614b9b565b611c2e565b34801561077057600080fd5b506001546104ab906001600160a01b031681565b34801561079057600080fd5b5061041961079f366004614b46565b611d4e565b3480156107b057600080fd5b506104ab6107bf366004614be5565b611dbc565b6104196107d2366004614955565b611e78565b3480156107e357600080fd5b506104196107f2366004614a40565b611f81565b34801561080357600080fd5b50610419610812366004614c5b565b612026565b610419610825366004614b46565b6122ac565b34801561083657600080fd5b50610419610845366004614b46565b61244e565b610419610858366004614cba565b612528565b34801561086957600080fd5b506103ac610878366004614a40565b600a6020526000908152604090205481565b34801561089657600080fd5b506104ab6108a5366004614a40565b600b602052600090815260409020546001600160a01b031681565b6104196108ce366004614980565b6126d5565b3480156108df57600080fd5b506104196108ee366004614c5b565b6127d6565b3480156108ff57600080fd5b506104ab61090e366004614a5b565b6005602052600090815260409020546001600160a01b031681565b34801561093557600080fd5b506103ac610944366004614955565b612958565b34801561095557600080fd5b506105846109643660046149ba565b60066020526000908152604090205460ff1681565b34801561098557600080fd5b50610419612a4c565b34801561099a57600080fd5b506105846109a9366004614a40565b60036020526000908152604090205460ff1681565b3480156109ca57600080fd5b506105846109d9366004614a40565b6001600160a01b031660009081526003602052604090205460ff1690565b6103ac610a053660046148b1565b612a55565b348015610a1657600080fd5b50610419610a25366004614a40565b612acd565b348015610a3657600080fd5b50610419610a45366004614a40565b612b2d565b348015610a5657600080fd5b50610419610a65366004614b46565b612c09565b348015610a7657600080fd5b506103ac610a85366004614d08565b612cb1565b6001546000906001600160a01b03163314610aec5760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206973206e6f74206d657373616765206275730000000000000060448201526064015b60405180910390fd5b9695505050505050565b600154600090600160a01b900460ff1615610b465760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6004546001600160a01b0316610b9e5760405162461bcd60e51b815260206004820152601860248201527f5266713a206e61746976652077726170206e6f742073657400000000000000006044820152606401610ae3565b6004546001600160a01b0316610bba6040850160208601614a40565b6001600160a01b031614610c105760405162461bcd60e51b815260206004820152601760248201527f5266713a2073726320746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b8260400135341015610c645760405162461bcd60e51b815260206004820152601860248201527f5266713a20696e73756666696369656e7420616d6f756e7400000000000000006044820152606401610ae3565b6000610c7e8484610c79604083013534614d48565b612d0f565b9050600460009054906101000a90046001600160a01b03166001600160a01b031663d0e30db085604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015610cd457600080fd5b505af1158015610ce8573d6000803e3d6000fd5b50939450505050505b92915050565b6001546000906001600160a01b03163314610d545760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206973206e6f74206d65737361676520627573000000000000006044820152606401610ae3565b95945050505050565b600154600160a01b900460ff1615610daa5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6004546001600160a01b0316610dc660c0830160a08401614a40565b6001600160a01b031614610e1c5760405162461bcd60e51b815260206004820152601760248201527f5266713a2064737420746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b8060c00135341015610e705760405162461bcd60e51b815260206004820152601860248201527f5266713a20696e73756666696369656e7420616d6f756e7400000000000000006044820152606401610ae3565b600080610e7c8361317f565b6000828152600760209081526040808320805460ff191660081790555193955091935091610eaf91859160019101614d5b565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529190529050610f0382610eef6020870187614a5b565b83610efe60c089013534614d48565b613419565b610f22610f1861016086016101408701614a40565b8560c00135613435565b7fb97bb040c4582b3252c1079bcea2a781f656ef09ceb53be48b2d615c61198bc583610f5661016087016101408801614a40565b610f6660c0880160a08901614a40565b604080519384526001600160a01b03928316602085015291169082015260c086013560608201526080015b60405180910390a150505050565b600154600160a01b900460ff1615610fec5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b610ffc60a0830160808401614a5b565b6001600160401b03166110126020840184614a5b565b6001600160401b0316146110685760405162461bcd60e51b815260206004820152601860248201527f5266713a206e6f742073616d6520636861696e207377617000000000000000006044820152606401610ae3565b6004546001600160a01b031661108460c0840160a08501614a40565b6001600160a01b0316146110da5760405162461bcd60e51b815260206004820152601760248201527f5266713a2064737420746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b8160c0013534146111375760405162461bcd60e51b815260206004820152602160248201527f5266713a206e617469766520746f6b656e20616d6f756e74206d69736d6174636044820152600d60fb1b6064820152608401610ae3565b60006111428361317f565b50905061116461115a61016085016101408601614a40565b8460c00135613435565b61116f838284613546565b7fb97bb040c4582b3252c1079bcea2a781f656ef09ceb53be48b2d615c61198bc5816111a361016086016101408701614a40565b6111b360c0870160a08801614a40565b604080519384526001600160a01b03928316602085015291169082015260c085013560608201526080015b60405180910390a1505050565b60006111f8848484611dbc565b9050846001600160a01b0316816001600160a01b0316148061125a57506001600160a01b038581166000908152600b6020526040902054161580159061125a57506001600160a01b038086166000908152600b60205260409020548282169116145b6112a65760405162461bcd60e51b815260206004820152601760248201527f5266713a206e6f7420616c6c6f776564207369676e65720000000000000000006044820152606401610ae3565b5050505050565b336112c06000546001600160a01b031690565b6001600160a01b0316146113045760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b61130d81613699565b50565b3360009081526002602052604090205460ff1661136f5760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610ae3565b611377613756565b565b3361138c6000546001600160a01b031690565b6001600160a01b0316146113d05760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f3f8223bcd8b3b875473e9f9e14e1ad075451a2b5ffd31591655da9a01516bf5e906020015b60405180910390a150565b60015460405163299aee5160e11b81526000916001600160a01b031690635335dca2906114589086908690600401614d7a565b602060405180830381865afa158015611475573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114999190614da9565b9392505050565b6001600160a01b0381166114ce57336000908152600b6020526040902080546001600160a01b031916905550565b336000908152600b6020526040902080546001600160a01b0383166001600160a01b031990911617905550565b6001546000906001600160a01b031633146115585760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206973206e6f74206d65737361676520627573000000000000006044820152606401610ae3565b979650505050505050565b336115766000546001600160a01b031690565b6001600160a01b0316146115ba5760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b600154600160a01b900460ff16156116295760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6004546001600160a01b03166116456040850160208601614a40565b6001600160a01b03161461169b5760405162461bcd60e51b815260206004820152601760248201527f5266713a2073726320746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b6000806116a98585856137fc565b6000828152600760205260409020805460ff1916600517905590925090506116e66116dc61016087016101408801614a40565b8660400135613990565b7f2e0668a62a5f556368dca9c7113e20f2852c05155548243804bf714ce72b25a682826117196040890160208a01614a40565b604080519384526001600160a01b03928316602085015291168282015287013560608201526080015b60405180910390a15050505050565b6008546001600160a01b03166117a95760405162461bcd60e51b815260206004820152601d60248201527f5266713a2074726561737572792061646472657373206e6f74207365740000006044820152606401610ae3565b6001600160a01b038082166000818152600a60205260408120805491905560085490926117d892911683613af8565b600854604080516001600160a01b039283168152918416602083015281018290527ff228de527fc1b9843baac03b9a04565473a263375950e63435d4138464386f469060600160405180910390a15050565b3361183d6000546001600160a01b031690565b6001600160a01b0316146118815760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b61130d81613b88565b61137733613b88565b600154600160a01b900460ff16156118e05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b426118f2610100830160e08401614a5b565b6001600160401b0316106119525760405162461bcd60e51b815260206004820152602160248201527f5266713a207472616e7366657220646561646c696e65206e6f742070617373656044820152601960fa1b6064820152608401610ae3565b6001600160401b03461661196c60a0830160808401614a5b565b6001600160401b0316146119c25760405162461bcd60e51b815260206004820152601960248201527f5266713a2064737420636861696e4964206d69736d61746368000000000000006044820152606401610ae3565b60006005816119d46020850185614a5b565b6001600160401b031681526020810191909152604001600020546001600160a01b0316905080611a465760405162461bcd60e51b815260206004820152601d60248201527f5266713a207372632072667120636f6e7472616374206e6f74207365740000006044820152606401610ae3565b6000611a5183612958565b90506000808281526007602052604090205460ff166008811115611a7757611a7761485f565b14611ac45760405162461bcd60e51b815260206004820152601b60248201527f5266713a2071756f746520616c726561647920657865637574656400000000006044820152606401610ae3565b6000818152600760209081526040808320805460ff1916600617905551611af091849160029101614d5b565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529190529050611b3783611b306020870187614a5b565b8334613419565b6040518281527f7cdd4403cff3a09d96c1ffe4ad1cc5c195e9053463a55edfc2944644ec02211890602001610f91565b33611b7a6000546001600160a01b031690565b6001600160a01b031614611bbe5760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b61130d81613c41565b3360009081526002602052604090205460ff16611c265760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610ae3565b611377613cfe565b6001546000906001600160a01b03163314611c8b5760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206973206e6f74206d65737361676520627573000000000000006044820152606401610ae3565b60208314611cdb5760405162461bcd60e51b815260206004820152601d60248201527f5266713a20696e636f7272656374206d657373616765206c656e6774680000006044820152606401610ae3565b6001600160401b0385166000908152600560205260409020546001600160a01b039081169087168114611d12576002915050610d54565b600160066000611d228789614dc2565b81526020810191909152604001600020805460ff19169115159190911790555060019695505050505050565b600154600160a01b900460ff1615611d9b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6000611da8848484613d86565b9050611db684826000613546565b50505050565b604080514660208201526bffffffffffffffffffffffff193060601b16918101919091527f416c6c6f7765645472616e7366657200000000000000000000000000000000006054820152606381018490526000908190611e349060830160405160208183030381529060405280519060200120613e13565b9050610d5484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508593925050613e4e9050565b600154600160a01b900460ff1615611ec55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b600080611ed18361317f565b6000828152600760208181526040808420805460ff1916909317909255905193955091935091611f0691859160019101614d5b565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529190529050611f4682611b306020870187614a5b565b610f2233611f5c61016087016101408801614a40565b60c08701803590611f709060a08a01614a40565b6001600160a01b0316929190613e72565b33611f946000546001600160a01b031690565b6001600160a01b031614611fd85760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527fb17659014001857e7557191ad74dc9e967b181eaed0895975325e3848debbc429060200161141a565b3360009081526003602052604090205460ff166120855760405162461bcd60e51b815260206004820152601660248201527f43616c6c6572206973206e6f7420676f7665726e6f72000000000000000000006044820152606401610ae3565b8281146120d45760405162461bcd60e51b815260206004820152601460248201527f5266713a206c656e677468206d69736d617463680000000000000000000000006044820152606401610ae3565b60005b8381101561227657620f42408383838181106120f5576120f5614de0565b905060200201602081019061210a9190614e0a565b63ffffffff161061215d5760405162461bcd60e51b815260206004820152601d60248201527f5266713a206665652070657263656e7461676520746f6f206c617267650000006044820152606401610ae3565b84848281811061216f5761216f614de0565b90506020020160208101906121849190614a5b565b6001600160401b03166000036121e0578282828181106121a6576121a6614de0565b90506020020160208101906121bb9190614e0a565b600860146101000a81548163ffffffff021916908363ffffffff160217905550612264565b8282828181106121f2576121f2614de0565b90506020020160208101906122079190614e0a565b6009600087878581811061221d5761221d614de0565b90506020020160208101906122329190614a5b565b6001600160401b031681526020810191909152604001600020805463ffffffff191663ffffffff929092169190911790555b8061226e81614e25565b9150506120d7565b507f541df5e570cf10ffe04899eebd9eebebd1c54e2bd4af9f24b23fb4a40c6ea00b84848484604051610f919493929190614e85565b600154600160a01b900460ff16156122f95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6000806123058561317f565b909250905061232761231f6101a087016101808801614a40565b8386866111eb565b6000828152600760208181526040808420805460ff1916909317909255905161235591859160019101614d5b565b60408051601f198184030181528282528051602091820120908301520160408051601f19818403018152919052905061239582611b306020890189614a5b565b6123d06123aa6101a088016101808901614a40565b6123bc61016089016101408a01614a40565b60c08901803590611f709060a08c01614a40565b7fb97bb040c4582b3252c1079bcea2a781f656ef09ceb53be48b2d615c61198bc58361240461016089016101408a01614a40565b61241460c08a0160a08b01614a40565b604080519384526001600160a01b03928316602085015291169082015260c0880135606082015260800160405180910390a1505050505050565b600154600160a01b900460ff161561249b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6004546001600160a01b03166124b76040850160208601614a40565b6001600160a01b03161461250d5760405162461bcd60e51b815260206004820152601760248201527f5266713a2073726320746f6b656e206d69736d617463680000000000000000006044820152606401610ae3565b600061251a848484613d86565b9050611db684826001613546565b600154600160a01b900460ff16156125755760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b61258560a0850160808601614a5b565b6001600160401b031661259b6020860186614a5b565b6001600160401b0316146125f15760405162461bcd60e51b815260206004820152601860248201527f5266713a206e6f742073616d6520636861696e207377617000000000000000006044820152606401610ae3565b60006125fc8561317f565b50905061261c6126146101a087016101808801614a40565b8285856111eb565b6126576126316101a087016101808801614a40565b61264361016088016101408901614a40565b60c08801803590611f709060a08b01614a40565b612662858286613546565b7fb97bb040c4582b3252c1079bcea2a781f656ef09ceb53be48b2d615c61198bc58161269661016088016101408901614a40565b6126a660c0890160a08a01614a40565b604080519384526001600160a01b03928316602085015291169082015260c08701356060820152608001611742565b600154600160a01b900460ff16156127225760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b61273260a0830160808401614a5b565b6001600160401b03166127486020840184614a5b565b6001600160401b03161461279e5760405162461bcd60e51b815260206004820152601860248201527f5266713a206e6f742073616d6520636861696e207377617000000000000000006044820152606401610ae3565b60006127a98361317f565b509050611164336127c261016086016101408701614a40565b60c08601803590611f709060a08901614a40565b336127e96000546001600160a01b031690565b6001600160a01b03161461282d5760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b82811461287c5760405162461bcd60e51b815260206004820152601460248201527f5266713a206c656e677468206d69736d617463680000000000000000000000006044820152606401610ae3565b60005b838110156129225782828281811061289957612899614de0565b90506020020160208101906128ae9190614a40565b600560008787858181106128c4576128c4614de0565b90506020020160208101906128d99190614a5b565b6001600160401b03168152602081019190915260400160002080546001600160a01b0319166001600160a01b03929092169190911790558061291a81614e25565b91505061287f565b507fb4739c640c5970d8ce88b6c31f3706099efca660e282d47b0a267a0bb572d8b784848484604051610f919493929190614ee5565b60006129676020830183614a5b565b6129776040840160208501614a40565b6040840135606085013561299160a0870160808801614a5b565b6129a160c0880160a08901614a40565b60c08801356129b76101008a0160e08b01614a5b565b6129c96101208b016101008c01614a5b565b6129db6101408c016101208d01614a40565b6129ed6101608d016101408e01614a40565b6129ff6101808e016101608f01614a40565b8d610180016020810190612a139190614a40565b604051602001612a2f9d9c9b9a99989796959493929190614f3b565b604051602081830303815290604052805190602001209050919050565b61137733613eaa565b600154600090600160a01b900460ff1615612aa55760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6000612ab2848434612d0f565b9050611499333060408701803590611f709060208a01614a40565b33612ae06000546001600160a01b031690565b6001600160a01b031614612b245760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b61130d81613eaa565b33612b406000546001600160a01b031690565b6001600160a01b031614612b845760405162461bcd60e51b815260206004820181905260248201526000805160206153068339815191526044820152606401610ae3565b6001600160a01b038116612c005760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610ae3565b61130d81613f63565b600154600160a01b900460ff1615612c565760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b600080612c648585856137fc565b6000828152600760205260409020805492945090925060049160ff191660018302179055506116e68160408701803590612ca19060208a01614a40565b6001600160a01b03169190613af8565b6001600160401b03821660009081526009602052604081205463ffffffff16808203612ce95750600854600160a01b900463ffffffff165b620f4240612cfd63ffffffff83168561506a565b612d079190615081565b949350505050565b600042836001600160401b0316118015612d4a57506001600160401b038316612d3f610100860160e08701614a5b565b6001600160401b0316115b612d965760405162461bcd60e51b815260206004820152601b60248201527f5266713a20696e617070726f70726961746520646561646c696e6500000000006044820152606401610ae3565b6000612daa61016086016101408701614a40565b6001600160a01b031614158015612ddc57506000612dd06101a086016101808701614a40565b6001600160a01b031614155b612e4e5760405162461bcd60e51b815260206004820152602a60248201527f5266713a20696e76616c6964207265636569766572206f72206c69717569646960448201527f747950726f7669646572000000000000000000000000000000000000000000006064820152608401610ae3565b6001600160401b034616612e656020860186614a5b565b6001600160401b031614612ebb5760405162461bcd60e51b815260206004820152601960248201527f5266713a2073726320636861696e4964206d69736d61746368000000000000006044820152606401610ae3565b33612ece61014086016101208701614a40565b6001600160a01b031614612f245760405162461bcd60e51b815260206004820152601460248201527f5266713a2073656e646572206d69736d617463680000000000000000000000006044820152606401610ae3565b6000612f2f85612958565b90506000808281526007602052604090205460ff166008811115612f5557612f5561485f565b14612fa25760405162461bcd60e51b815260206004820152601660248201527f5266713a2071756f7465206861736820657869737473000000000000000000006044820152606401610ae3565b6000612fc1612fb760a0880160808901614a5b565b8760400135612cb1565b9050612fd560608701356040880135614d48565b8111156130245760405162461bcd60e51b815260206004820152601e60248201527f5266713a20696e73756666696369656e742070726f746f636f6c2066656500006044820152606401610ae3565b6000828152600760205260409020805460ff1916600117905561304d60a0870160808801614a5b565b6001600160401b03166130636020880188614a5b565b6001600160401b03161461313d57600060058161308660a08a0160808b01614a5b565b6001600160401b031681526020810191909152604001600020546001600160a01b03169050806130f85760405162461bcd60e51b815260206004820152601960248201527f5266713a2064737420636f6e7472616374206e6f7420736574000000000000006044820152606401610ae3565b60008360405160200161310d91815260200190565b60408051601f19818403018152919052905061313a8261313360a08b0160808c01614a5b565b8389613419565b50505b7f3e4de2d1674631d426ae2a89635b421e6d40a31d27681afdf0eed67e81d07bcb828760405161316e9291906150a3565b60405180910390a150949350505050565b60008042613194610100850160e08601614a5b565b6001600160401b0316116131ea5760405162461bcd60e51b815260206004820152601d60248201527f5266713a207472616e7366657220646561646c696e65207061737365640000006044820152606401610ae3565b6001600160401b03461661320460a0850160808601614a5b565b6001600160401b03161461325a5760405162461bcd60e51b815260206004820152601960248201527f5266713a2064737420636861696e4964206d69736d61746368000000000000006044820152606401610ae3565b600061326584612958565b905060006005816132796020880188614a5b565b6001600160401b031681526020810191909152604001600020546001600160a01b031690506132ae60a0860160808701614a5b565b6001600160401b03166132c46020870187614a5b565b6001600160401b03161461339d5760008281526007602052604081205460ff1660088111156132f5576132f561485f565b146133425760405162461bcd60e51b815260206004820152601b60248201527f5266713a2071756f746520616c726561647920657865637574656400000000006044820152606401610ae3565b6001600160a01b0381166133985760405162461bcd60e51b815260206004820152601d60248201527f5266713a206473742072667120636f6e7472616374206e6f74207365740000006044820152606401610ae3565b61340f565b600160008381526007602052604090205460ff1660088111156133c2576133c261485f565b1461340f5760405162461bcd60e51b815260206004820152601d60248201527f5266713a206e6f206465706f736974206f6e2073616d6520636861696e0000006044820152606401610ae3565b9094909350915050565b600154611db6908590859085906001600160a01b031685613fb3565b6004546001600160a01b031661348d5760405162461bcd60e51b815260206004820152601860248201527f5266713a206e61746976652077726170206e6f742073657400000000000000006044820152606401610ae3565b6000826001600160a01b03168261c35090604051600060405180830381858888f193505050503d80600081146134df576040519150601f19603f3d011682016040523d82523d6000602084013e6134e4565b606091505b50509050806135415760405162461bcd60e51b8152602060048201526024808201527f5266713a206661696c656420746f207472616e73666572206e6174697665207460448201526337b5b2b760e11b6064820152608401610ae3565b505050565b61355860608401356040850135614d48565b600a600061356c6040870160208801614a40565b6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461359b9190615215565b909155505080156135e3576000828152600760205260409020805460ff191660031790556135de6135d46101a085016101808601614a40565b8460600135613990565b613626565b6000828152600760205260409020805460ff191660021790556136266136116101a085016101808601614a40565b6060850135612ca16040870160208801614a40565b7ff29b32a17c591b8b3b1216ce0ffb67c07f3478e99b50c5ccf8602878b1ee63768261365a6101a086016101808701614a40565b61366a6040870160208801614a40565b604080519384526001600160a01b039283166020850152911690820152606080860135908201526080016111de565b6001600160a01b03811660009081526003602052604090205460ff16156137025760405162461bcd60e51b815260206004820152601b60248201527f4163636f756e7420697320616c726561647920676f7665726e6f7200000000006044820152606401610ae3565b6001600160a01b038116600081815260036020908152604091829020805460ff1916600117905590519182527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5910161141a565b600154600160a01b900460ff166137af5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610ae3565b6001805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600080600061380a86612958565b9050600160008281526007602052604090205460ff1660088111156138315761383161485f565b1461387e5760405162461bcd60e51b815260206004820152601960248201527f5266713a20696e636f72726563742071756f74652068617368000000000000006044820152606401610ae3565b61388e60a0870160808801614a5b565b6001600160401b03166138a46020880188614a5b565b6001600160401b0316146138c4576138bf858583600261401e565b613936565b426138d6610100880160e08901614a5b565b6001600160401b0316106139365760405162461bcd60e51b815260206004820152602160248201527f5266713a207472616e7366657220646561646c696e65206e6f742070617373656044820152601960fa1b6064820152608401610ae3565b60008061394b61018089016101608a01614a40565b6001600160a01b0316146139705761396b61018088016101608901614a40565b613982565b61398261014088016101208901614a40565b919791965090945050505050565b6004546001600160a01b03166139e85760405162461bcd60e51b815260206004820152601860248201527f5266713a206e61746976652077726170206e6f742073657400000000000000006044820152606401610ae3565b60048054604051632e1a7d4d60e01b81529182018390526001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015613a2c57600080fd5b505af1158015613a40573d6000803e3d6000fd5b505050506000826001600160a01b03168261c35090604051600060405180830381858888f193505050503d8060008114613a96576040519150601f19603f3d011682016040523d82523d6000602084013e613a9b565b606091505b50509050806135415760405162461bcd60e51b8152602060048201526024808201527f5266713a206661696c656420746f207769746864726177206e6174697665207460448201526337b5b2b760e11b6064820152608401610ae3565b6040516001600160a01b03831660248201526044810182905261354190849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614191565b6001600160a01b03811660009081526002602052604090205460ff16613bf05760405162461bcd60e51b815260206004820152601560248201527f4163636f756e74206973206e6f742070617573657200000000000000000000006044820152606401610ae3565b6001600160a01b038116600081815260026020908152604091829020805460ff1916905590519182527fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e910161141a565b6001600160a01b03811660009081526002602052604090205460ff1615613caa5760405162461bcd60e51b815260206004820152601960248201527f4163636f756e7420697320616c726561647920706175736572000000000000006044820152606401610ae3565b6001600160a01b038116600081815260026020908152604091829020805460ff1916600117905590519182527f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f8910161141a565b600154600160a01b900460ff1615613d4b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610ae3565b6001805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586137df3390565b600080613d9285612958565b9050600160008281526007602052604090205460ff166008811115613db957613db961485f565b14613e065760405162461bcd60e51b815260206004820152601960248201527f5266713a20696e636f72726563742071756f74652068617368000000000000006044820152606401610ae3565b612d07848483600161401e565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01612a2f565b6000806000613e5d8585614276565b91509150613e6a816142e4565b509392505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611db69085906323b872dd60e01b90608401613b24565b6001600160a01b03811660009081526003602052604090205460ff16613f125760405162461bcd60e51b815260206004820152601760248201527f4163636f756e74206973206e6f7420676f7665726e6f720000000000000000006044820152606401610ae3565b6001600160a01b038116600081815260036020908152604091829020805460ff1916905590519182527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b910161141a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b604051634f9e72ad60e11b81526001600160a01b03831690639f3ce55a908390613fe590899089908990600401615278565b6000604051808303818588803b158015613ffe57600080fd5b505af1158015614012573d6000803e3d6000fd5b50505050505050505050565b60008282604051602001614033929190614d5b565b60408051601f1981840301815291815281516020928301206000818152600690935291205490915060ff16614117576001546040516000916001600160a01b03169061408290889088906152a9565b6000604051808303816000865af19150503d80600081146140bf576040519150601f19603f3d011682016040523d82523d6000602084013e6140c4565b606091505b50509050806141155760405162461bcd60e51b815260206004820152601260248201527f65786563757465206d7367206661696c656400000000000000000000000000006044820152606401610ae3565b505b60008181526006602052604090205460ff166141755760405162461bcd60e51b815260206004820152601060248201527f5266713a20696e76616c6964206d7367000000000000000000000000000000006044820152606401610ae3565b6000908152600660205260409020805460ff1916905550505050565b60006141e6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661449a9092919063ffffffff16565b805190915015613541578080602001905181019061420491906152b9565b6135415760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610ae3565b60008082516041036142ac5760208301516040840151606085015160001a6142a0878285856144a9565b945094505050506142dd565b82516040036142d557602083015160408401516142ca868383614596565b9350935050506142dd565b506000905060025b9250929050565b60008160048111156142f8576142f861485f565b036143005750565b60018160048111156143145761431461485f565b036143615760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610ae3565b60028160048111156143755761437561485f565b036143c25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610ae3565b60038160048111156143d6576143d661485f565b0361442e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610ae3565b60048160048111156144425761444261485f565b0361130d5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610ae3565b6060612d0784846000856145e8565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156144e0575060009050600361458d565b8460ff16601b141580156144f857508460ff16601c14155b15614509575060009050600461458d565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561455d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166145865760006001925092505061458d565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316816145cc60ff86901c601b615215565b90506145da878288856144a9565b935093505050935093915050565b6060824710156146605760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610ae3565b6001600160a01b0385163b6146b75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ae3565b600080866001600160a01b031685876040516146d391906152d6565b60006040518083038185875af1925050503d8060008114614710576040519150601f19603f3d011682016040523d82523d6000602084013e614715565b606091505b50915091506115588282866060831561472f575081611499565b82511561473f5782518084602001fd5b8160405162461bcd60e51b8152600401610ae391906152f2565b60008083601f84011261476b57600080fd5b5081356001600160401b0381111561478257600080fd5b6020830191508360208285010111156142dd57600080fd5b80356001600160401b03811681146147b157600080fd5b919050565b80356001600160a01b03811681146147b157600080fd5b600080600080600080608087890312156147e657600080fd5b86356001600160401b03808211156147fd57600080fd5b6148098a838b01614759565b909850965086915061481d60208a0161479a565b9550604089013591508082111561483357600080fd5b5061484089828a01614759565b90945092506148539050606088016147b6565b90509295509295509295565b634e487b7160e01b600052602160045260246000fd5b6003811061130d5761130d61485f565b6020810161489283614875565b91905290565b60006101a082840312156148ab57600080fd5b50919050565b6000806101c083850312156148c557600080fd5b6148cf8484614898565b91506148de6101a0840161479a565b90509250929050565b6000806000806000608086880312156148ff57600080fd5b614908866147b6565b94506020860135935060408601356001600160401b0381111561492a57600080fd5b61493688828901614759565b90945092506149499050606087016147b6565b90509295509295909350565b60006101a0828403121561496857600080fd5b6114998383614898565b801515811461130d57600080fd5b6000806101c0838503121561499457600080fd5b61499e8484614898565b91506101a08301356149af81614972565b809150509250929050565b6000602082840312156149cc57600080fd5b5035919050565b60208101600983106148925761489261485f565b600080600080606085870312156149fd57600080fd5b614a06856147b6565b93506020850135925060408501356001600160401b03811115614a2857600080fd5b614a3487828801614759565b95989497509550505050565b600060208284031215614a5257600080fd5b611499826147b6565b600060208284031215614a6d57600080fd5b6114998261479a565b60008060208385031215614a8957600080fd5b82356001600160401b03811115614a9f57600080fd5b614aab85828601614759565b90969095509350505050565b600080600080600080600060c0888a031215614ad257600080fd5b614adb886147b6565b9650614ae9602089016147b6565b955060408801359450614afe6060890161479a565b935060808801356001600160401b03811115614b1957600080fd5b614b258a828b01614759565b9094509250614b38905060a089016147b6565b905092959891949750929550565b60008060006101c08486031215614b5c57600080fd5b614b668585614898565b92506101a08401356001600160401b03811115614b8257600080fd5b614b8e86828701614759565b9497909650939450505050565b600080600080600060808688031215614bb357600080fd5b614bbc866147b6565b9450614bca6020870161479a565b935060408601356001600160401b0381111561492a57600080fd5b600080600060408486031215614bfa57600080fd5b8335925060208401356001600160401b03811115614b8257600080fd5b60008083601f840112614c2957600080fd5b5081356001600160401b03811115614c4057600080fd5b6020830191508360208260051b85010111156142dd57600080fd5b60008060008060408587031215614c7157600080fd5b84356001600160401b0380821115614c8857600080fd5b614c9488838901614c17565b90965094506020870135915080821115614cad57600080fd5b50614a3487828801614c17565b6000806000806101e08587031215614cd157600080fd5b614cdb8686614898565b93506101a0850135614cec81614972565b92506101c08501356001600160401b03811115614a2857600080fd5b60008060408385031215614d1b57600080fd5b614d248361479a565b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610cf157610cf1614d32565b828152614d6782614875565b60f89190911b6020820152602101919050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600060208284031215614dbb57600080fd5b5051919050565b80356020831015610cf157600019602084900360031b1b1692915050565b634e487b7160e01b600052603260045260246000fd5b803563ffffffff811681146147b157600080fd5b600060208284031215614e1c57600080fd5b61149982614df6565b600060018201614e3757614e37614d32565b5060010190565b8183526000602080850194508260005b85811015614e7a576001600160401b03614e678361479a565b1687529582019590820190600101614e4e565b509495945050505050565b604081526000614e99604083018688614e3e565b8281036020848101919091528482528591810160005b86811015614ed85763ffffffff614ec585614df6565b1682529282019290820190600101614eaf565b5098975050505050505050565b604081526000614ef9604083018688614e3e565b8281036020848101919091528482528591810160005b86811015614ed8576001600160a01b03614f28856147b6565b1682529282019290820190600101614f0f565b6001600160c01b03198e60c01b1681526bffffffffffffffffffffffff198d60601b1660088201528b601c8201528a603c820152614f88605c82018b60c01b6001600160c01b0319169052565b614fa6606482018a60601b6bffffffffffffffffffffffff19169052565b876078820152614fc5609882018860c01b6001600160c01b0319169052565b614fde60a082018760c01b6001600160c01b0319169052565b614ffc60a882018660601b6bffffffffffffffffffffffff19169052565b61501a60bc82018560601b6bffffffffffffffffffffffff19169052565b61503860d082018460601b6bffffffffffffffffffffffff19169052565b61505660e482018360601b6bffffffffffffffffffffffff19169052565b60f8019d9c50505050505050505050505050565b8082028115828204841417610cf157610cf1614d32565b60008261509e57634e487b7160e01b600052601260045260246000fd5b500490565b8281526101c081016150c8602083016150bb8561479a565b6001600160401b03169052565b6150d4602084016147b6565b6001600160a01b03811660408401525060408301356060830152606083013560808301526151046080840161479a565b6001600160401b03811660a08401525061512060a084016147b6565b6001600160a01b03811660c08401525060c083013560e083015261514660e0840161479a565b61010061515d818501836001600160401b03169052565b61516881860161479a565b915050610120615182818501836001600160401b03169052565b61518d8186016147b6565b9150506101406151a7818501836001600160a01b03169052565b6151b28186016147b6565b9150506101606151cc818501836001600160a01b03169052565b6151d78186016147b6565b9150506101806151f1818501836001600160a01b03169052565b6151fc8186016147b6565b915050613e6a6101a08401826001600160a01b03169052565b80820180821115610cf157610cf1614d32565b60005b8381101561524357818101518382015260200161522b565b50506000910152565b60008151808452615264816020860160208601615228565b601f01601f19169290920160200192915050565b6001600160a01b03841681526001600160401b0383166020820152606060408201526000610d54606083018461524c565b8183823760009101908152919050565b6000602082840312156152cb57600080fd5b815161149981614972565b600082516152e8818460208701615228565b9190910192915050565b602081526000611499602083018461524c56fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a2646970667358221220d0cf8bb66abb774cf11009a7b38b3d1b5a1d355754b34237da7d1a494fad05fb64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000afdb9c40c7144022811f034ee07ce2e110093fe6
-----Decoded View---------------
Arg [0] : _messageBus (address): 0xaFDb9C40C7144022811F034EE07Ce2E110093fe6
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000afdb9c40c7144022811f034ee07ce2e110093fe6
Deployed Bytecode Sourcemap
536:19336:8:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1086:227:10;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3405:579:8;;;;;;:::i;:::-;;:::i;:::-;;;2740:25:29;;;2728:2;2713:18;3405:579:8;2594:177:29;3906:234:10;;;;;;:::i;:::-;;:::i;1947:27:8:-;;;;;;;;;;-1:-1:-1;1947:27:8;;;;-1:-1:-1;;;1947:27:8;;;;;;;;;3581:10:29;3569:23;;;3551:42;;3539:2;3524:18;1947:27:8;3407:192:29;6024:738:8;;;;;;:::i;:::-;;:::i;:::-;;8081:632;;;;;;:::i;:::-;;:::i;1862:45::-;;;;;;;;;;-1:-1:-1;1862:45:8;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;16926:437::-;;;;;;;;;;-1:-1:-1;16926:437:8;;;;;:::i;:::-;;:::i;1914:27::-;;;;;;;;;;-1:-1:-1;1914:27:8;;;;-1:-1:-1;;;;;1914:27:8;;;;;;-1:-1:-1;;;;;5623:55:29;;;5605:74;;5593:2;5578:18;1914:27:8;5459:226:29;561:95:19;;;;;;;;;;-1:-1:-1;561:95:19;;;;;:::i;:::-;;:::i;2055:48:8:-;;;;;;;;;;-1:-1:-1;2055:48:8;;;;;:::i;:::-;;;;;;;;;;;;;;;;563:64:21;;;;;;;;;;;;;:::i;1671:25:8:-;;;;;;;;;;-1:-1:-1;1671:25:8;;;;-1:-1:-1;;;;;1671:25:8;;;633:102:21;;;;;;;;;;-1:-1:-1;633:102:21;;;;;:::i;:::-;-1:-1:-1;;;;;712:16:21;689:4;712:16;;;:7;:16;;;;;;;;;633:102;;;;6235:14:29;;6228:22;6210:41;;6198:2;6183:18;633:102:21;6070:187:29;242:146:9;;;;;;;;;;-1:-1:-1;242:146:9;;;;;:::i;:::-;;:::i;16475:139:8:-;;;;;;;;;;-1:-1:-1;16475:139:8;;;;;:::i;:::-;;:::i;15137:225::-;;;;;;;;;;-1:-1:-1;15137:225:8;;;;;:::i;:::-;;:::i;3125:289:10:-;;;;;;:::i;:::-;;:::i;19766:104:8:-;;;;;;;;;;-1:-1:-1;19766:104:8;;;;;:::i;:::-;;:::i;1098:84:22:-;;;;;;;;;;-1:-1:-1;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1098:84;;13107:483:8;;;;;;;;;;-1:-1:-1;13107:483:8;;;;;:::i;:::-;;:::i;14797:334::-;;;;;;;;;;-1:-1:-1;14797:334:8;;;;;:::i;:::-;;:::i;836:95:21:-;;;;;;;;;;-1:-1:-1;836:95:21;;;;;:::i;:::-;;:::i;937:75::-;;;;;;;;;;;;;:::i;11866:824:8:-;;;;;;:::i;:::-;;:::i;200:39:21:-;;;;;;;;;;-1:-1:-1;200:39:21;;;;;:::i;:::-;;;;;;;;;;;;;;;;741:89;;;;;;;;;;-1:-1:-1;741:89:21;;;;;:::i;:::-;;:::i;497:60::-;;;;;;;;;;;;;:::i;1479:85:20:-;;;;;;;;;;-1:-1:-1;1525:7:20;1551:6;-1:-1:-1;;;;;1551:6:20;1479:85;;14251:540:8;;;;;;:::i;:::-;;:::i;210:25:9:-;;;;;;;;;;-1:-1:-1;210:25:9;;;;-1:-1:-1;;;;;210:25:9;;;10266:225:8;;;;;;;;;;-1:-1:-1;10266:225:8;;;;;:::i;:::-;;:::i;16620:300::-;;;;;;;;;;-1:-1:-1;16620:300:8;;;;;:::i;:::-;;:::i;5430:588::-;;;;;;:::i;:::-;;:::i;19599:161::-;;;;;;;;;;-1:-1:-1;19599:161:8;;;;;:::i;:::-;;:::i;19035:558::-;;;;;;;;;;-1:-1:-1;19035:558:8;;;;;:::i;:::-;;:::i;6868:703::-;;;;;;:::i;:::-;;:::i;10497:305::-;;;;;;;;;;-1:-1:-1;10497:305:8;;;;;:::i;:::-;;:::i;8825:643::-;;;;;;:::i;:::-;;:::i;2140:46::-;;;;;;;;;;-1:-1:-1;2140:46:8;;;;;:::i;:::-;;;;;;;;;;;;;;2231:48;;;;;;;;;;-1:-1:-1;2231:48:8;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;2231:48:8;;;7577:498;;;;;;:::i;:::-;;:::i;18590:439::-;;;;;;;;;;-1:-1:-1;18590:439:8;;;;;:::i;:::-;;:::i;1702:52::-;;;;;;;;;;-1:-1:-1;1702:52:8;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;1702:52:8;;;15519:685;;;;;;;;;;-1:-1:-1;15519:685:8;;;;;:::i;:::-;;:::i;1779:45::-;;;;;;;;;;-1:-1:-1;1779:45:8;;;;;:::i;:::-;;;;;;;;;;;;;;;;769:79:19;;;;;;;;;;;;;:::i;136:41::-;;;;;;;;;;-1:-1:-1;136:41:19;;;;;:::i;:::-;;;;;;;;;;;;;;;;447:108;;;;;;;;;;-1:-1:-1;447:108:19;;;;;:::i;:::-;-1:-1:-1;;;;;529:19:19;506:4;529:19;;;:9;:19;;;;;;;;;447:108;3034:365:8;;;;;;:::i;:::-;;:::i;662:101:19:-;;;;;;;;;;-1:-1:-1;662:101:19;;;;;:::i;:::-;;:::i;1916:189:20:-;;;;;;;;;;-1:-1:-1;1916:189:20;;;;;:::i;:::-;;:::i;12696:405:8:-;;;;;;;;;;-1:-1:-1;12696:405:8;;;;;:::i;:::-;;:::i;16210:259::-;;;;;;;;;;-1:-1:-1;16210:259:8;;;;;:::i;:::-;;:::i;1086:227:10:-;294:10;;1294:15;;-1:-1:-1;;;;;294:10:10;280;:24;272:62;;;;-1:-1:-1;;;272:62:10;;12337:2:29;272:62:10;;;12319:21:29;12376:2;12356:18;;;12349:30;12415:27;12395:18;;;12388:55;12460:18;;272:62:10;;;;;;;;;1086:227;;;;;;;;:::o;3405:579:8:-;1168:7:22;;3554::8;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;3585:10:8::1;::::0;-1:-1:-1;;;;;3585:10:8::1;3577:61;;;::::0;-1:-1:-1;;;3577:61:8;;13036:2:29;3577:61:8::1;::::0;::::1;13018:21:29::0;13075:2;13055:18;;;13048:30;13114:26;13094:18;;;13087:54;13158:18;;3577:61:8::1;12834:348:29::0;3577:61:8::1;3675:10;::::0;-1:-1:-1;;;;;3675:10:8::1;3656:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;3656:29:8::1;;3648:65;;;::::0;-1:-1:-1;;;3648:65:8;;13389:2:29;3648:65:8::1;::::0;::::1;13371:21:29::0;13428:2;13408:18;;;13401:30;13467:25;13447:18;;;13440:53;13510:18;;3648:65:8::1;13187:347:29::0;3648:65:8::1;3744:6;:16;;;3731:9;:29;;3723:66;;;::::0;-1:-1:-1;;;3723:66:8;;13741:2:29;3723:66:8::1;::::0;::::1;13723:21:29::0;13780:2;13760:18;;;13753:30;13819:26;13799:18;;;13792:54;13863:18;;3723:66:8::1;13539:348:29::0;3723:66:8::1;3799:17;3819:70;3831:6:::0;3839:19;3860:28:::1;3872:16;::::0;::::1;;3860:9;:28;:::i;:::-;3819:11;:70::i;:::-;3799:90;;3905:10;;;;;;;;;-1:-1:-1::0;;;;;3905:10:8::1;-1:-1:-1::0;;;;;3899:25:8::1;;3932:6;:16;;;3899:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;3968:9:8;;-1:-1:-1;;;;;1451:1:22::1;3405:579:8::0;;;;:::o;3906:234:10:-;294:10;;4121:15;;-1:-1:-1;;;;;294:10:10;280;:24;272:62;;;;-1:-1:-1;;;272:62:10;;12337:2:29;272:62:10;;;12319:21:29;12376:2;12356:18;;;12349:30;12415:27;12395:18;;;12388:55;12460:18;;272:62:10;12135:349:29;272:62:10;3906:234;;;;;;;:::o;6024:738:8:-;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;6142:10:8::1;::::0;-1:-1:-1;;;;;6142:10:8::1;6123:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;6123:29:8::1;;6115:65;;;::::0;-1:-1:-1;;;6115:65:8;;14359:2:29;6115:65:8::1;::::0;::::1;14341:21:29::0;14398:2;14378:18;;;14371:30;14437:25;14417:18;;;14410:53;14480:18;;6115:65:8::1;14157:347:29::0;6115:65:8::1;6211:6;:16;;;6198:9;:29;;6190:66;;;::::0;-1:-1:-1;;;6190:66:8;;13741:2:29;6190:66:8::1;::::0;::::1;13723:21:29::0;13780:2;13760:18;;;13753:30;13819:26;13799:18;;;13792:54;13863:18;;6190:66:8::1;13539:348:29::0;6190:66:8::1;6267:17;6286:19:::0;6309:25:::1;6327:6;6309:17;:25::i;:::-;6344:17;::::0;;;:6:::1;:17;::::0;;;;;;;:52;;-1:-1:-1;;6344:52:8::1;6364:32;6344:52;::::0;;6456:48;6344:17;;-1:-1:-1;6266:68:8;;-1:-1:-1;6344:17:8;6456:48:::1;::::0;6344:17;;:52;;6456:48:::1;;:::i;:::-;;::::0;;-1:-1:-1;;6456:48:8;;::::1;::::0;;;;;;6446:59;;6456:48:::1;6446:59:::0;;::::1;::::0;6429:77;;::::1;14967:19:29::0;15002:12;6429:77:8::1;::::0;;-1:-1:-1;;6429:77:8;;::::1;::::0;;;;;;;-1:-1:-1;6516:82:8::1;6528:11:::0;6541:17:::1;6429:77;6541:17:::0;::::1;:6:::0;:17:::1;:::i;:::-;6560:7:::0;6569:28:::1;6581:16;::::0;::::1;;6569:9;:28;:::i;:::-;6516:11;:82::i;:::-;6608:55;6629:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;6646:6;:16;;;6608:20;:55::i;:::-;6678:77;6693:9:::0;6704:15:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;6721;::::0;;;::::1;::::0;::::1;;:::i;:::-;6678:77;::::0;;15256:25:29;;;-1:-1:-1;;;;;15378:15:29;;;15373:2;15358:18;;15351:43;15430:15;;15410:18;;;15403:43;6738:16:8::1;::::0;::::1;;15477:2:29::0;15462:18;;15455:34;15243:3;15228:19;6678:77:8::1;;;;;;;;6105:657;;;6024:738:::0;:::o;8081:632::-;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;8228:17:8::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;8207:38:8::1;:17;;::::0;::::1;:6:::0;:17:::1;:::i;:::-;-1:-1:-1::0;;;;;8207:38:8::1;;8199:75;;;::::0;-1:-1:-1;;;8199:75:8;;15702:2:29;8199:75:8::1;::::0;::::1;15684:21:29::0;15741:2;15721:18;;;15714:30;15780:26;15760:18;;;15753:54;15824:18;;8199:75:8::1;15500:348:29::0;8199:75:8::1;8311:10;::::0;-1:-1:-1;;;;;8311:10:8::1;8292:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;8292:29:8::1;;8284:65;;;::::0;-1:-1:-1;;;8284:65:8;;14359:2:29;8284:65:8::1;::::0;::::1;14341:21:29::0;14398:2;14378:18;;;14371:30;14437:25;14417:18;;;14410:53;14480:18;;8284:65:8::1;14157:347:29::0;8284:65:8::1;8380:6;:16;;;8367:9;:29;8359:75;;;::::0;-1:-1:-1;;;8359:75:8;;16055:2:29;8359:75:8::1;::::0;::::1;16037:21:29::0;16094:2;16074:18;;;16067:30;16133:34;16113:18;;;16106:62;-1:-1:-1;;;16184:18:29;;;16177:31;16225:19;;8359:75:8::1;15853:397:29::0;8359:75:8::1;8445:17;8468:25;8486:6;8468:17;:25::i;:::-;-1:-1:-1::0;8444:49:8;-1:-1:-1;8503:55:8::1;8524:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;8541:6;:16;;;8503:20;:55::i;:::-;8568:46;8580:6;8588:9;8599:14;8568:11;:46::i;:::-;8629:77;8644:9:::0;8655:15:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;8672;::::0;;;::::1;::::0;::::1;;:::i;:::-;8629:77;::::0;;15256:25:29;;;-1:-1:-1;;;;;15378:15:29;;;15373:2;15358:18;;15351:43;15430:15;;15410:18;;;15403:43;8689:16:8::1;::::0;::::1;;15477:2:29::0;15462:18;;15455:34;15243:3;15228:19;8629:77:8::1;;;;;;;;8189:524;8081:632:::0;;:::o;16926:437::-;17077:14;17094:38;17115:10;17127:4;;17094:20;:38::i;:::-;17077:55;;17173:18;-1:-1:-1;;;;;17163:28:8;:6;-1:-1:-1;;;;;17163:28:8;;:144;;;-1:-1:-1;;;;;;17212:33:8;;;17257:1;17212:33;;;:13;:33;;;;;;;:47;;;;:94;;-1:-1:-1;;;;;;17273:33:8;;;;;;;:13;:33;;;;;;17263:43;;;17273:33;;17263:43;17212:94;17142:214;;;;-1:-1:-1;;;17142:214:8;;16457:2:29;17142:214:8;;;16439:21:29;16496:2;16476:18;;;16469:30;16535:25;16515:18;;;16508:53;16578:18;;17142:214:8;16255:347:29;17142:214:8;17067:296;16926:437;;;;:::o;561:95:19:-;1702:10:20;1691:7;1525;1551:6;-1:-1:-1;;;;;1551:6:20;;1479:85;1691:7;-1:-1:-1;;;;;1691:21:20;;1683:66;;;;-1:-1:-1;;;1683:66:20;;16809:2:29;1683:66:20;;;16791:21:29;;;16828:18;;;16821:30;-1:-1:-1;;;;;;;;;;;16867:18:29;;;16860:62;16939:18;;1683:66:20;16607:356:29;1683:66:20;627:22:19::1;640:8;627:12;:22::i;:::-;561:95:::0;:::o;563:64:21:-;437:10;689:4;712:16;;;:7;:16;;;;;;;;420:53;;;;-1:-1:-1;;;420:53:21;;17170:2:29;420:53:21;;;17152:21:29;17209:2;17189:18;;;17182:30;17248:22;17228:18;;;17221:50;17288:18;;420:53:21;16968:344:29;420:53:21;610:10:::1;:8;:10::i;:::-;563:64::o:0;242:146:9:-;1702:10:20;1691:7;1525;1551:6;-1:-1:-1;;;;;1551:6:20;;1479:85;1691:7;-1:-1:-1;;;;;1691:21:20;;1683:66;;;;-1:-1:-1;;;1683:66:20;;16809:2:29;1683:66:20;;;16791:21:29;;;16828:18;;;16821:30;-1:-1:-1;;;;;;;;;;;16867:18:29;;;16860:62;16939:18;;1683:66:20;16607:356:29;1683:66:20;313:10:9::1;:24:::0;;-1:-1:-1;;;;;;313:24:9::1;-1:-1:-1::0;;;;;313:24:9;::::1;::::0;;::::1;::::0;;;352:29:::1;::::0;5605:74:29;;;352:29:9::1;::::0;5593:2:29;5578:18;352:29:9::1;;;;;;;;242:146:::0;:::o;16475:139:8:-;16578:10;;16566:41;;-1:-1:-1;;;16566:41:8;;16540:7;;-1:-1:-1;;;;;16578:10:8;;16566:31;;:41;;16598:8;;;;16566:41;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;16559:48;16475:139;-1:-1:-1;;;16475:139:8:o;15137:225::-;-1:-1:-1;;;;;15208:21:8;;15204:152;;15267:10;15253:25;;;;:13;:25;;;;;15245:34;;-1:-1:-1;;;;;;15245:34:8;;;561:95:19;:::o;15204:152:8:-;15324:10;15310:25;;;;:13;:25;;;;;:35;;-1:-1:-1;;;;;15310:35:8;;-1:-1:-1;;;;;;15310:35:8;;;;;;15137:225;:::o;3125:289:10:-;294:10;;3395:15;;-1:-1:-1;;;;;294:10:10;280;:24;272:62;;;;-1:-1:-1;;;272:62:10;;12337:2:29;272:62:10;;;12319:21:29;12376:2;12356:18;;;12349:30;12415:27;12395:18;;;12388:55;12460:18;;272:62:10;12135:349:29;272:62:10;3125:289;;;;;;;;;:::o;19766:104:8:-;1702:10:20;1691:7;1525;1551:6;-1:-1:-1;;;;;1551:6:20;;1479:85;1691:7;-1:-1:-1;;;;;1691:21:20;;1683:66;;;;-1:-1:-1;;;1683:66:20;;16809:2:29;1683:66:20;;;16791:21:29;;;16828:18;;;16821:30;-1:-1:-1;;;;;;;;;;;16867:18:29;;;16860:62;16939:18;;1683:66:20;16607:356:29;1683:66:20;19839:10:8::1;:24:::0;;-1:-1:-1;;;;;;19839:24:8::1;-1:-1:-1::0;;;;;19839:24:8;;;::::1;::::0;;;::::1;::::0;;19766:104::o;13107:483::-;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;13252:10:8::1;::::0;-1:-1:-1;;;;;13252:10:8::1;13233:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;13233:29:8::1;;13225:65;;;::::0;-1:-1:-1;;;13225:65:8;;13389:2:29;13225:65:8::1;::::0;::::1;13371:21:29::0;13428:2;13408:18;;;13401:30;13467:25;13447:18;;;13440:53;13510:18;;13225:65:8::1;13187:347:29::0;13225:65:8::1;13301:17;13320:16:::0;13340:40:::1;13355:6;13363:16;;13340:14;:40::i;:::-;13390:17;::::0;;;:6:::1;:17;::::0;;;;:49;;-1:-1:-1;;13390:49:8::1;13410:29;13390:49;::::0;;:17;;-1:-1:-1;13300:80:8;-1:-1:-1;13449:55:8::1;13470:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;13487:6;:16;;;13449:20;:55::i;:::-;13519:64;13528:9:::0;13539:8;13549:15:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;13566:16;13519:64:::0;;15256:25:29;;;-1:-1:-1;;;;;15378:15:29;;;15373:2;15358:18;;15351:43;15430:15;;15410:18;;;15403:43;13566:16:8;::::1;;15477:2:29::0;15462:18;;15455:34;15243:3;15228:19;13519:64:8::1;;;;;;;;13215:375;;13107:483:::0;;;:::o;14797:334::-;14860:12;;-1:-1:-1;;;;;14860:12:8;14852:68;;;;-1:-1:-1;;;14852:68:8;;18101:2:29;14852:68:8;;;18083:21:29;18140:2;18120:18;;;18113:30;18179:31;18159:18;;;18152:59;18228:18;;14852:68:8;17899:353:29;14852:68:8;-1:-1:-1;;;;;14950:19:8;;;14930:17;14950:19;;;:11;:19;;;;;;;14979:23;;;15040:12;;14950:19;;15012:52;;14950:19;15040:12;14950:19;15012:27;:52::i;:::-;15092:12;;15079:45;;;-1:-1:-1;;;;;15092:12:8;;;18520:34:29;;18590:15;;;18585:2;18570:18;;18563:43;18622:18;;18615:34;;;15079:45:8;;18447:2:29;18432:18;15079:45:8;;;;;;;14842:289;14797:334;:::o;836:95:21:-;1702:10:20;1691:7;1525;1551:6;-1:-1:-1;;;;;1551:6:20;;1479:85;1691:7;-1:-1:-1;;;;;1691:21:20;;1683:66;;;;-1:-1:-1;;;1683:66:20;;16809:2:29;1683:66:20;;;16791:21:29;;;16828:18;;;16821:30;-1:-1:-1;;;;;;;;;;;16867:18:29;;;16860:62;16939:18;;1683:66:20;16607:356:29;1683:66:20;902:22:21::1;916:7;902:13;:22::i;937:75::-:0;980:25;994:10;980:13;:25::i;11866:824:8:-;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;11979:15:8::1;11961;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;11961:33:8::1;;11953:79;;;::::0;-1:-1:-1;;;11953:79:8;;18862:2:29;11953:79:8::1;::::0;::::1;18844:21:29::0;18901:2;18881:18;;;18874:30;18940:34;18920:18;;;18913:62;-1:-1:-1;;;18991:18:29;;;18984:31;19032:19;;11953:79:8::1;18660:397:29::0;11953:79:8::1;-1:-1:-1::0;;;;;12078:13:8::1;12050:42;:17;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;12050:42:8::1;;12042:80;;;::::0;-1:-1:-1;;;12042:80:8;;19264:2:29;12042:80:8::1;::::0;::::1;19246:21:29::0;19303:2;19283:18;;;19276:30;19342:27;19322:18;;;19315:55;19387:18;;12042:80:8::1;19062:349:29::0;12042:80:8::1;12132:17;12152:18;12132:17:::0;12171::::1;;::::0;::::1;:6:::0;:17:::1;:::i;:::-;-1:-1:-1::0;;;;;12152:37:8::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;12152:37:8;;-1:-1:-1;;;;;12152:37:8::1;::::0;-1:-1:-1;12152:37:8;12199:65:::1;;;::::0;-1:-1:-1;;;12199:65:8;;19618:2:29;12199:65:8::1;::::0;::::1;19600:21:29::0;19657:2;19637:18;;;19630:30;19696:31;19676:18;;;19669:59;19745:18;;12199:65:8::1;19416:353:29::0;12199:65:8::1;12274:17;12294:20;12307:6;12294:12;:20::i;:::-;12274:40:::0;-1:-1:-1;12353:16:8::1;12332:17:::0;;;;:6:::1;:17;::::0;;;;;::::1;;:37;::::0;::::1;;;;;;:::i;:::-;;12324:77;;;::::0;-1:-1:-1;;;12324:77:8;;19976:2:29;12324:77:8::1;::::0;::::1;19958:21:29::0;20015:2;19995:18;;;19988:30;20054:29;20034:18;;;20027:57;20101:18;;12324:77:8::1;19774:351:29::0;12324:77:8::1;12412:17;::::0;;;:6:::1;:17;::::0;;;;;;;:50;;-1:-1:-1;;12412:50:8::1;12432:30;12412:50;::::0;;12522:47;::::1;::::0;12412:17;;12550:18:::1;::::0;12522:47:::1;;:::i;:::-;;::::0;;-1:-1:-1;;12522:47:8;;::::1;::::0;;;;;;12512:58;;12522:47:::1;12512:58:::0;;::::1;::::0;12495:76;;::::1;14967:19:29::0;15002:12;12495:76:8::1;::::0;;-1:-1:-1;;12495:76:8;;::::1;::::0;;;;;;;-1:-1:-1;12581:61:8::1;12593:9:::0;12604:17:::1;12495:76;12604:17:::0;::::1;:6:::0;:17:::1;:::i;:::-;12623:7;12632:9;12581:11;:61::i;:::-;12657:26;::::0;2740:25:29;;;12657:26:8::1;::::0;2728:2:29;2713:18;12657:26:8::1;2594:177:29::0;741:89:21;1702:10:20;1691:7;1525;1551:6;-1:-1:-1;;;;;1551:6:20;;1479:85;1691:7;-1:-1:-1;;;;;1691:21:20;;1683:66;;;;-1:-1:-1;;;1683:66:20;;16809:2:29;1683:66:20;;;16791:21:29;;;16828:18;;;16821:30;-1:-1:-1;;;;;;;;;;;16867:18:29;;;16860:62;16939:18;;1683:66:20;16607:356:29;1683:66:20;804:19:21::1;815:7;804:10;:19::i;497:60::-:0;437:10;689:4;712:16;;;:7;:16;;;;;;;;420:53;;;;-1:-1:-1;;;420:53:21;;17170:2:29;420:53:21;;;17152:21:29;17209:2;17189:18;;;17182:30;17248:22;17228:18;;;17221:50;17288:18;;420:53:21;16968:344:29;420:53:21;542:8:::1;:6;:8::i;14251:540:8:-:0;294:10:10;;14446:15:8;;-1:-1:-1;;;;;294:10:10;280;:24;272:62;;;;-1:-1:-1;;;272:62:10;;12337:2:29;272:62:10;;;12319:21:29;12376:2;12356:18;;;12349:30;12415:27;12395:18;;;12388:55;12460:18;;272:62:10;12135:349:29;272:62:10;14500:2:8::1;14481:21:::0;::::1;14473:63;;;::::0;-1:-1:-1;;;14473:63:8;;20332:2:29;14473:63:8::1;::::0;::::1;20314:21:29::0;20371:2;20351:18;;;20344:30;20410:31;20390:18;;;20383:59;20459:18;;14473:63:8::1;20130:353:29::0;14473:63:8::1;-1:-1:-1::0;;;;;14571:31:8;::::1;14546:22;14571:31:::0;;;:18:::1;:31;::::0;;;;;-1:-1:-1;;;;;14571:31:8;;::::1;::::0;14616:25;::::1;::::0;::::1;14612:84;;14664:21;14657:28;;;;;14612:84;14740:4;14705:13;:32;14719:17;14727:8:::0;;14719:17:::1;:::i;:::-;14705:32:::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;14705:32:8;:39;;-1:-1:-1;;14705:39:8::1;::::0;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;;;14251:540:8;-1:-1:-1;;;;;;14251:540:8:o;10266:225::-;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;10375:17:8::1;10395:42;10412:6;10420:16;;10395;:42::i;:::-;10375:62;;10447:37;10459:6;10467:9;10478:5;10447:11;:37::i;:::-;10365:126;10266:225:::0;;;:::o;16620:300::-;16759:77;;;16776:13;16759:77;;;21193:19:29;-1:-1:-1;;16799:4:8;21250:2:29;21246:15;21242:53;21228:12;;;21221:75;;;;21326:17;21312:12;;;21305:39;21360:12;;;21353:28;;;16712:7:8;;;;16749:126;;21397:12:29;;16759:77:8;;;;;;;;;;;;16749:88;;;;;;:124;:126::i;:::-;16731:144;;16892:21;16908:4;;16892:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16892:7:8;;:21;-1:-1:-1;;16892:15:8;:21;-1:-1:-1;16892:21:8:i;5430:588::-;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;5516:17:8::1;5535:19:::0;5558:25:::1;5576:6;5558:17;:25::i;:::-;5593:17;::::0;;;5613:26:::1;5593:17;::::0;;;;;;;:46;;-1:-1:-1;;5593:46:8::1;::::0;;::::1;::::0;;;5699:48;;5593:17;;-1:-1:-1;5515:68:8;;-1:-1:-1;5593:17:8;5699:48:::1;::::0;5593:17;;:46;;5699:48:::1;;:::i;:::-;;::::0;;-1:-1:-1;;5699:48:8;;::::1;::::0;;;;;;5689:59;;5699:48:::1;5689:59:::0;;::::1;::::0;5672:77;;::::1;14967:19:29::0;15002:12;5672:77:8::1;::::0;;-1:-1:-1;;5672:77:8;;::::1;::::0;;;;;;;-1:-1:-1;5759:63:8::1;5771:11:::0;5784:17:::1;5672:77;5784:17:::0;::::1;:6:::0;:17:::1;:::i;5759:63::-;5832:87;5873:10;5885:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;5902:16;::::0;::::1;::::0;::::1;::::0;5839:15:::1;::::0;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;5832:40:8::1;::::0;:87;;:40:::1;:87::i;19599:161::-:0;1702:10:20;1691:7;1525;1551:6;-1:-1:-1;;;;;1551:6:20;;1479:85;1691:7;-1:-1:-1;;;;;1691:21:20;;1683:66;;;;-1:-1:-1;;;1683:66:20;;16809:2:29;1683:66:20;;;16791:21:29;;;16828:18;;;16821:30;-1:-1:-1;;;;;;;;;;;16867:18:29;;;16860:62;16939:18;;1683:66:20;16607:356:29;1683:66:20;19676:12:8::1;:28:::0;;-1:-1:-1;;;;;;19676:28:8::1;-1:-1:-1::0;;;;;19676:28:8;::::1;::::0;;::::1;::::0;;;19719:34:::1;::::0;5605:74:29;;;19719:34:8::1;::::0;5593:2:29;5578:18;19719:34:8::1;5459:226:29::0;19035:558:8;324:10:19;506:4;529:19;;;:9;:19;;;;;;;;305:57;;;;-1:-1:-1;;;305:57:19;;21622:2:29;305:57:19;;;21604:21:29;21661:2;21641:18;;;21634:30;21700:24;21680:18;;;21673:52;21742:18;;305:57:19;21420:346:29;305:57:19;19153:36:8;;::::1;19145:69;;;::::0;-1:-1:-1;;;19145:69:8;;21973:2:29;19145:69:8::1;::::0;::::1;21955:21:29::0;22012:2;21992:18;;;21985:30;22051:22;22031:18;;;22024:50;22091:18;;19145:69:8::1;21771:344:29::0;19145:69:8::1;19229:9;19224:312;19244:20:::0;;::::1;19224:312;;;19308:3;19293:9;;19303:1;19293:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;:18;;;19285:60;;;::::0;-1:-1:-1;;;19285:60:8;;22811:2:29;19285:60:8::1;::::0;::::1;22793:21:29::0;22850:2;22830:18;;;22823:30;22889:31;22869:18;;;22862:59;22938:18;;19285:60:8::1;22609:353:29::0;19285:60:8::1;19363:9;;19373:1;19363:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;19363:17:8::1;19379:1;19363:17:::0;19359:167:::1;;19416:9;;19426:1;19416:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;19400:13;;:28;;;;;;;;;;;;;;;;;;19359:167;;;19499:9;;19509:1;19499:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;19467:15;:29;19483:9;;19493:1;19483:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;19467:29:8::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;19467:29:8;:44;;-1:-1:-1;;19467:44:8::1;;::::0;;;::::1;::::0;;;::::1;::::0;;19359:167:::1;19266:3:::0;::::1;::::0;::::1;:::i;:::-;;;;19224:312;;;;19550:36;19565:9;;19576;;19550:36;;;;;;;;;:::i;6868:703::-:0;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;6982:17:8::1;7001:19:::0;7024:25:::1;7042:6;7024:17;:25::i;:::-;6981:68:::0;;-1:-1:-1;6981:68:8;-1:-1:-1;7059:63:8::1;7080:24;::::0;;;::::1;::::0;::::1;;:::i;:::-;7106:9;7117:4;;7059:20;:63::i;:::-;7132:17;::::0;;;7152:26:::1;7132:17;::::0;;;;;;;:46;;-1:-1:-1;;7132:46:8::1;::::0;;::::1;::::0;;;7238:48;;::::1;::::0;7132:17;;:46;;7238:48:::1;;:::i;:::-;;::::0;;-1:-1:-1;;7238:48:8;;::::1;::::0;;;;;;7228:59;;7238:48:::1;7228:59:::0;;::::1;::::0;7211:77;;::::1;14967:19:29::0;15002:12;7211:77:8::1;::::0;;-1:-1:-1;;7211:77:8;;::::1;::::0;;;;;;;-1:-1:-1;7298:63:8::1;7310:11:::0;7323:17:::1;7211:77;7323:17:::0;::::1;:6:::0;:17:::1;:::i;7298:63::-;7371:101;7412:24;::::0;;;::::1;::::0;::::1;;:::i;:::-;7438:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;7455:16;::::0;::::1;::::0;::::1;::::0;7378:15:::1;::::0;::::1;::::0;::::1;;:::i;7371:101::-;7487:77;7502:9:::0;7513:15:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;7530;::::0;;;::::1;::::0;::::1;;:::i;:::-;7487:77;::::0;;15256:25:29;;;-1:-1:-1;;;;;15378:15:29;;;15373:2;15358:18;;15351:43;15430:15;;15410:18;;;15403:43;7547:16:8::1;::::0;::::1;;15477:2:29::0;15462:18;;15455:34;15243:3;15228:19;7487:77:8::1;;;;;;;6971:600;;;6868:703:::0;;;:::o;10497:305::-;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;10639:10:8::1;::::0;-1:-1:-1;;;;;10639:10:8::1;10620:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;10620:29:8::1;;10612:65;;;::::0;-1:-1:-1;;;10612:65:8;;13389:2:29;10612:65:8::1;::::0;::::1;13371:21:29::0;13428:2;13408:18;;;13401:30;13467:25;13447:18;;;13440:53;13510:18;;10612:65:8::1;13187:347:29::0;10612:65:8::1;10687:17;10707:42;10724:6;10732:16;;10707;:42::i;:::-;10687:62;;10759:36;10771:6;10779:9;10790:4;10759:11;:36::i;8825:643::-:0;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;9024:17:8::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;9003:38:8::1;:17;;::::0;::::1;:6:::0;:17:::1;:::i;:::-;-1:-1:-1::0;;;;;9003:38:8::1;;8995:75;;;::::0;-1:-1:-1;;;8995:75:8;;15702:2:29;8995:75:8::1;::::0;::::1;15684:21:29::0;15741:2;15721:18;;;15714:30;15780:26;15760:18;;;15753:54;15824:18;;8995:75:8::1;15500:348:29::0;8995:75:8::1;9081:17;9104:25;9122:6;9104:17;:25::i;:::-;-1:-1:-1::0;9080:49:8;-1:-1:-1;9139:63:8::1;9160:24;::::0;;;::::1;::::0;::::1;;:::i;:::-;9186:9;9197:4;;9139:20;:63::i;:::-;9212:101;9253:24;::::0;;;::::1;::::0;::::1;;:::i;:::-;9279:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;9296:16;::::0;::::1;::::0;::::1;::::0;9219:15:::1;::::0;::::1;::::0;::::1;;:::i;9212:101::-;9323:46;9335:6;9343:9;9354:14;9323:11;:46::i;:::-;9384:77;9399:9:::0;9410:15:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;9427;::::0;;;::::1;::::0;::::1;;:::i;:::-;9384:77;::::0;;15256:25:29;;;-1:-1:-1;;;;;15378:15:29;;;15373:2;15358:18;;15351:43;15430:15;;15410:18;;;15403:43;9444:16:8::1;::::0;::::1;;15477:2:29::0;15462:18;;15455:34;15243:3;15228:19;9384:77:8::1;15025:470:29::0;7577:498:8;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;7718:17:8::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;7697:38:8::1;:17;;::::0;::::1;:6:::0;:17:::1;:::i;:::-;-1:-1:-1::0;;;;;7697:38:8::1;;7689:75;;;::::0;-1:-1:-1;;;7689:75:8;;15702:2:29;7689:75:8::1;::::0;::::1;15684:21:29::0;15741:2;15721:18;;;15714:30;15780:26;15760:18;;;15753:54;15824:18;;7689:75:8::1;15500:348:29::0;7689:75:8::1;7775:17;7798:25;7816:6;7798:17;:25::i;:::-;-1:-1:-1::0;7774:49:8;-1:-1:-1;7833:87:8::1;7874:10;7886:15;::::0;;;::::1;::::0;::::1;;:::i;:::-;7903:16;::::0;::::1;::::0;::::1;::::0;7840:15:::1;::::0;::::1;::::0;::::1;;:::i;18590:439::-:0;1702:10:20;1691:7;1525;1551:6;-1:-1:-1;;;;;1551:6:20;;1479:85;1691:7;-1:-1:-1;;;;;1691:21:20;;1683:66;;;;-1:-1:-1;;;1683:66:20;;16809:2:29;1683:66:20;;;16791:21:29;;;16828:18;;;16821:30;-1:-1:-1;;;;;;;;;;;16867:18:29;;;16860:62;16939:18;;1683:66:20;16607:356:29;1683:66:20;18747:46:8;;::::1;18739:79;;;::::0;-1:-1:-1;;;18739:79:8;;21973:2:29;18739:79:8::1;::::0;::::1;21955:21:29::0;22012:2;21992:18;;;21985:30;22051:22;22031:18;;;22024:50;22091:18;;18739:79:8::1;21771:344:29::0;18739:79:8::1;18833:9;18828:129;18848:20:::0;;::::1;18828:129;;;18924:19;;18944:1;18924:22;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;18889:18;:32;18908:9;;18918:1;18908:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;18889:32:8::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;18889:32:8;:57;;-1:-1:-1;;;;;;18889:57:8::1;-1:-1:-1::0;;;;;18889:57:8;;;::::1;::::0;;;::::1;::::0;;18870:3;::::1;::::0;::::1;:::i;:::-;;;;18828:129;;;;18971:51;18991:9;;19002:19;;18971:51;;;;;;;;;:::i;15519:685::-:0;15585:7;15688:17;;;;:6;:17;:::i;:::-;15727:15;;;;;;;;:::i;:::-;15764:16;;;;15802:23;;;;15847:17;;;;;;;;:::i;:::-;15886:15;;;;;;;;:::i;:::-;15923:16;;;;15961:15;;;;;;;;:::i;:::-;15998:12;;;;;;;;:::i;:::-;16032:13;;;;;;;;:::i;:::-;16067:15;;;;;;;;:::i;:::-;16104;;;;;;;;:::i;:::-;16141:6;:24;;;;;;;;;;:::i;:::-;15650:533;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;15623:574;;;;;;15604:593;;15519:685;;;:::o;769:79:19:-;814:27;830:10;814:15;:27::i;3034:365:8:-;1168:7:22;;3177::8;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;3200:17:8::1;3220:51;3232:6;3240:19;3261:9;3220:11;:51::i;:::-;3200:71:::0;-1:-1:-1;3281:85:8::1;3322:10;3342:4;3349:16;::::0;::::1;::::0;::::1;::::0;3288:15:::1;::::0;::::1;::::0;::::1;;:::i;662:101:19:-:0;1702:10:20;1691:7;1525;1551:6;-1:-1:-1;;;;;1551:6:20;;1479:85;1691:7;-1:-1:-1;;;;;1691:21:20;;1683:66;;;;-1:-1:-1;;;1683:66:20;;16809:2:29;1683:66:20;;;16791:21:29;;;16828:18;;;16821:30;-1:-1:-1;;;;;;;;;;;16867:18:29;;;16860:62;16939:18;;1683:66:20;16607:356:29;1683:66:20;731:25:19::1;747:8;731:15;:25::i;1916:189:20:-:0;1702:10;1691:7;1525;1551:6;-1:-1:-1;;;;;1551:6:20;;1479:85;1691:7;-1:-1:-1;;;;;1691:21:20;;1683:66;;;;-1:-1:-1;;;1683:66:20;;16809:2:29;1683:66:20;;;16791:21:29;;;16828:18;;;16821:30;-1:-1:-1;;;;;;;;;;;16867:18:29;;;16860:62;16939:18;;1683:66:20;16607:356:29;1683:66:20;-1:-1:-1;;;;;2004:22:20;::::1;1996:73;;;::::0;-1:-1:-1;;;1996:73:20;;27066:2:29;1996:73:20::1;::::0;::::1;27048:21:29::0;27105:2;27085:18;;;27078:30;27144:34;27124:18;;;27117:62;27215:8;27195:18;;;27188:36;27241:19;;1996:73:20::1;26864:402:29::0;1996:73:20::1;2079:19;2089:8;2079:9;:19::i;12696:405:8:-:0;1168:7:22;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;12809:17:8::1;12828:16:::0;12848:40:::1;12863:6;12871:16;;12848:14;:40::i;:::-;12898:17;::::0;;;:6:::1;:17;::::0;;;;:43;;12808:80;;-1:-1:-1;12808:80:8;;-1:-1:-1;12918:23:8::1;::::0;-1:-1:-1;;12898:43:8::1;::::0;12918:23;12898:43:::1;;::::0;;-1:-1:-1;12951:64:8::1;12988:8:::0;12998:16:::1;::::0;::::1;::::0;::::1;::::0;12958:15:::1;::::0;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;12951:36:8::1;::::0;:64;:36:::1;:64::i;16210:259::-:0;-1:-1:-1;;;;;16320:25:8;;16284:7;16320:25;;;:15;:25;;;;;;;;16359:12;;;16355:66;;-1:-1:-1;16397:13:8;;-1:-1:-1;;;16397:13:8;;;;16355:66;16459:3;16438:17;;;;:7;:17;:::i;:::-;16437:25;;;;:::i;:::-;16430:32;16210:259;-1:-1:-1;;;;16210:259:8:o;3990:1434::-;4126:7;4188:15;4166:19;-1:-1:-1;;;;;4166:37:8;;:78;;;;-1:-1:-1;;;;;;4207:37:8;;:15;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4207:37:8;;4166:78;4145:152;;;;-1:-1:-1;;;4145:152:8;;27868:2:29;4145:152:8;;;27850:21:29;27907:2;27887:18;;;27880:30;27946:29;27926:18;;;27919:57;27993:18;;4145:152:8;27666:351:29;4145:152:8;4355:1;4328:15;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4328:29:8;;;:71;;;;-1:-1:-1;4397:1:8;4361:24;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4361:38:8;;;4328:71;4307:160;;;;-1:-1:-1;;;4307:160:8;;28224:2:29;4307:160:8;;;28206:21:29;28263:2;28243:18;;;28236:30;28302:34;28282:18;;;28275:62;28373:12;28353:18;;;28346:40;28403:19;;4307:160:8;28022:406:29;4307:160:8;-1:-1:-1;;;;;4513:13:8;4485:42;:17;;;;:6;:17;:::i;:::-;-1:-1:-1;;;;;4485:42:8;;4477:80;;;;-1:-1:-1;;;4477:80:8;;28635:2:29;4477:80:8;;;28617:21:29;28674:2;28654:18;;;28647:30;28713:27;28693:18;;;28686:55;28758:18;;4477:80:8;28433:349:29;4477:80:8;4592:10;4575:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4575:27:8;;4567:60;;;;-1:-1:-1;;;4567:60:8;;28989:2:29;4567:60:8;;;28971:21:29;29028:2;29008:18;;;29001:30;29067:22;29047:18;;;29040:50;29107:18;;4567:60:8;28787:344:29;4567:60:8;4637:17;4657:20;4670:6;4657:12;:20::i;:::-;4637:40;-1:-1:-1;4716:16:8;4695:17;;;;:6;:17;;;;;;;;:37;;;;;;;;:::i;:::-;;4687:72;;;;-1:-1:-1;;;4687:72:8;;29338:2:29;4687:72:8;;;29320:21:29;29377:2;29357:18;;;29350:30;29416:24;29396:18;;;29389:52;29458:18;;4687:72:8;29136:346:29;4687:72:8;4769:14;4786:46;4796:17;;;;;;;;:::i;:::-;4815:6;:16;;;4786:9;:46::i;:::-;4769:63;-1:-1:-1;4860:42:8;4879:23;;;;4860:16;;;;:42;:::i;:::-;4850:6;:52;;4842:95;;;;-1:-1:-1;;;4842:95:8;;29689:2:29;4842:95:8;;;29671:21:29;29728:2;29708:18;;;29701:30;29767:32;29747:18;;;29740:60;29817:18;;4842:95:8;29487:354:29;4842:95:8;4948:17;;;;:6;:17;;;;;:44;;-1:-1:-1;;4948:44:8;4968:24;4948:44;;;5027:17;;;;;;;;:::i;:::-;-1:-1:-1;;;;;5006:38:8;:17;;;;:6;:17;:::i;:::-;-1:-1:-1;;;;;5006:38:8;;5002:344;;5060:19;5082:18;5060:19;5101:17;;;;;;;;:::i;:::-;-1:-1:-1;;;;;5082:37:8;;;;;;;;;;;;-1:-1:-1;5082:37:8;;-1:-1:-1;;;;;5082:37:8;;-1:-1:-1;5082:37:8;5133:63;;;;-1:-1:-1;;;5133:63:8;;30048:2:29;5133:63:8;;;30030:21:29;30087:2;30067:18;;;30060:30;30126:27;30106:18;;;30099:55;30171:18;;5133:63:8;29846:349:29;5133:63:8;5210:20;5250:9;5233:27;;;;;;14967:19:29;;15011:2;15002:12;;14838:182;5233:27:8;;;;-1:-1:-1;;5233:27:8;;;;;;;;;;-1:-1:-1;5274:61:8;5286:11;5299:17;;;;;;;;:::i;:::-;5318:7;5327;5274:11;:61::i;:::-;5046:300;;5002:344;5360:31;5373:9;5384:6;5360:31;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;5408:9:8;3990:1434;-1:-1:-1;;;;3990:1434:8:o;9474:786::-;9546:7;;9600:15;9582;;;;;;;;:::i;:::-;-1:-1:-1;;;;;9582:33:8;;9574:75;;;;-1:-1:-1;;;9574:75:8;;32240:2:29;9574:75:8;;;32222:21:29;32279:2;32259:18;;;32252:30;32318:31;32298:18;;;32291:59;32367:18;;9574:75:8;32038:353:29;9574:75:8;-1:-1:-1;;;;;9695:13:8;9667:42;:17;;;;;;;;:::i;:::-;-1:-1:-1;;;;;9667:42:8;;9659:80;;;;-1:-1:-1;;;9659:80:8;;19264:2:29;9659:80:8;;;19246:21:29;19303:2;19283:18;;;19276:30;19342:27;19322:18;;;19315:55;19387:18;;9659:80:8;19062:349:29;9659:80:8;9749:17;9769:20;9782:6;9769:12;:20::i;:::-;9749:40;-1:-1:-1;9799:19:8;9821:18;9799:19;9840:17;;;;:6;:17;:::i;:::-;-1:-1:-1;;;;;9821:37:8;;;;;;;;;;;;-1:-1:-1;9821:37:8;;-1:-1:-1;;;;;9821:37:8;;-1:-1:-1;9893:17:8;;;;;;;;:::i;:::-;-1:-1:-1;;;;;9872:38:8;:17;;;;:6;:17;:::i;:::-;-1:-1:-1;;;;;9872:38:8;;9868:345;;9955:16;9934:17;;;:6;:17;;;;;;;;:37;;;;;;;;:::i;:::-;;9926:77;;;;-1:-1:-1;;;9926:77:8;;19976:2:29;9926:77:8;;;19958:21:29;20015:2;19995:18;;;19988:30;20054:29;20034:18;;;20027:57;20101:18;;9926:77:8;19774:351:29;9926:77:8;-1:-1:-1;;;;;10025:25:8;;10017:67;;;;-1:-1:-1;;;10017:67:8;;32598:2:29;10017:67:8;;;32580:21:29;32637:2;32617:18;;;32610:30;32676:31;32656:18;;;32649:59;32725:18;;10017:67:8;32396:353:29;10017:67:8;9868:345;;;10144:24;10123:17;;;;:6;:17;;;;;;;;:45;;;;;;;;:::i;:::-;;10115:87;;;;-1:-1:-1;;;10115:87:8;;32956:2:29;10115:87:8;;;32938:21:29;32995:2;32975:18;;;32968:30;33034:31;33014:18;;;33007:59;33083:18;;10115:87:8;32754:353:29;10115:87:8;10230:9;;10241:11;;-1:-1:-1;9474:786:8;-1:-1:-1;;9474:786:8:o;1137:241:11:-;1354:10;;1291:80;;1320:9;;1331:11;;1344:8;;-1:-1:-1;;;;;1354:10:11;1366:4;1291:28;:80::i;17880:287:8:-;17972:10;;-1:-1:-1;;;;;17972:10:8;17964:61;;;;-1:-1:-1;;;17964:61:8;;13036:2:29;17964:61:8;;;13018:21:29;13075:2;13055:18;;;13048:30;13114:26;13094:18;;;13087:54;13158:18;;17964:61:8;12834:348:29;17964:61:8;18036:9;18051;-1:-1:-1;;;;;18051:14:8;18073:7;18087:5;18051:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18035:62;;;18115:4;18107:53;;;;-1:-1:-1;;;18107:53:8;;33524:2:29;18107:53:8;;;33506:21:29;33563:2;33543:18;;;33536:30;33602:34;33582:18;;;33575:62;-1:-1:-1;;;33653:18:29;;;33646:34;33697:19;;18107:53:8;33322:400:29;18107:53:8;17954:213;17880:287;;:::o;11173:687::-;11339:42;11358:23;;;;11339:16;;;;:42;:::i;:::-;11306:11;:28;11318:15;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11306:28:8;-1:-1:-1;;;;;11306:28:8;;;;;;;;;;;;;:76;;;;;;;:::i;:::-;;;;-1:-1:-1;;11392:356:8;;;;11426:18;;;;:6;:18;;;;;:50;;-1:-1:-1;;11426:50:8;11447:29;11426:50;;;11490:71;11511:24;;;;;;;;:::i;:::-;11537:6;:23;;;11490:20;:71::i;:::-;11392:356;;;11592:18;;;;:6;:18;;;;;:44;;-1:-1:-1;;11592:44:8;11613:23;11592:44;;;11650:87;11687:24;;;;;;;;:::i;:::-;11713:23;;;;11657:15;;;;;;;;:::i;11650:87::-;11762:91;11774:10;11786:24;;;;;;;;:::i;:::-;11812:15;;;;;;;;:::i;:::-;11762:91;;;15256:25:29;;;-1:-1:-1;;;;;15378:15:29;;;15373:2;15358:18;;15351:43;15430:15;;15410:18;;;15403:43;11829:23:8;;;;;15462:18:29;;;15455:34;15243:3;15228:19;11762:91:8;15025:470:29;854:200:19;-1:-1:-1;;;;;529:19:19;;506:4;529:19;;;:9;:19;;;;;;;;920:21;912:61;;;;-1:-1:-1;;;912:61:19;;34059:2:29;912:61:19;;;34041:21:29;34098:2;34078:18;;;34071:30;34137:29;34117:18;;;34110:57;34184:18;;912:61:19;33857:351:29;912:61:19;-1:-1:-1;;;;;983:19:19;;;;;;:9;:19;;;;;;;;;:26;;-1:-1:-1;;983:26:19;1005:4;983:26;;;1024:23;;5605:74:29;;;1024:23:19;;5578:18:29;1024:23:19;5459:226:29;2110:117:22;1168:7;;-1:-1:-1;;;1168:7:22;;;;1669:41;;;;-1:-1:-1;;;1669:41:22;;34415:2:29;1669:41:22;;;34397:21:29;34454:2;34434:18;;;34427:30;34493:22;34473:18;;;34466:50;34533:18;;1669:41:22;34213:344:29;1669:41:22;2168:7:::1;:15:::0;;-1:-1:-1;;;;2168:15:22::1;::::0;;2198:22:::1;719:10:26::0;2207:12:22::1;2198:22;::::0;-1:-1:-1;;;;;5623:55:29;;;5605:74;;5593:2;5578:18;2198:22:22::1;;;;;;;2110:117::o:0;13596:649:8:-;13693:7;13702;13721:17;13741:20;13754:6;13741:12;:20::i;:::-;13721:40;-1:-1:-1;13800:24:8;13779:17;;;;:6;:17;;;;;;;;:45;;;;;;;;:::i;:::-;;13771:83;;;;-1:-1:-1;;;13771:83:8;;34764:2:29;13771:83:8;;;34746:21:29;34803:2;34783:18;;;34776:30;34842:27;34822:18;;;34815:55;34887:18;;13771:83:8;34562:349:29;13771:83:8;13889:17;;;;;;;;:::i;:::-;-1:-1:-1;;;;;13868:38:8;:17;;;;:6;:17;:::i;:::-;-1:-1:-1;;;;;13868:38:8;;13864:243;;13922:64;13938:16;;13956:9;13967:18;13922:15;:64::i;:::-;13864:243;;;14043:15;14025;;;;;;;;:::i;:::-;-1:-1:-1;;;;;14025:33:8;;14017:79;;;;-1:-1:-1;;;14017:79:8;;18862:2:29;14017:79:8;;;18844:21:29;18901:2;18881:18;;;18874:30;18940:34;18920:18;;;18913:62;-1:-1:-1;;;18991:18:29;;;18984:31;19032:19;;14017:79:8;18660:397:29;14017:79:8;14116:16;;14136:15;;;;;;;;:::i;:::-;-1:-1:-1;;;;;14136:29:8;;14135:65;;14185:15;;;;;;;;:::i;:::-;14135:65;;;14169:13;;;;;;;;:::i;:::-;14218:9;;;;-1:-1:-1;13596:649:8;;-1:-1:-1;;;;;13596:649:8:o;18173:332::-;18265:10;;-1:-1:-1;;;;;18265:10:8;18257:61;;;;-1:-1:-1;;;18257:61:8;;13036:2:29;18257:61:8;;;13018:21:29;13075:2;13055:18;;;13048:30;13114:26;13094:18;;;13087:54;13158:18;;18257:61:8;12834:348:29;18257:61:8;18334:10;;;18328:35;;-1:-1:-1;;;18328:35:8;;;;;2740:25:29;;;-1:-1:-1;;;;;18334:10:8;;18328:26;;2713:18:29;;18328:35:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18374:9;18389;-1:-1:-1;;;;;18389:14:8;18411:7;18425:5;18389:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18373:62;;;18453:4;18445:53;;;;-1:-1:-1;;;18445:53:8;;35118:2:29;18445:53:8;;;35100:21:29;35157:2;35137:18;;;35130:30;35196:34;35176:18;;;35169:62;-1:-1:-1;;;35247:18:29;;;35240:34;35291:19;;18445:53:8;34916:400:29;701:205:24;840:58;;-1:-1:-1;;;;;35513:55:29;;840:58:24;;;35495:74:29;35585:18;;;35578:34;;;813:86:24;;833:5;;-1:-1:-1;;;863:23:24;35468:18:29;;840:58:24;;;;-1:-1:-1;;840:58:24;;;;;;;;;;;;;;;;;;;;;;;;;;;813:19;:86::i;1210:187:21:-;-1:-1:-1;;;;;712:16:21;;689:4;712:16;;;:7;:16;;;;;;;;1268:51;;;;-1:-1:-1;;;1268:51:21;;35825:2:29;1268:51:21;;;35807:21:29;35864:2;35844:18;;;35837:30;35903:23;35883:18;;;35876:51;35944:18;;1268:51:21;35623:345:29;1268:51:21;-1:-1:-1;;;;;1329:16:21;;1348:5;1329:16;;;:7;:16;;;;;;;;;:24;;-1:-1:-1;;1329:24:21;;;1368:22;;5605:74:29;;;1368:22:21;;5578:18:29;1368:22:21;5459:226:29;1018:186:21;-1:-1:-1;;;;;712:16:21;;689:4;712:16;;;:7;:16;;;;;;;;1081:18;1073:56;;;;-1:-1:-1;;;1073:56:21;;36175:2:29;1073:56:21;;;36157:21:29;36214:2;36194:18;;;36187:30;36253:27;36233:18;;;36226:55;36298:18;;1073:56:21;35973:349:29;1073:56:21;-1:-1:-1;;;;;1139:16:21;;;;;;:7;:16;;;;;;;;;:23;;-1:-1:-1;;1139:23:21;1158:4;1139:23;;;1177:20;;5605:74:29;;;1177:20:21;;5578:18:29;1177:20:21;5459:226:29;1863:115:22;1168:7;;-1:-1:-1;;;1168:7:22;;;;1411:9;1403:38;;;;-1:-1:-1;;;1403:38:22;;12691:2:29;1403:38:22;;;12673:21:29;12730:2;12710:18;;;12703:30;-1:-1:-1;;;12749:18:29;;;12742:46;12805:18;;1403:38:22;12489:340:29;1403:38:22;1932:4:::1;1922:14:::0;;-1:-1:-1;;;;1922:14:22::1;-1:-1:-1::0;;;1922:14:22::1;::::0;;1951:20:::1;1958:12;719:10:26::0;;640:96;10808:359:8;10907:7;10926:17;10946:20;10959:6;10946:12;:20::i;:::-;10926:40;-1:-1:-1;11005:24:8;10984:17;;;;:6;:17;;;;;;;;:45;;;;;;;;:::i;:::-;;10976:83;;;;-1:-1:-1;;;10976:83:8;;34764:2:29;10976:83:8;;;34746:21:29;34803:2;34783:18;;;34776:30;34842:27;34822:18;;;34815:55;34887:18;;10976:83:8;34562:349:29;10976:83:8;11069:65;11085:16;;11103:9;11114:19;11069:15;:65::i;8012:265:28:-;8211:58;;36569:66:29;8211:58:28;;;36557:79:29;36652:12;;;36645:28;;;8081:7:28;;36689:12:29;;8211:58:28;36327:380:29;4308:227:28;4386:7;4406:17;4425:18;4447:27;4458:4;4464:9;4447:10;:27::i;:::-;4405:69;;;;4484:18;4496:5;4484:11;:18::i;:::-;-1:-1:-1;4519:9:28;4308:227;-1:-1:-1;;;4308:227:28:o;912:241:24:-;1077:68;;-1:-1:-1;;;;;18538:15:29;;;1077:68:24;;;18520:34:29;18590:15;;18570:18;;;18563:43;18622:18;;;18615:34;;;1050:96:24;;1070:5;;-1:-1:-1;;;1100:27:24;18432:18:29;;1077:68:24;18257:398:29;1060:201:19;-1:-1:-1;;;;;529:19:19;;506:4;529:19;;;:9;:19;;;;;;;;1121:56;;;;-1:-1:-1;;;1121:56:19;;36914:2:29;1121:56:19;;;36896:21:29;36953:2;36933:18;;;36926:30;36992:25;36972:18;;;36965:53;37035:18;;1121:56:19;36712:347:29;1121:56:19;-1:-1:-1;;;;;1187:19:19;;1209:5;1187:19;;;:9;:19;;;;;;;;;:27;;-1:-1:-1;;1187:27:19;;;1229:25;;5605:74:29;;;1229:25:19;;5578:18:29;1229:25:19;5459:226:29;2111:169:20;2166:16;2185:6;;-1:-1:-1;;;;;2201:17:20;;;-1:-1:-1;;;;;;2201:17:20;;;;;;2233:40;;2185:6;;;;;;;2233:40;;2166:16;2233:40;2156:124;2111:169;:::o;1113:273:14:-;1296:83;;-1:-1:-1;;;1296:83:14;;-1:-1:-1;;;;;1296:36:14;;;;;1340:4;;1296:83;;1346:9;;1357:11;;1370:8;;1296:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1113:273;;;;;:::o;17369:505:8:-;17517:19;17566:10;17578:8;17549:38;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;17549:38:8;;;;;;;;;17539:49;;17549:38;17539:49;;;;17603:26;;;;:13;:26;;;;;;17539:49;;-1:-1:-1;17603:26:8;;17598:162;;17664:10;;:33;;17646:12;;-1:-1:-1;;;;;17664:10:8;;:33;;17680:16;;;;17664:33;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17645:52;;;17719:7;17711:38;;;;-1:-1:-1;;;17711:38:8;;38509:2:29;17711:38:8;;;38491:21:29;38548:2;38528:18;;;38521:30;38587:20;38567:18;;;38560:48;38625:18;;17711:38:8;38307:342:29;17711:38:8;17631:129;17598:162;17777:26;;;;:13;:26;;;;;;;;17769:55;;;;-1:-1:-1;;;17769:55:8;;38856:2:29;17769:55:8;;;38838:21:29;38895:2;38875:18;;;38868:30;38934:18;38914;;;38907:46;38970:18;;17769:55:8;38654:340:29;17769:55:8;17841:26;;;;:13;:26;;;;;17834:33;;-1:-1:-1;;17834:33:8;;;-1:-1:-1;;;;17369:505:8:o;3207:706:24:-;3626:23;3652:69;3680:4;3652:69;;;;;;;;;;;;;;;;;3660:5;-1:-1:-1;;;;;3652:27:24;;;:69;;;;;:::i;:::-;3735:17;;3626:95;;-1:-1:-1;3735:21:24;3731:176;;3830:10;3819:30;;;;;;;;;;;;:::i;:::-;3811:85;;;;-1:-1:-1;;;3811:85:24;;39451:2:29;3811:85:24;;;39433:21:29;39490:2;39470:18;;;39463:30;39529:34;39509:18;;;39502:62;39600:12;39580:18;;;39573:40;39630:19;;3811:85:24;39249:406:29;2243:1279:28;2324:7;2333:12;2554:9;:16;2574:2;2554:22;2550:966;;2843:4;2828:20;;2822:27;2892:4;2877:20;;2871:27;2949:4;2934:20;;2928:27;2592:9;2920:36;2990:25;3001:4;2920:36;2822:27;2871;2990:10;:25::i;:::-;2983:32;;;;;;;;;2550:966;3036:9;:16;3056:2;3036:22;3032:484;;3305:4;3290:20;;3284:27;3355:4;3340:20;;3334:27;3395:23;3406:4;3284:27;3334;3395:10;:23::i;:::-;3388:30;;;;;;;;3032:484;-1:-1:-1;3465:1:28;;-1:-1:-1;3469:35:28;3032:484;2243:1279;;;;;:::o;548:631::-;625:20;616:5;:29;;;;;;;;:::i;:::-;;612:561;;548:631;:::o;612:561::-;721:29;712:5;:38;;;;;;;;:::i;:::-;;708:465;;766:34;;-1:-1:-1;;;766:34:28;;39862:2:29;766:34:28;;;39844:21:29;39901:2;39881:18;;;39874:30;39940:26;39920:18;;;39913:54;39984:18;;766:34:28;39660:348:29;708:465:28;830:35;821:5;:44;;;;;;;;:::i;:::-;;817:356;;881:41;;-1:-1:-1;;;881:41:28;;40215:2:29;881:41:28;;;40197:21:29;40254:2;40234:18;;;40227:30;40293:33;40273:18;;;40266:61;40344:18;;881:41:28;40013:355:29;817:356:28;952:30;943:5;:39;;;;;;;;:::i;:::-;;939:234;;998:44;;-1:-1:-1;;;998:44:28;;40575:2:29;998:44:28;;;40557:21:29;40614:2;40594:18;;;40587:30;40653:34;40633:18;;;40626:62;-1:-1:-1;;;40704:18:29;;;40697:32;40746:19;;998:44:28;40373:398:29;939:234:28;1072:30;1063:5;:39;;;;;;;;:::i;:::-;;1059:114;;1118:44;;-1:-1:-1;;;1118:44:28;;40978:2:29;1118:44:28;;;40960:21:29;41017:2;40997:18;;;40990:30;41056:34;41036:18;;;41029:62;-1:-1:-1;;;41107:18:29;;;41100:32;41149:19;;1118:44:28;40776:398:29;3861:223:25;3994:12;4025:52;4047:6;4055:4;4061:1;4064:12;4025:21;:52::i;5716:1603:28:-;5842:7;;6766:66;6753:79;;6749:161;;;-1:-1:-1;6864:1:28;;-1:-1:-1;6868:30:28;6848:51;;6749:161;6923:1;:7;;6928:2;6923:7;;:18;;;;;6934:1;:7;;6939:2;6934:7;;6923:18;6919:100;;;-1:-1:-1;6973:1:28;;-1:-1:-1;6977:30:28;6957:51;;6919:100;7130:24;;;7113:14;7130:24;;;;;;;;;41406:25:29;;;41479:4;41467:17;;41447:18;;;41440:45;;;;41501:18;;;41494:34;;;41544:18;;;41537:34;;;7130:24:28;;41378:19:29;;7130:24:28;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7130:24:28;;-1:-1:-1;;7130:24:28;;;-1:-1:-1;;;;;;;7168:20:28;;7164:101;;7220:1;7224:29;7204:50;;;;;;;7164:101;7283:6;-1:-1:-1;7291:20:28;;-1:-1:-1;5716:1603:28;;;;;;;;:::o;4789:336::-;4899:7;;4957:66;4944:80;;4899:7;5050:25;5066:3;5051:18;;;5073:2;5050:25;:::i;:::-;5034:42;;5093:25;5104:4;5110:1;5113;5116;5093:10;:25::i;:::-;5086:32;;;;;;4789:336;;;;;;:::o;4948:499:25:-;5113:12;5170:5;5145:21;:30;;5137:81;;;;-1:-1:-1;;;5137:81:25;;41784:2:29;5137:81:25;;;41766:21:29;41823:2;41803:18;;;41796:30;41862:34;41842:18;;;41835:62;41933:8;41913:18;;;41906:36;41959:19;;5137:81:25;41582:402:29;5137:81:25;-1:-1:-1;;;;;1465:19:25;;;5228:60;;;;-1:-1:-1;;;5228:60:25;;42191:2:29;5228:60:25;;;42173:21:29;42230:2;42210:18;;;42203:30;42269:31;42249:18;;;42242:59;42318:18;;5228:60:25;41989:353:29;5228:60:25;5300:12;5314:23;5341:6;-1:-1:-1;;;;;5341:11:25;5360:5;5367:4;5341:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5299:73;;;;5389:51;5406:7;5415:10;5427:12;7707;7735:7;7731:516;;;-1:-1:-1;7765:10:25;7758:17;;7731:516;7876:17;;:21;7872:365;;8070:10;8064:17;8130:15;8117:10;8113:2;8109:19;8102:44;7872:365;8209:12;8202:20;;-1:-1:-1;;;8202:20:25;;;;;;;;:::i;14:347:29:-;65:8;75:6;129:3;122:4;114:6;110:17;106:27;96:55;;147:1;144;137:12;96:55;-1:-1:-1;170:20:29;;-1:-1:-1;;;;;202:30:29;;199:50;;;245:1;242;235:12;199:50;282:4;274:6;270:17;258:29;;334:3;327:4;318:6;310;306:19;302:30;299:39;296:59;;;351:1;348;341:12;366:171;433:20;;-1:-1:-1;;;;;482:30:29;;472:41;;462:69;;527:1;524;517:12;462:69;366:171;;;:::o;542:196::-;610:20;;-1:-1:-1;;;;;659:54:29;;649:65;;639:93;;728:1;725;718:12;743:864;850:6;858;866;874;882;890;943:3;931:9;922:7;918:23;914:33;911:53;;;960:1;957;950:12;911:53;1000:9;987:23;-1:-1:-1;;;;;1070:2:29;1062:6;1059:14;1056:34;;;1086:1;1083;1076:12;1056:34;1125:58;1175:7;1166:6;1155:9;1151:22;1125:58;:::i;:::-;1202:8;;-1:-1:-1;1099:84:29;-1:-1:-1;1099:84:29;;-1:-1:-1;1256:37:29;1289:2;1274:18;;1256:37;:::i;:::-;1246:47;;1346:2;1335:9;1331:18;1318:32;1302:48;;1375:2;1365:8;1362:16;1359:36;;;1391:1;1388;1381:12;1359:36;;1430:60;1482:7;1471:8;1460:9;1456:24;1430:60;:::i;:::-;1509:8;;-1:-1:-1;1404:86:29;-1:-1:-1;1563:38:29;;-1:-1:-1;1597:2:29;1582:18;;1563:38;:::i;:::-;1553:48;;743:864;;;;;;;;:::o;1612:127::-;1673:10;1668:3;1664:20;1661:1;1654:31;1704:4;1701:1;1694:15;1728:4;1725:1;1718:15;1744:120;1832:1;1825:5;1822:12;1812:46;;1838:18;;:::i;1869:249::-;2021:2;2006:18;;2033:45;2071:6;2033:45;:::i;:::-;2087:25;;;1869:249;:::o;2123:154::-;2181:5;2226:3;2217:6;2212:3;2208:16;2204:26;2201:46;;;2243:1;2240;2233:12;2201:46;-1:-1:-1;2265:6:29;2123:154;-1:-1:-1;2123:154:29:o;2282:307::-;2373:6;2381;2434:3;2422:9;2413:7;2409:23;2405:33;2402:53;;;2451:1;2448;2441:12;2402:53;2474:52;2518:7;2507:9;2474:52;:::i;:::-;2464:62;;2545:38;2578:3;2567:9;2563:19;2545:38;:::i;:::-;2535:48;;2282:307;;;;;:::o;2776:626::-;2873:6;2881;2889;2897;2905;2958:3;2946:9;2937:7;2933:23;2929:33;2926:53;;;2975:1;2972;2965:12;2926:53;2998:29;3017:9;2998:29;:::i;:::-;2988:39;;3074:2;3063:9;3059:18;3046:32;3036:42;;3129:2;3118:9;3114:18;3101:32;-1:-1:-1;;;;;3148:6:29;3145:30;3142:50;;;3188:1;3185;3178:12;3142:50;3227:58;3277:7;3268:6;3257:9;3253:22;3227:58;:::i;:::-;3304:8;;-1:-1:-1;3201:84:29;-1:-1:-1;3358:38:29;;-1:-1:-1;3392:2:29;3377:18;;3358:38;:::i;:::-;3348:48;;2776:626;;;;;;;;:::o;3604:234::-;3687:6;3740:3;3728:9;3719:7;3715:23;3711:33;3708:53;;;3757:1;3754;3747:12;3708:53;3780:52;3824:7;3813:9;3780:52;:::i;3843:118::-;3929:5;3922:13;3915:21;3908:5;3905:32;3895:60;;3951:1;3948;3941:12;3966:364;4055:6;4063;4116:3;4104:9;4095:7;4091:23;4087:33;4084:53;;;4133:1;4130;4123:12;4084:53;4156:52;4200:7;4189:9;4156:52;:::i;:::-;4146:62;;4258:3;4247:9;4243:19;4230:33;4272:28;4294:5;4272:28;:::i;:::-;4319:5;4309:15;;;3966:364;;;;;:::o;4335:180::-;4394:6;4447:2;4435:9;4426:7;4422:23;4418:32;4415:52;;;4463:1;4460;4453:12;4415:52;-1:-1:-1;4486:23:29;;4335:180;-1:-1:-1;4335:180:29:o;4520:246::-;4667:2;4652:18;;4700:1;4689:13;;4679:47;;4706:18;;:::i;4771:551::-;4859:6;4867;4875;4883;4936:2;4924:9;4915:7;4911:23;4907:32;4904:52;;;4952:1;4949;4942:12;4904:52;4975:29;4994:9;4975:29;:::i;:::-;4965:39;;5051:2;5040:9;5036:18;5023:32;5013:42;;5106:2;5095:9;5091:18;5078:32;-1:-1:-1;;;;;5125:6:29;5122:30;5119:50;;;5165:1;5162;5155:12;5119:50;5204:58;5254:7;5245:6;5234:9;5230:22;5204:58;:::i;:::-;4771:551;;;;-1:-1:-1;5281:8:29;-1:-1:-1;;;;4771:551:29:o;5690:186::-;5749:6;5802:2;5790:9;5781:7;5777:23;5773:32;5770:52;;;5818:1;5815;5808:12;5770:52;5841:29;5860:9;5841:29;:::i;5881:184::-;5939:6;5992:2;5980:9;5971:7;5967:23;5963:32;5960:52;;;6008:1;6005;5998:12;5960:52;6031:28;6049:9;6031:28;:::i;6262:409::-;6332:6;6340;6393:2;6381:9;6372:7;6368:23;6364:32;6361:52;;;6409:1;6406;6399:12;6361:52;6449:9;6436:23;-1:-1:-1;;;;;6474:6:29;6471:30;6468:50;;;6514:1;6511;6504:12;6468:50;6553:58;6603:7;6594:6;6583:9;6579:22;6553:58;:::i;:::-;6630:8;;6527:84;;-1:-1:-1;6262:409:29;-1:-1:-1;;;;6262:409:29:o;6858:774::-;6972:6;6980;6988;6996;7004;7012;7020;7073:3;7061:9;7052:7;7048:23;7044:33;7041:53;;;7090:1;7087;7080:12;7041:53;7113:29;7132:9;7113:29;:::i;:::-;7103:39;;7161:38;7195:2;7184:9;7180:18;7161:38;:::i;:::-;7151:48;;7246:2;7235:9;7231:18;7218:32;7208:42;;7269:37;7302:2;7291:9;7287:18;7269:37;:::i;:::-;7259:47;;7357:3;7346:9;7342:19;7329:33;-1:-1:-1;;;;;7377:6:29;7374:30;7371:50;;;7417:1;7414;7407:12;7371:50;7456:58;7506:7;7497:6;7486:9;7482:22;7456:58;:::i;:::-;7533:8;;-1:-1:-1;7430:84:29;-1:-1:-1;7587:39:29;;-1:-1:-1;7621:3:29;7606:19;;7587:39;:::i;:::-;7577:49;;6858:774;;;;;;;;;;:::o;7637:532::-;7740:6;7748;7756;7809:3;7797:9;7788:7;7784:23;7780:33;7777:53;;;7826:1;7823;7816:12;7777:53;7849:52;7893:7;7882:9;7849:52;:::i;:::-;7839:62;;7952:3;7941:9;7937:19;7924:33;-1:-1:-1;;;;;7972:6:29;7969:30;7966:50;;;8012:1;8009;8002:12;7966:50;8051:58;8101:7;8092:6;8081:9;8077:22;8051:58;:::i;:::-;7637:532;;8128:8;;-1:-1:-1;8025:84:29;;-1:-1:-1;;;;7637:532:29:o;8174:630::-;8270:6;8278;8286;8294;8302;8355:3;8343:9;8334:7;8330:23;8326:33;8323:53;;;8372:1;8369;8362:12;8323:53;8395:29;8414:9;8395:29;:::i;:::-;8385:39;;8443:37;8476:2;8465:9;8461:18;8443:37;:::i;:::-;8433:47;;8531:2;8520:9;8516:18;8503:32;-1:-1:-1;;;;;8550:6:29;8547:30;8544:50;;;8590:1;8587;8580:12;8809:477;8888:6;8896;8904;8957:2;8945:9;8936:7;8932:23;8928:32;8925:52;;;8973:1;8970;8963:12;8925:52;9009:9;8996:23;8986:33;;9070:2;9059:9;9055:18;9042:32;-1:-1:-1;;;;;9089:6:29;9086:30;9083:50;;;9129:1;9126;9119:12;9291:366;9353:8;9363:6;9417:3;9410:4;9402:6;9398:17;9394:27;9384:55;;9435:1;9432;9425:12;9384:55;-1:-1:-1;9458:20:29;;-1:-1:-1;;;;;9490:30:29;;9487:50;;;9533:1;9530;9523:12;9487:50;9570:4;9562:6;9558:17;9546:29;;9630:3;9623:4;9613:6;9610:1;9606:14;9598:6;9594:27;9590:38;9587:47;9584:67;;;9647:1;9644;9637:12;9662:769;9782:6;9790;9798;9806;9859:2;9847:9;9838:7;9834:23;9830:32;9827:52;;;9875:1;9872;9865:12;9827:52;9915:9;9902:23;-1:-1:-1;;;;;9985:2:29;9977:6;9974:14;9971:34;;;10001:1;9998;9991:12;9971:34;10040:69;10101:7;10092:6;10081:9;10077:22;10040:69;:::i;:::-;10128:8;;-1:-1:-1;10014:95:29;-1:-1:-1;10216:2:29;10201:18;;10188:32;;-1:-1:-1;10232:16:29;;;10229:36;;;10261:1;10258;10251:12;10229:36;;10300:71;10363:7;10352:8;10341:9;10337:24;10300:71;:::i;10436:662::-;10545:6;10553;10561;10569;10622:3;10610:9;10601:7;10597:23;10593:33;10590:53;;;10639:1;10636;10629:12;10590:53;10662:52;10706:7;10695:9;10662:52;:::i;:::-;10652:62;;10764:3;10753:9;10749:19;10736:33;10778:28;10800:5;10778:28;:::i;:::-;10825:5;-1:-1:-1;10881:3:29;10866:19;;10853:33;-1:-1:-1;;;;;10898:30:29;;10895:50;;;10941:1;10938;10931:12;11878:252;11945:6;11953;12006:2;11994:9;11985:7;11981:23;11977:32;11974:52;;;12022:1;12019;12012:12;11974:52;12045:28;12063:9;12045:28;:::i;:::-;12035:38;12120:2;12105:18;;;;12092:32;;-1:-1:-1;;;11878:252:29:o;13892:127::-;13953:10;13948:3;13944:20;13941:1;13934:31;13984:4;13981:1;13974:15;14008:4;14005:1;13998:15;14024:128;14091:9;;;14112:11;;;14109:37;;;14126:18;;:::i;14509:324::-;14691:6;14686:3;14679:19;14707:45;14745:6;14707:45;:::i;:::-;14786:3;14782:16;;;;14777:2;14768:12;;14761:38;14824:2;14815:12;;14509:324;-1:-1:-1;14509:324:29:o;17317:388::-;17474:2;17463:9;17456:21;17513:6;17508:2;17497:9;17493:18;17486:34;17570:6;17562;17557:2;17546:9;17542:18;17529:48;17626:1;17597:22;;;17621:2;17593:31;;;17586:42;;;;17689:2;17668:15;;;-1:-1:-1;;17664:29:29;17649:45;17645:54;;17317:388;-1:-1:-1;17317:388:29:o;17710:184::-;17780:6;17833:2;17821:9;17812:7;17808:23;17804:32;17801:52;;;17849:1;17846;17839:12;17801:52;-1:-1:-1;17872:16:29;;17710:184;-1:-1:-1;17710:184:29:o;20488:255::-;20608:19;;20647:2;20639:11;;20636:101;;;-1:-1:-1;;20708:2:29;20704:12;;;20701:1;20697:20;20693:33;20682:45;20488:255;;;;:::o;22120:127::-;22181:10;22176:3;22172:20;22169:1;22162:31;22212:4;22209:1;22202:15;22236:4;22233:1;22226:15;22252:163;22319:20;;22379:10;22368:22;;22358:33;;22348:61;;22405:1;22402;22395:12;22420:184;22478:6;22531:2;22519:9;22510:7;22506:23;22502:32;22499:52;;;22547:1;22544;22537:12;22499:52;22570:28;22588:9;22570:28;:::i;22967:135::-;23006:3;23027:17;;;23024:43;;23047:18;;:::i;:::-;-1:-1:-1;23094:1:29;23083:13;;22967:135::o;23224:444::-;23323:6;23318:3;23311:19;23293:3;23349:4;23378:2;23373:3;23369:12;23362:19;;23404:5;23427:1;23437:206;23451:6;23448:1;23445:13;23437:206;;;-1:-1:-1;;;;;23516:25:29;23534:6;23516:25;:::i;:::-;23512:50;23500:63;;23583:12;;;;23618:15;;;;23473:1;23466:9;23437:206;;;-1:-1:-1;23659:3:29;;23224:444;-1:-1:-1;;;;;23224:444:29:o;23673:820::-;23946:2;23935:9;23928:21;23909:4;23972:72;24040:2;24029:9;24025:18;24017:6;24009;23972:72;:::i;:::-;24101:22;;;24063:2;24081:18;;;24074:50;;;;24159:22;;;24235:6;;24197:15;;24259:1;24269:198;24283:6;24280:1;24277:13;24269:198;;;24375:10;24348:25;24366:6;24348:25;:::i;:::-;24344:42;24332:55;;24442:15;;;;24407:12;;;;24305:1;24298:9;24269:198;;;-1:-1:-1;24484:3:29;23673:820;-1:-1:-1;;;;;;;;23673:820:29:o;24498:855::-;24773:2;24762:9;24755:21;24736:4;24799:72;24867:2;24856:9;24852:18;24844:6;24836;24799:72;:::i;:::-;24928:22;;;24890:2;24908:18;;;24901:50;;;;24986:22;;;25062:6;;25024:15;;25086:1;25096:231;25110:6;25107:1;25104:13;25096:231;;;-1:-1:-1;;;;;25175:26:29;25194:6;25175:26;:::i;:::-;25171:75;25159:88;;25302:15;;;;25267:12;;;;25132:1;25125:9;25096:231;;25523:1336;-1:-1:-1;;;;;;26008:6:29;26003:3;25999:16;25995:89;25990:3;25983:102;26139:26;26135:31;26126:6;26122:2;26118:15;26114:53;26110:1;26105:3;26101:11;26094:74;26198:6;26193:2;26188:3;26184:12;26177:28;26235:6;26230:2;26225:3;26221:12;26214:28;26251:39;26286:2;26281:3;26277:12;26269:6;25431:3;25427:15;-1:-1:-1;;;;;;25423:88:29;25411:101;;25358:160;26251:39;26299:70;26364:3;26359;26355:13;26347:6;20851:2;20847:14;-1:-1:-1;;20843:52:29;20831:65;;20748:154;26299:70;26400:6;26394:3;26389;26385:13;26378:29;26416:40;26451:3;26446;26442:13;26434:6;25431:3;25427:15;-1:-1:-1;;;;;;25423:88:29;25411:101;;25358:160;26416:40;26465;26500:3;26495;26491:13;26483:6;25431:3;25427:15;-1:-1:-1;;;;;;25423:88:29;25411:101;;25358:160;26465:40;26514:70;26579:3;26574;26570:13;26562:6;20851:2;20847:14;-1:-1:-1;;20843:52:29;20831:65;;20748:154;26514:70;26593:71;26659:3;26654;26650:13;26641:7;20851:2;20847:14;-1:-1:-1;;20843:52:29;20831:65;;20748:154;26593:71;26673;26739:3;26734;26730:13;26721:7;20851:2;20847:14;-1:-1:-1;;20843:52:29;20831:65;;20748:154;26673:71;26753;26819:3;26814;26810:13;26801:7;20851:2;20847:14;-1:-1:-1;;20843:52:29;20831:65;;20748:154;26753:71;26849:3;26840:13;;25523:1336;-1:-1:-1;;;;;;;;;;;;;25523:1336:29:o;27271:168::-;27344:9;;;27375;;27392:15;;;27386:22;;27372:37;27362:71;;27413:18;;:::i;27444:217::-;27484:1;27510;27500:132;;27554:10;27549:3;27545:20;27542:1;27535:31;27589:4;27586:1;27579:15;27617:4;27614:1;27607:15;27500:132;-1:-1:-1;27646:9:29;;27444:217::o;30200:1833::-;30421:25;;;30408:3;30393:19;;30455:74;30525:2;30510:18;;30483:25;30501:6;30483:25;:::i;:::-;-1:-1:-1;;;;;23182:30:29;23170:43;;23107:112;30455:74;30558:35;30589:2;30581:6;30577:15;30558:35;:::i;:::-;-1:-1:-1;;;;;5393:54:29;;30650:2;30635:18;;5381:67;30602:52;30715:2;30707:6;30703:15;30690:29;30685:2;30674:9;30670:18;30663:57;30782:2;30774:6;30770:15;30757:29;30751:3;30740:9;30736:19;30729:58;30818:35;30848:3;30840:6;30836:16;30818:35;:::i;:::-;-1:-1:-1;;;;;23182:30:29;;30921:3;30906:19;;23170:43;30862:64;30957:36;30988:3;30980:6;30976:16;30957:36;:::i;:::-;-1:-1:-1;;;;;5393:54:29;;31052:3;31037:19;;5381:67;31002:55;31119:3;31111:6;31107:16;31094:30;31088:3;31077:9;31073:19;31066:59;31156:35;31186:3;31178:6;31174:16;31156:35;:::i;:::-;31210:3;31222:63;31281:2;31270:9;31266:18;31250:14;-1:-1:-1;;;;;23182:30:29;23170:43;;23107:112;31222:63;31316:34;31346:2;31338:6;31334:15;31316:34;:::i;:::-;31294:56;;;31369:3;31381:63;31440:2;31429:9;31425:18;31409:14;-1:-1:-1;;;;;23182:30:29;23170:43;;23107:112;31381:63;31475:35;31506:2;31498:6;31494:15;31475:35;:::i;:::-;31453:57;;;31529:3;31541:54;31591:2;31580:9;31576:18;31560:14;-1:-1:-1;;;;;5393:54:29;5381:67;;5327:127;31541:54;31626:35;31657:2;31649:6;31645:15;31626:35;:::i;:::-;31604:57;;;31680:3;31692:54;31742:2;31731:9;31727:18;31711:14;-1:-1:-1;;;;;5393:54:29;5381:67;;5327:127;31692:54;31777:35;31808:2;31800:6;31796:15;31777:35;:::i;:::-;31755:57;;;31831:3;31843:54;31893:2;31882:9;31878:18;31862:14;-1:-1:-1;;;;;5393:54:29;5381:67;;5327:127;31843:54;31928:35;31959:2;31951:6;31947:15;31928:35;:::i;:::-;31906:57;;;31972:55;32022:3;32011:9;32007:19;31991:14;-1:-1:-1;;;;;5393:54:29;5381:67;;5327:127;33727:125;33792:9;;;33813:10;;;33810:36;;;33826:18;;:::i;37064:250::-;37149:1;37159:113;37173:6;37170:1;37167:13;37159:113;;;37249:11;;;37243:18;37230:11;;;37223:39;37195:2;37188:10;37159:113;;;-1:-1:-1;;37306:1:29;37288:16;;37281:27;37064:250::o;37319:270::-;37360:3;37398:5;37392:12;37425:6;37420:3;37413:19;37441:76;37510:6;37503:4;37498:3;37494:14;37487:4;37480:5;37476:16;37441:76;:::i;:::-;37571:2;37550:15;-1:-1:-1;;37546:29:29;37537:39;;;;37578:4;37533:50;;37319:270;-1:-1:-1;;37319:270:29:o;37594:432::-;-1:-1:-1;;;;;37800:6:29;37796:55;37785:9;37778:74;-1:-1:-1;;;;;37892:6:29;37888:31;37883:2;37872:9;37868:18;37861:59;37956:2;37951;37940:9;37936:18;37929:30;37759:4;37976:44;38016:2;38005:9;38001:18;37993:6;37976:44;:::i;38031:271::-;38214:6;38206;38201:3;38188:33;38170:3;38240:16;;38265:13;;;38240:16;38031:271;-1:-1:-1;38031:271:29:o;38999:245::-;39066:6;39119:2;39107:9;39098:7;39094:23;39090:32;39087:52;;;39135:1;39132;39125:12;39087:52;39167:9;39161:16;39186:28;39208:5;39186:28;:::i;42347:287::-;42476:3;42514:6;42508:13;42530:66;42589:6;42584:3;42577:4;42569:6;42565:17;42530:66;:::i;:::-;42612:16;;;;;42347:287;-1:-1:-1;;42347:287:29:o;42639:219::-;42788:2;42777:9;42770:21;42751:4;42808:44;42848:2;42837:9;42833:18;42825:6;42808:44;:::i
Swarm Source
ipfs://d0cf8bb66abb774cf11009a7b38b3d1b5a1d355754b34237da7d1a494fad05fb
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
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.