Contract
0xd2b5945829d8254c40f63f476c9f02cf5762f8df
2
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
MetaRouter
Compiler Version
v0.8.11+commit.d7f03943
Optimization Enabled:
Yes with 2000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0 // uni -> stable -> uni scheme pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./MetaRouteStructs.sol"; import "./MetaRouterGateway.sol"; import "../../utils/RevertMessageParser.sol"; /** * @title MetaRouterV3 * @notice Users must give approve on their tokens to `MetaRoutetGateway` contract, * not to `MetaRouter` contract. */ contract MetaRouter is Context { MetaRouterGateway public immutable metaRouterGateway; constructor() { metaRouterGateway = new MetaRouterGateway(address(this)); } /** * @notice Method that starts the Meta Routing * @dev external + internal swap for burn scheme, only external for synth scheme * @dev calls the next method on the other side * @param _metarouteTransaction metaRoute offchain transaction data */ function metaRoute( MetaRouteStructs.MetaRouteTransaction calldata _metarouteTransaction ) external payable { uint256 approvedTokensLength = _metarouteTransaction.approvedTokens.length; if (!_metarouteTransaction.nativeIn) { metaRouterGateway.claimTokens( _metarouteTransaction.approvedTokens[0], _msgSender(), _metarouteTransaction.amount ); } uint256 secondSwapAmountIn = _metarouteTransaction.amount; if (_metarouteTransaction.firstSwapCalldata.length != 0) { if (!_metarouteTransaction.nativeIn) { _lazyApprove( _metarouteTransaction.approvedTokens[0], _metarouteTransaction.firstDexRouter, _metarouteTransaction.amount ); } require( _metarouteTransaction.firstDexRouter != address(metaRouterGateway), "MetaRouter: invalid first router" ); (bool firstSwapSuccess, bytes memory swapData) = _metarouteTransaction.firstDexRouter.call{value: msg.value}( _metarouteTransaction.firstSwapCalldata ); if (!firstSwapSuccess) { revert(RevertMessageParser.getRevertMessage(swapData, "MetaRouter: first swap failed")); } secondSwapAmountIn = IERC20(_metarouteTransaction.approvedTokens[1]).balanceOf(address(this)); } uint256 finalSwapAmountIn = secondSwapAmountIn; if (_metarouteTransaction.secondSwapCalldata.length != 0) { bytes memory secondSwapCalldata = _metarouteTransaction.secondSwapCalldata; assembly { mstore(add(secondSwapCalldata, 100), secondSwapAmountIn) } _lazyApprove( _metarouteTransaction.approvedTokens[approvedTokensLength - 2], _metarouteTransaction.secondDexRouter, secondSwapAmountIn ); require( _metarouteTransaction.secondDexRouter != address(metaRouterGateway), "MetaRouter: invalid second router" ); (bool secondSwapSuccess, bytes memory swapData) = _metarouteTransaction.secondDexRouter.call(secondSwapCalldata); if (!secondSwapSuccess) { revert(RevertMessageParser.getRevertMessage(swapData, "MetaRouter: second swap failed")); } finalSwapAmountIn = IERC20( _metarouteTransaction.approvedTokens[approvedTokensLength - 1] ).balanceOf(address(this)); } _lazyApprove( _metarouteTransaction.approvedTokens[approvedTokensLength - 1], _metarouteTransaction.relayRecipient, finalSwapAmountIn ); bytes memory otherSideCalldata = _metarouteTransaction.otherSideCalldata; assembly { mstore(add(otherSideCalldata, 100), finalSwapAmountIn) } require( _metarouteTransaction.relayRecipient != address(metaRouterGateway), "MetaRouter: invalid recipient" ); (bool otherSideCallSuccess, bytes memory data) = _metarouteTransaction.relayRecipient.call(otherSideCalldata); if (!otherSideCallSuccess) { revert(RevertMessageParser.getRevertMessage(data, "MetaRouter: other side call failed")); } } /** * @notice Implements an external call on some contract * @dev called by Portal in metaUnsynthesize() method * @param _token address of token * @param _amount amount of _token * @param _receiveSide contract on which call will take place * @param _calldata encoded method to call * @param _offset shift to patch the amount to calldata */ function externalCall( address _token, uint256 _amount, address _receiveSide, bytes calldata _calldata, uint256 _offset ) external { (bool success, bytes memory data) = _externalCall(_token, _amount, _receiveSide, _calldata, _offset); if (!success) { revert(RevertMessageParser.getRevertMessage(data, "MetaRouter: external call failed")); } } /** * @notice Implements an internal swap on stable router and final method call * @dev called by Synthesis in metaMint() method * @param _metaMintTransaction metaMint offchain transaction data */ function metaMintSwap( MetaRouteStructs.MetaMintTransaction calldata _metaMintTransaction ) external { address finalCallToken = _metaMintTransaction.swapTokens[0]; if (_metaMintTransaction.secondSwapCalldata.length != 0) { // internal swap (bool internalSwapSuccess, bytes memory internalSwapData) = _externalCall( _metaMintTransaction.swapTokens[0], _metaMintTransaction.amount, _metaMintTransaction.secondDexRouter, _metaMintTransaction.secondSwapCalldata, 100 ); if (!internalSwapSuccess) { revert(RevertMessageParser.getRevertMessage(internalSwapData, "MetaRouter: internal swap failed")); } uint256 internalSwapReturnAmount = IERC20(_metaMintTransaction.swapTokens[1]).balanceOf(address(this)); // exit without external call if (_metaMintTransaction.swapTokens.length == 2) { TransferHelper.safeTransfer( _metaMintTransaction.swapTokens[1], _metaMintTransaction.to, internalSwapReturnAmount ); return; } finalCallToken = _metaMintTransaction.swapTokens[1]; } uint256 finalAmountIn = IERC20(finalCallToken).balanceOf(address(this)); // external call (bool finalSuccess, bytes memory finalData) = _externalCall( finalCallToken, finalAmountIn, _metaMintTransaction.finalReceiveSide, _metaMintTransaction.finalCalldata, _metaMintTransaction.finalOffset ); if (!finalSuccess) { revert(RevertMessageParser.getRevertMessage(finalData, "MetaRouter: final call failed")); } uint256 externalCallAmountOut = IERC20(_metaMintTransaction.swapTokens[_metaMintTransaction.swapTokens.length - 1]).balanceOf(address(this)); if (externalCallAmountOut != 0) { TransferHelper.safeTransfer( _metaMintTransaction.swapTokens[_metaMintTransaction.swapTokens.length - 1], _metaMintTransaction.to, externalCallAmountOut ); } } /** * @notice Implements call of some operation with token * @dev Internal function used in metaMintSwap() and externalCall() * @param _token token address * @param _amount amount of _token * @param _receiveSide address of contract on which method will be called * @param _calldata encoded method call * @param _offset shift to patch the _amount to calldata */ function _externalCall( address _token, uint256 _amount, address _receiveSide, bytes memory _calldata, uint256 _offset ) internal returns (bool success, bytes memory data) { require(_receiveSide != address(metaRouterGateway), "MetaRouter: invalid receiveSide"); _lazyApprove(_token, _receiveSide, _amount); assembly { mstore(add(_calldata, _offset), _amount) } (success, data) = _receiveSide.call(_calldata); } /** * @notice Implements approve * @dev Internal function used to approve the token spending * @param _token token address * @param _to address to approve * @param _amount amount for which approve will be given */ function _lazyApprove(address _token, address _to, uint256 _amount) internal { if (IERC20(_token).allowance(address(this), _to) < _amount) { TransferHelper.safeApprove(_token, _to, type(uint256).max); } } }
// 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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, 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: GPL-3.0 pragma solidity ^0.8.0; library MetaRouteStructs { struct MetaBurnTransaction { uint256 stableBridgingFee; uint256 amount; address syntCaller; address finalReceiveSide; address sToken; bytes finalCallData; uint256 finalOffset; address chain2address; address receiveSide; address oppositeBridge; address revertableAddress; uint256 chainID; bytes32 clientID; } struct MetaMintTransaction { uint256 stableBridgingFee; uint256 amount; bytes32 externalID; address tokenReal; uint256 chainID; address to; address[] swapTokens; address secondDexRouter; bytes secondSwapCalldata; address finalReceiveSide; bytes finalCalldata; uint256 finalOffset; } struct MetaRouteTransaction { bytes firstSwapCalldata; bytes secondSwapCalldata; address[] approvedTokens; address firstDexRouter; address secondDexRouter; uint256 amount; bool nativeIn; address relayRecipient; bytes otherSideCalldata; } struct MetaSynthesizeTransaction { uint256 stableBridgingFee; uint256 amount; address rtoken; address chain2address; address receiveSide; address oppositeBridge; address syntCaller; uint256 chainID; address[] swapTokens; address secondDexRouter; bytes secondSwapCalldata; address finalReceiveSide; bytes finalCalldata; uint256 finalOffset; address revertableAddress; bytes32 clientID; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; import "@uniswap/lib/contracts/libraries/TransferHelper.sol"; /** * @title MetaRouterGateway * @notice During the `metaRoute` transaction `MetaRouter` (only) claims user's tokens * from `MetaRoutetGateway` contract and then operates with them. */ contract MetaRouterGateway { address public immutable metaRouter; modifier onlyMetarouter() { require(metaRouter == msg.sender, "Symb: caller is not the metarouter"); _; } constructor(address _metaRouter) { metaRouter = _metaRouter; } function claimTokens( address _token, address _from, uint256 _amount ) external onlyMetarouter { TransferHelper.safeTransferFrom(_token, _from, metaRouter, _amount); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; library RevertMessageParser { function getRevertMessage(bytes memory _data, string memory _defaultMessage) internal pure returns (string memory) { // If the _data length is less than 68, then the transaction failed silently (without a revert message) if (_data.length < 68) return _defaultMessage; assembly { // Slice the sighash _data := add(_data, 0x04) } return abi.decode(_data, (string)); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.0; // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeApprove: approve failed' ); } function safeTransfer( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeTransfer: transfer failed' ); } function safeTransferFrom( address token, address from, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::transferFrom: transferFrom failed' ); } function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'TransferHelper::safeTransferETH: ETH transfer failed'); } }
{ "optimizer": { "enabled": true, "runs": 2000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_receiveSide","type":"address"},{"internalType":"bytes","name":"_calldata","type":"bytes"},{"internalType":"uint256","name":"_offset","type":"uint256"}],"name":"externalCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"stableBridgingFee","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"externalID","type":"bytes32"},{"internalType":"address","name":"tokenReal","type":"address"},{"internalType":"uint256","name":"chainID","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address[]","name":"swapTokens","type":"address[]"},{"internalType":"address","name":"secondDexRouter","type":"address"},{"internalType":"bytes","name":"secondSwapCalldata","type":"bytes"},{"internalType":"address","name":"finalReceiveSide","type":"address"},{"internalType":"bytes","name":"finalCalldata","type":"bytes"},{"internalType":"uint256","name":"finalOffset","type":"uint256"}],"internalType":"struct MetaRouteStructs.MetaMintTransaction","name":"_metaMintTransaction","type":"tuple"}],"name":"metaMintSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"firstSwapCalldata","type":"bytes"},{"internalType":"bytes","name":"secondSwapCalldata","type":"bytes"},{"internalType":"address[]","name":"approvedTokens","type":"address[]"},{"internalType":"address","name":"firstDexRouter","type":"address"},{"internalType":"address","name":"secondDexRouter","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"nativeIn","type":"bool"},{"internalType":"address","name":"relayRecipient","type":"address"},{"internalType":"bytes","name":"otherSideCalldata","type":"bytes"}],"internalType":"struct MetaRouteStructs.MetaRouteTransaction","name":"_metarouteTransaction","type":"tuple"}],"name":"metaRoute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"metaRouterGateway","outputs":[{"internalType":"contract MetaRouterGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b503060405161001e9061005c565b6001600160a01b039091168152602001604051809103906000f08015801561004a573d6000803e3d6000fd5b506001600160a01b0316608052610069565b6104d08061181c83390190565b6080516117766100a660003960008181606b0152818161011a0152818161027a01528181610541015281816107fc0152610f7001526117766000f3fe60806040526004361061003f5760003560e01c8063a11b119814610044578063c394a5da14610059578063e1edd61c146100a9578063e1ee0f79146100c9575b600080fd5b610057610052366004611339565b6100e9565b005b34801561006557600080fd5b5061008d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b3480156100b557600080fd5b506100576100c436600461137c565b610926565b3480156100d557600080fd5b506100576100e43660046113d4565b610dd9565b60006100f8604083018361147a565b915061010c905060e0830160c084016114dc565b6101f6576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016639fc314c861014c604085018561147a565b600081811061015d5761015d6114f9565b9050602002016020810190610172919061150f565b336040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0392831660048201529116602482015260a08501356044820152606401600060405180830381600087803b1580156101dd57600080fd5b505af11580156101f1573d6000803e3d6000fd5b505050505b60a0820135610205838061152a565b1590506104815761021c60e0840160c085016114dc565b61027057610270610230604085018561147a565b6000818110610241576102416114f9565b9050602002016020810190610256919061150f565b610266608086016060870161150f565b8560a00135610e72565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166102aa608085016060860161150f565b6001600160a01b031614156103065760405162461bcd60e51b815260206004820181905260248201527f4d657461526f757465723a20696e76616c696420666972737420726f7574657260448201526064015b60405180910390fd5b600080610319608086016060870161150f565b6001600160a01b03163461032d878061152a565b60405161033b929190611571565b60006040518083038185875af1925050503d8060008114610378576040519150601f19603f3d011682016040523d82523d6000602084013e61037d565b606091505b5091509150816103df576103c6816040518060400160405280601d81526020017f4d657461526f757465723a2066697273742073776170206661696c6564000000815250610f34565b60405162461bcd60e51b81526004016102fd91906115b1565b6103ec604086018661147a565b60018181106103fd576103fd6114f9565b9050602002016020810190610412919061150f565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610458573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047c91906115e4565b925050505b8061048f602085018561152a565b15905061074f5760006104a5602086018661152a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506064810184905290506105376104f2604087018761147a565b6104fd6002886115fd565b81811061050c5761050c6114f9565b9050602002016020810190610521919061150f565b61053160a088016080890161150f565b85610e72565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001661057160a087016080880161150f565b6001600160a01b031614156105ee5760405162461bcd60e51b815260206004820152602160248201527f4d657461526f757465723a20696e76616c6964207365636f6e6420726f75746560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084016102fd565b60008061060160a088016080890161150f565b6001600160a01b0316836040516106189190611622565b6000604051808303816000865af19150503d8060008114610655576040519150601f19603f3d011682016040523d82523d6000602084013e61065a565b606091505b5091509150816106a3576103c6816040518060400160405280601e81526020017f4d657461526f757465723a207365636f6e642073776170206661696c65640000815250610f34565b6106b0604088018861147a565b6106bb6001896115fd565b8181106106ca576106ca6114f9565b90506020020160208101906106df919061150f565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610725573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074991906115e4565b93505050505b6107a561075f604086018661147a565b61076a6001876115fd565b818110610779576107796114f9565b905060200201602081019061078e919061150f565b61079f610100870160e0880161150f565b83610e72565b60006107b561010086018661152a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506064810183905290506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001661082d610100870160e0880161150f565b6001600160a01b031614156108845760405162461bcd60e51b815260206004820152601d60248201527f4d657461526f757465723a20696e76616c696420726563697069656e7400000060448201526064016102fd565b600080610898610100880160e0890161150f565b6001600160a01b0316836040516108af9190611622565b6000604051808303816000865af19150503d80600081146108ec576040519150601f19603f3d011682016040523d82523d6000602084013e6108f1565b606091505b50915091508161091d576103c68160405180606001604052806022815260200161171f60229139610f34565b50505050505050565b600061093560c083018361147a565b6000818110610946576109466114f9565b905060200201602081019061095b919061150f565b905061096b61010083018361152a565b159050610b9857600080610a0c61098560c086018661147a565b6000818110610996576109966114f9565b90506020020160208101906109ab919061150f565b60208601356109c1610100880160e0890161150f565b6109cf61010089018961152a565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060649250610f6a915050565b9150915081610a54576103c6816040518060400160405280602081526020017f4d657461526f757465723a20696e7465726e616c2073776170206661696c6564815250610f34565b6000610a6360c086018661147a565b6001818110610a7457610a746114f9565b9050602002016020810190610a89919061150f565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610acf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af391906115e4565b9050610b0260c086018661147a565b905060021415610b5f57610b58610b1c60c087018761147a565b6001818110610b2d57610b2d6114f9565b9050602002016020810190610b42919061150f565b610b5260c0880160a0890161150f565b83611069565b5050505050565b610b6c60c086018661147a565b6001818110610b7d57610b7d6114f9565b9050602002016020810190610b92919061150f565b93505050505b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0391906115e4565b9050600080610c6c8484610c1f61014089016101208a0161150f565b610c2d6101408a018a61152a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506101608a0135610f6a565b9150915081610cb4576103c6816040518060400160405280601d81526020017f4d657461526f757465723a2066696e616c2063616c6c206661696c6564000000815250610f34565b6000610cc360c087018761147a565b6001610cd260c08a018a61147a565b610cdd9291506115fd565b818110610cec57610cec6114f9565b9050602002016020810190610d01919061150f565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015610d47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6b91906115e4565b90508015610dd157610dd1610d8360c088018861147a565b6001610d9260c08b018b61147a565b610d9d9291506115fd565b818110610dac57610dac6114f9565b9050602002016020810190610dc1919061150f565b610b5260c0890160a08a0161150f565b505050505050565b600080610e2088888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250610f6a915050565b9150915081610e68576103c6816040518060400160405280602081526020017f4d657461526f757465723a2065787465726e616c2063616c6c206661696c6564815250610f34565b5050505050505050565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015282919085169063dd62ed3e90604401602060405180830381865afa158015610eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610efe91906115e4565b1015610f2f57610f2f83837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6111d1565b505050565b6060604483511015610f47575080610f64565b60048301925082806020019051810190610f619190611654565b90505b92915050565b600060607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b03161415610ff05760405162461bcd60e51b815260206004820152601f60248201527f4d657461526f757465723a20696e76616c69642072656365697665536964650060448201526064016102fd565b610ffb878688610e72565b8583850152846001600160a01b0316846040516110189190611622565b6000604051808303816000865af19150503d8060008114611055576040519150601f19603f3d011682016040523d82523d6000602084013e61105a565b606091505b50909890975095505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916110f39190611622565b6000604051808303816000865af19150503d8060008114611130576040519150601f19603f3d011682016040523d82523d6000602084013e611135565b606091505b509150915081801561115f57508051158061115f57508080602001905181019061115f9190611701565b610b585760405162461bcd60e51b815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201527f616e73666572206661696c65640000000000000000000000000000000000000060648201526084016102fd565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052915160009283929087169161125b9190611622565b6000604051808303816000865af19150503d8060008114611298576040519150601f19603f3d011682016040523d82523d6000602084013e61129d565b606091505b50915091508180156112c75750805115806112c75750808060200190518101906112c79190611701565b610b585760405162461bcd60e51b815260206004820152602b60248201527f5472616e7366657248656c7065723a3a73616665417070726f76653a2061707060448201527f726f7665206661696c656400000000000000000000000000000000000000000060648201526084016102fd565b60006020828403121561134b57600080fd5b813567ffffffffffffffff81111561136257600080fd5b8201610120818503121561137557600080fd5b9392505050565b60006020828403121561138e57600080fd5b813567ffffffffffffffff8111156113a557600080fd5b8201610180818503121561137557600080fd5b80356001600160a01b03811681146113cf57600080fd5b919050565b60008060008060008060a087890312156113ed57600080fd5b6113f6876113b8565b95506020870135945061140b604088016113b8565b9350606087013567ffffffffffffffff8082111561142857600080fd5b818901915089601f83011261143c57600080fd5b81358181111561144b57600080fd5b8a602082850101111561145d57600080fd5b602083019550809450505050608087013590509295509295509295565b6000808335601e1984360301811261149157600080fd5b83018035915067ffffffffffffffff8211156114ac57600080fd5b6020019150600581901b36038213156114c457600080fd5b9250929050565b80151581146114d957600080fd5b50565b6000602082840312156114ee57600080fd5b8135611375816114cb565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561152157600080fd5b610f61826113b8565b6000808335601e1984360301811261154157600080fd5b83018035915067ffffffffffffffff82111561155c57600080fd5b6020019150368190038213156114c457600080fd5b8183823760009101908152919050565b60005b8381101561159c578181015183820152602001611584565b838111156115ab576000848401525b50505050565b60208152600082518060208401526115d0816040850160208701611581565b601f01601f19169190910160400192915050565b6000602082840312156115f657600080fd5b5051919050565b60008282101561161d57634e487b7160e01b600052601160045260246000fd5b500390565b60008251611634818460208701611581565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561166657600080fd5b815167ffffffffffffffff8082111561167e57600080fd5b818401915084601f83011261169257600080fd5b8151818111156116a4576116a461163e565b604051601f8201601f19908116603f011681019083821181831017156116cc576116cc61163e565b816040528281528760208487010111156116e557600080fd5b6116f6836020830160208801611581565b979650505050505050565b60006020828403121561171357600080fd5b8151611375816114cb56fe4d657461526f757465723a206f7468657220736964652063616c6c206661696c6564a264697066735822122038f27bdfb83d00ba14804e191388e0e86d9bf9dfe8563555eac6972281f89d2c64736f6c634300080b003360a060405234801561001057600080fd5b506040516104d03803806104d083398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b6080516104396100976000396000818160550152818160a2015261017101526104396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80639fc314c81461003b578063dbec15bb14610050575b600080fd5b61004e610049366004610363565b6100a0565b005b6100777f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16331461016a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f53796d623a2063616c6c6572206973206e6f7420746865206d657461726f757460448201527f657200000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61019683837f00000000000000000000000000000000000000000000000000000000000000008461019b565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161023a919061039f565b6000604051808303816000865af19150503d8060008114610277576040519150601f19603f3d011682016040523d82523d6000602084013e61027c565b606091505b50915091508180156102a65750805115806102a65750808060200190518101906102a691906103da565b610332576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c65640000000000000000000000000000006064820152608401610161565b505050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461035e57600080fd5b919050565b60008060006060848603121561037857600080fd5b6103818461033a565b925061038f6020850161033a565b9150604084013590509250925092565b6000825160005b818110156103c057602081860181015185830152016103a6565b818111156103cf576000828501525b509190910192915050565b6000602082840312156103ec57600080fd5b815180151581146103fc57600080fd5b939250505056fea26469706673582212202cd6ac3fbe807d5dff29d8e687a3d6bfcc72a63c84781d24f85c2ebf35d4bae164736f6c634300080b0033
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.