Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Safe
- Optimization enabled
- false
- Compiler version
- v0.7.6+commit.7338295f
- EVM Version
- default
- Verified at
- 2024-06-26T04:14:18.213143Z
contracts/Safe.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "./base/ModuleManager.sol";import "./base/OwnerManager.sol";import "./base/FallbackManager.sol";import "./base/GuardManager.sol";import "./common/NativeCurrencyPaymentFallback.sol";import "./common/Singleton.sol";import "./common/SignatureDecoder.sol";import "./common/SecuredTokenTransfer.sol";import "./common/StorageAccessible.sol";import "./interfaces/ISignatureValidator.sol";import "./external/SafeMath.sol";/*** @title Safe - A multisignature wallet with support for confirmations using signed messages based on EIP-712.* @dev Most important concepts:* - Threshold: Number of required confirmations for a Safe transaction.* - Owners: List of addresses that control the Safe. They are the only ones that can add/remove owners, change the threshold and* approve transactions. Managed in `OwnerManager`.* - Transaction Hash: Hash of a transaction is calculated using the EIP-712 typed structured data hashing scheme.* - Nonce: Each transaction should have a different nonce to prevent replay attacks.* - Signature: A valid signature of an owner of the Safe for a transaction hash.* - Guard: Guard is a contract that can execute pre- and post- transaction checks. Managed in `GuardManager`.* - Modules: Modules are contracts that can be used to extend the write functionality of a Safe. Managed in `ModuleManager`.* - Fallback: Fallback handler is a contract that can provide additional read-only functional for Safe. Managed in `FallbackManager`.* Note: This version of the implementation contract doesn't emit events for the sake of gas efficiency and therefore requires a tracing node for indexing/* For the events-based implementation see `SafeL2.sol`.* @author Stefan George - @Georgi87* @author Richard Meissner - @rmeissner*/contract Safe isSingleton,NativeCurrencyPaymentFallback,ModuleManager,OwnerManager,SignatureDecoder,SecuredTokenTransfer,ISignatureValidatorConstants,FallbackManager,
contracts/common/Singleton.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title Singleton - Base for singleton contracts (should always be the first super contract)* This contract is tightly coupled to our proxy contract (see `proxies/SafeProxy.sol`)* @author Richard Meissner - @rmeissner*/abstract contract Singleton {// singleton always has to be the first declared variable to ensure the same location as in the Proxy contract.// It should also always be ensured the address is stored alone (uses a full word)address private singleton;}
@openzeppelin/contracts/token/ERC20/ERC20.sol
// SPDX-License-Identifier: MITpragma solidity >=0.6.0 <0.8.0;import "../../utils/Context.sol";import "./IERC20.sol";import "../../math/SafeMath.sol";/*** @dev Implementation of the {IERC20} interface.** This implementation is agnostic to the way tokens are created. This means* that a supply mechanism has to be added in a derived contract using {_mint}.* For a generic mechanism see {ERC20PresetMinterPauser}.** TIP: For a detailed writeup see our guide* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How* to implement supply mechanisms].** We have followed general OpenZeppelin guidelines: functions revert instead* of returning `false` on failure. This behavior is nonetheless conventional* and does not conflict with the expectations of ERC20 applications.** Additionally, an {Approval} event is emitted on calls to {transferFrom}.* This allows applications to reconstruct the allowance for all accounts just* by listening to said events. Other implementations of the EIP may not emit* these events, as it isn't required by the specification.** Finally, the non-standard {decreaseAllowance} and {increaseAllowance}* functions have been added to mitigate the well-known issues around setting* allowances. See {IERC20-approve}.*/contract ERC20 is Context, IERC20 {using SafeMath for uint256;mapping (address => uint256) private _balances;mapping (address => mapping (address => uint256)) private _allowances;uint256 private _totalSupply;
contracts/common/Enum.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title Enum - Collection of enums used in Safe contracts.* @author Richard Meissner - @rmeissner*/abstract contract Enum {enum Operation {Call,DelegateCall}}
@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MITpragma solidity >=0.6.0 <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 GSN 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 payable) {return msg.sender;}function _msgData() internal view virtual returns (bytes memory) {this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691return msg.data;}}
contracts/interfaces/ISignatureValidator.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;contract ISignatureValidatorConstants {// bytes4(keccak256("isValidSignature(bytes,bytes)")bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b;}abstract contract ISignatureValidator is ISignatureValidatorConstants {/*** @notice Legacy EIP1271 method to validate a signature.* @param _data Arbitrary length data signed on the behalf of address(this).* @param _signature Signature byte array associated with _data.** MUST return the bytes4 magic value 0x20c13b0b when function passes.* MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)* MUST allow external calls*/function isValidSignature(bytes memory _data, bytes memory _signature) public view virtual returns (bytes4);}
contracts/test/TestHandler.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../handler/HandlerContext.sol";/*** @title TestHandler - A test FallbackHandler contract*/contract TestHandler is HandlerContext {/*** @notice Returns the sender and manager address provided by the HandlerContext* @return sender The sender address* @return manager The manager address*/function dudududu() external view returns (address sender, address manager) {return (_msgSender(), _manager());}}
contracts/proxies/SafeProxyFactory.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "./SafeProxy.sol";import "./IProxyCreationCallback.sol";/*** @title Proxy Factory - Allows to create a new proxy contract and execute a message call to the new proxy within one transaction.* @author Stefan George - @Georgi87*/contract SafeProxyFactory {event ProxyCreation(SafeProxy indexed proxy, address singleton);/// @dev Allows to retrieve the creation code used for the Proxy deployment. With this it is easily possible to calculate predicted address.function proxyCreationCode() public pure returns (bytes memory) {return type(SafeProxy).creationCode;}/*** @notice Internal method to create a new proxy contract using CREATE2. Optionally executes an initializer call to a new proxy.* @param _singleton Address of singleton contract. Must be deployed at the time of execution.* @param initializer (Optional) Payload for a message call to be sent to a new proxy contract.* @param salt Create2 salt to use for calculating the address of the new proxy contract.* @return proxy Address of the new proxy contract.*/function deployProxy(address _singleton, bytes memory initializer, bytes32 salt) internal returns (SafeProxy proxy) {require(isContract(_singleton), "Singleton contract not deployed");bytes memory deploymentData = abi.encodePacked(type(SafeProxy).creationCode, uint256(uint160(_singleton)));// solhint-disable-next-line no-inline-assemblyassembly {proxy := create2(0x0, add(0x20, deploymentData), mload(deploymentData), salt)}require(address(proxy) != address(0), "Create2 call failed");if (initializer.length > 0) {// solhint-disable-next-line no-inline-assemblyassembly {if eq(call(gas(), proxy, 0, add(initializer, 0x20), mload(initializer), 0, 0), 0) {revert(0, 0)}
contracts/libraries/MultiSendCallOnly.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title Multi Send Call Only - Allows to batch multiple transactions into one, but only calls* @notice The guard logic is not required here as this contract doesn't support nested delegate calls* @author Stefan George - @Georgi87* @author Richard Meissner - @rmeissner*/contract MultiSendCallOnly {/*** @dev Sends multiple transactions and reverts all if one fails.* @param transactions Encoded transactions. Each transaction is encoded as a packed bytes of* operation has to be uint8(0) in this version (=> 1 byte),* to as a address (=> 20 bytes),* value as a uint256 (=> 32 bytes),* data length as a uint256 (=> 32 bytes),* data as bytes.* see abi.encodePacked for more information on packed encoding* @notice The code is for most part the same as the normal MultiSend (to keep compatibility),* but reverts if a transaction tries to use a delegatecall.* @notice This method is payable as delegatecalls keep the msg.value from the previous call* If the calling method (e.g. execTransaction) received ETH this would revert otherwise*/function multiSend(bytes memory transactions) public payable {// solhint-disable-next-line no-inline-assemblyassembly {let length := mload(transactions)let i := 0x20for {// Pre block is not used in "while mode"} lt(i, length) {// Post block is not used in "while mode"} {// First byte of the data is the operation.// We shift by 248 bits (256 - 8 [operation byte]) it right since mload will always load 32 bytes (a word).// This will also zero out unused data.let operation := shr(0xf8, mload(add(transactions, i)))// We offset the load address by 1 byte (operation byte)// We shift it right by 96 bits (256 - 160 [20 address bytes]) to right-align the data and zero out unused data.let to := shr(0x60, mload(add(transactions, add(i, 0x01))))
contracts/proxies/SafeProxy.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title IProxy - Helper interface to access the singleton address of the Proxy on-chain.* @author Richard Meissner - @rmeissner*/interface IProxy {function masterCopy() external view returns (address);}/*** @title SafeProxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.* @author Stefan George - <stefan@gnosis.io>* @author Richard Meissner - <richard@gnosis.io>*/contract SafeProxy {// Singleton always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.// To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt`address internal singleton;/*** @notice Constructor function sets address of singleton contract.* @param _singleton Singleton address.*/constructor(address _singleton) {require(_singleton != address(0), "Invalid singleton address provided");singleton = _singleton;}/// @dev Fallback function forwards all transactions and returns all received return data.fallback() external payable {// solhint-disable-next-line no-inline-assemblyassembly {let _singleton := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)// 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0sif eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {mstore(0, _singleton)return(0, 0x20)}calldatacopy(0, 0, calldatasize())
contracts/common/SignatureDecoder.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title SignatureDecoder - Decodes signatures encoded as bytes* @author Richard Meissner - @rmeissner*/abstract contract SignatureDecoder {/*** @notice Splits signature bytes into `uint8 v, bytes32 r, bytes32 s`.* @dev Make sure to perform a bounds check for @param pos, to avoid out of bounds access on @param signatures* The signature format is a compact form of {bytes32 r}{bytes32 s}{uint8 v}* Compact means uint8 is not padded to 32 bytes.* @param pos Which signature to read.* A prior bounds check of this parameter should be performed, to avoid out of bounds access.* @param signatures Concatenated {r, s, v} signatures.* @return v Recovery ID or Safe signature type.* @return r Output value r of the signature.* @return s Output value s of the signature.*/function signatureSplit(bytes memory signatures, uint256 pos) internal pure returns (uint8 v, bytes32 r, bytes32 s) {// solhint-disable-next-line no-inline-assemblyassembly {let signaturePos := mul(0x41, pos)r := mload(add(signatures, add(signaturePos, 0x20)))s := mload(add(signatures, add(signaturePos, 0x40)))/*** Here we are loading the last 32 bytes, including 31 bytes* of 's'. There is no 'mload8' to do this.* 'byte' is not working due to the Solidity parser, so lets* use the second best option, 'and'*/v := and(mload(add(signatures, add(signaturePos, 0x41))), 0xff)}}}
contracts/libraries/SignMessageLib.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "./SafeStorage.sol";import "../Safe.sol";/*** @title SignMessageLib - Allows to sign messages on-chain by writing the signed message hashes on-chain.* @author Richard Meissner - @rmeissner*/contract SignMessageLib is SafeStorage {// keccak256("SafeMessage(bytes message)");bytes32 private constant SAFE_MSG_TYPEHASH = 0x60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca;event SignMsg(bytes32 indexed msgHash);/*** @notice Marks a message (`_data`) as signed.* @dev Can be verified using EIP-1271 validation method by passing the pre-image of the message hash and empty bytes as the signature.* @param _data Arbitrary length data that should be marked as signed on the behalf of address(this).*/function signMessage(bytes calldata _data) external {bytes32 msgHash = getMessageHash(_data);signedMessages[msgHash] = 1;emit SignMsg(msgHash);}/*** @dev Returns hash of a message that can be signed by owners.* @param message Message that should be hashed.* @return Message hash.*/function getMessageHash(bytes memory message) public view returns (bytes32) {bytes32 safeMessageHash = keccak256(abi.encode(SAFE_MSG_TYPEHASH, keccak256(message)));return keccak256(abi.encodePacked(bytes1(0x19), bytes1(0x01), Safe(payable(address(this))).domainSeparator(), safeMessageHash));}}
contracts/interfaces/ERC777TokensRecipient.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title ERC777TokensRecipient* @dev Interface for contracts that will be called with the ERC777 token's `tokensReceived` method.* The contract receiving the tokens must implement this interface in order to receive the tokens.*/interface ERC777TokensRecipient {/*** @dev Called by the ERC777 token contract after a successful transfer or a minting operation.* @param operator The address of the operator performing the transfer or minting operation.* @param from The address of the sender.* @param to The address of the recipient.* @param amount The amount of tokens that were transferred or minted.* @param data Additional data that was passed during the transfer or minting operation.* @param operatorData Additional data that was passed by the operator during the transfer or minting operation.*/function tokensReceived(address operator,address from,address to,uint256 amount,bytes calldata data,bytes calldata operatorData) external;}
contracts/examples/guards/DebugTransactionGuard.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../../common/Enum.sol";import "../../base/GuardManager.sol";import "../../Safe.sol";/*** @title Debug Transaction Guard - Emits transaction events with extended information.* @dev This guard is only meant as a development tool and example* @author Richard Meissner - @rmeissner*/contract DebugTransactionGuard is BaseGuard {// solhint-disable-next-line payable-fallbackfallback() external {// We don't revert on fallback to avoid issues in case of a Safe upgrade// E.g. The expected check method might change and then the Safe would be locked.}event TransactionDetails(address indexed safe,bytes32 indexed txHash,address to,uint256 value,bytes data,Enum.Operation operation,uint256 safeTxGas,bool usesRefund,uint256 nonce,bytes signatures,address executor);event GasUsage(address indexed safe, bytes32 indexed txHash, uint256 indexed nonce, bool success);mapping(bytes32 => uint256) public txNonces;/*** @notice Called by the Safe contract before a transaction is executed.* @param to Destination address of Safe transaction.* @param value Ether value of Safe transaction.
contracts/proxies/IProxyCreationCallback.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "./SafeProxy.sol";/*** @title IProxyCreationCallback* @dev An interface for a contract that implements a callback function to be executed after the creation of a proxy instance.*/interface IProxyCreationCallback {/*** @dev Function to be called after the creation of a SafeProxy instance.* @param proxy The newly created SafeProxy instance.* @param _singleton The address of the singleton contract used to create the proxy.* @param initializer The initializer function call data.* @param saltNonce The nonce used to generate the salt for the proxy deployment.*/function proxyCreated(SafeProxy proxy, address _singleton, bytes calldata initializer, uint256 saltNonce) external;}
contracts/handler/CompatibilityFallbackHandler.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "./TokenCallbackHandler.sol";import "../interfaces/ISignatureValidator.sol";import "../Safe.sol";/*** @title Compatibility Fallback Handler - Provides compatibility between pre 1.3.0 and 1.3.0+ Safe contracts.* @author Richard Meissner - @rmeissner*/contract CompatibilityFallbackHandler is TokenCallbackHandler, ISignatureValidator {// keccak256("SafeMessage(bytes message)");bytes32 private constant SAFE_MSG_TYPEHASH = 0x60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca;bytes4 internal constant SIMULATE_SELECTOR = bytes4(keccak256("simulate(address,bytes)"));address internal constant SENTINEL_MODULES = address(0x1);bytes4 internal constant UPDATED_MAGIC_VALUE = 0x1626ba7e;/*** @notice Legacy EIP-1271 signature validation method.* @dev Implementation of ISignatureValidator (see `interfaces/ISignatureValidator.sol`)* @param _data Arbitrary length data signed on the behalf of address(msg.sender).* @param _signature Signature byte array associated with _data.* @return The EIP-1271 magic value.*/function isValidSignature(bytes memory _data, bytes memory _signature) public view override returns (bytes4) {// Caller should be a SafeSafe safe = Safe(payable(msg.sender));bytes memory messageData = encodeMessageDataForSafe(safe, _data);bytes32 messageHash = keccak256(messageData);if (_signature.length == 0) {require(safe.signedMessages(messageHash) != 0, "Hash not approved");} else {safe.checkSignatures(messageHash, messageData, _signature);}return EIP1271_MAGIC_VALUE;}/**
contracts/handler/HandlerContext.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title Handler Context - Allows the fallback handler to extract addition context from the calldata* @dev The fallback manager appends the following context to the calldata:* 1. Fallback manager caller address (non-padded)* based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/f8cc8b844a9f92f63dc55aa581f7d643a1bc5ac1/contracts/metatx/ERC2771Context.sol* @author Richard Meissner - @rmeissner*/abstract contract HandlerContext {/*** @notice Allows fetching the original caller address.* @dev This is only reliable in combination with a FallbackManager that supports this (e.g. Safe contract >=1.3.0).* When using this functionality make sure that the linked _manager (aka msg.sender) supports this.* This function does not rely on a trusted forwarder. Use the returned value only to* check information against the calling manager.* @return sender Original caller address.*/function _msgSender() internal pure returns (address sender) {// The assembly code is more direct than the Solidity version using `abi.decode`.// solhint-disable-next-line no-inline-assemblyassembly {sender := shr(96, calldataload(sub(calldatasize(), 20)))}}/*** @notice Returns the FallbackManager address* @return Fallback manager address*/function _manager() internal view returns (address) {return msg.sender;}}
contracts/handler/TokenCallbackHandler.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../interfaces/ERC1155TokenReceiver.sol";import "../interfaces/ERC721TokenReceiver.sol";import "../interfaces/ERC777TokensRecipient.sol";import "../interfaces/IERC165.sol";/*** @title Default Callback Handler - Handles supported tokens' callbacks, allowing Safes receiving these tokens.* @author Richard Meissner - @rmeissner*/contract TokenCallbackHandler is ERC1155TokenReceiver, ERC777TokensRecipient, ERC721TokenReceiver, IERC165 {/*** @notice Handles ERC1155 Token callback.* return Standardized onERC1155Received return value.*/function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure override returns (bytes4) {return 0xf23a6e61;}/*** @notice Handles ERC1155 Token batch callback.* return Standardized onERC1155BatchReceived return value.*/function onERC1155BatchReceived(address,address,uint256[] calldata,uint256[] calldata,bytes calldata) external pure override returns (bytes4) {return 0xbc197c81;}/*** @notice Handles ERC721 Token callback.* return Standardized onERC721Received return value.*/function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) {return 0x150b7a02;
contracts/common/SelfAuthorized.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title SelfAuthorized - Authorizes current contract to perform actions to itself.* @author Richard Meissner - @rmeissner*/abstract contract SelfAuthorized {function requireSelfCall() private view {require(msg.sender == address(this), "GS031");}modifier authorized() {// Modifiers are copied around during compilation. This is a function call as it minimized the bytecode sizerequireSelfCall();_;}}
contracts/examples/libraries/Migrate_1_3_0_to_1_2_0.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../../libraries/SafeStorage.sol";/*** @title Migration - Migrates a Safe contract from 1.3.0 to 1.2.0* @author Richard Meissner - @rmeissner*/contract Migration is SafeStorage {bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x035aff83d86937d35b32e04f0ddc6ff469290eef2f1b692d8a815c89404d4749;address public immutable migrationSingleton;address public immutable safe120Singleton;constructor(address targetSingleton) {// Singleton address cannot be zero address.require(targetSingleton != address(0), "Invalid singleton address provided");safe120Singleton = targetSingleton;migrationSingleton = address(this);}event ChangedMasterCopy(address singleton);/*** @notice Migrates the Safe to the Singleton contract at `migrationSingleton`.* @dev This can only be called via a delegatecall.*/function migrate() public {require(address(this) != migrationSingleton, "Migration should only be called via delegatecall");singleton = safe120Singleton;_deprecatedDomainSeparator = keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, this));emit ChangedMasterCopy(singleton);}}
contracts/common/SecuredTokenTransfer.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title SecuredTokenTransfer - Secure token transfer.* @author Richard Meissner - @rmeissner*/abstract contract SecuredTokenTransfer {/*** @notice Transfers a token and returns a boolean if it was a success* @dev It checks the return data of the transfer call and returns true if the transfer was successful.* It doesn't check if the `token` address is a contract or not.* @param token Token that should be transferred* @param receiver Receiver to whom the token should be transferred* @param amount The amount of tokens that should be transferred* @return transferred Returns true if the transfer was successful*/function transferToken(address token, address receiver, uint256 amount) internal returns (bool transferred) {// 0xa9059cbb - keccack("transfer(address,uint256)")bytes memory data = abi.encodeWithSelector(0xa9059cbb, receiver, amount);// solhint-disable-next-line no-inline-assemblyassembly {// We write the return value to scratch space.// See https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memorylet success := call(sub(gas(), 10000), token, 0, add(data, 0x20), mload(data), 0, 0x20)switch returndatasize()case 0 {transferred := success}case 0x20 {transferred := iszero(or(iszero(success), iszero(mload(0))))}default {transferred := 0}}}}
contracts/SafeL2.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "./Safe.sol";/*** @title SafeL2 - An implementation of the Safe contract that emits additional events on transaction executions.* @notice For a more complete description of the Safe contract, please refer to the main Safe contract `Safe.sol`.* @author Stefan George - @Georgi87* @author Richard Meissner - @rmeissner*/contract SafeL2 is Safe {event SafeMultiSigTransaction(address to,uint256 value,bytes data,Enum.Operation operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address payable refundReceiver,bytes signatures,// We combine nonce, sender and threshold into one to avoid stack too deep// Dev note: additionalInfo should not contain `bytes`, as this complicates decodingbytes additionalInfo);event SafeModuleTransaction(address module, address to, uint256 value, bytes data, Enum.Operation operation);// @inheritdoc Safefunction execTransaction(address to,uint256 value,bytes calldata data,Enum.Operation operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address payable refundReceiver,
contracts/accessors/SimulateTxAccessor.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../base/Executor.sol";/*** @title Simulate Transaction Accessor.* @notice Can be used with StorageAccessible to simulate Safe transactions.* @author Richard Meissner - @rmeissner*/contract SimulateTxAccessor is Executor {address private immutable accessorSingleton;constructor() {accessorSingleton = address(this);}/*** @notice Modifier to make a function callable via delegatecall only.* If the function is called via a regular call, it will revert.*/modifier onlyDelegateCall() {require(address(this) != accessorSingleton, "SimulateTxAccessor should only be called via delegatecall");_;}/*** @notice Simulates a Safe transaction and returns the used gas, success boolean and the return data.* @dev Executes the specified operation {Call, DelegateCall} and returns operation-specific data.* Has to be called via delegatecall.* This returns the data equal to `abi.encode(uint256(etimate), bool(success), bytes(returnData))`.* Specifically, the returndata will be:* `estimate:uint256 || success:bool || returnData.length:uint256 || returnData:bytes`.* @param to Destination address .* @param value Native token value.* @param data Data payload.* @param operation Operation type {Call, DelegateCall}.* @return estimate Gas used.* @return success Success boolean value.* @return returnData Return data.*/
contracts/base/Executor.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../common/Enum.sol";/*** @title Executor - A contract that can execute transactions* @author Richard Meissner - @rmeissner*/abstract contract Executor {/*** @notice Executes either a delegatecall or a call with provided parameters.* @dev This method doesn't perform any sanity check of the transaction, such as:* - if the contract at `to` address has code or not* It is the responsibility of the caller to perform such checks.* @param to Destination address.* @param value Ether value.* @param data Data payload.* @param operation Operation type.* @return success boolean flag indicating if the call succeeded.*/function execute(address to,uint256 value,bytes memory data,Enum.Operation operation,uint256 txGas) internal returns (bool success) {if (operation == Enum.Operation.DelegateCall) {// solhint-disable-next-line no-inline-assemblyassembly {success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)}} else {// solhint-disable-next-line no-inline-assemblyassembly {success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)}}}}
contracts/test/4337/Test4337ModuleAndHandler.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;pragma abicoder v2;import "../../libraries/SafeStorage.sol";struct UserOperation {address sender;uint256 nonce;bytes initCode;bytes callData;uint256 callGasLimit;uint256 verificationGasLimit;uint256 preVerificationGas;uint256 maxFeePerGas;uint256 maxPriorityFeePerGas;bytes paymasterAndData;bytes signature;}interface ISafe {function execTransactionFromModule(address to, uint256 value, bytes memory data, uint8 operation) external returns (bool success);}/// @dev A Dummy 4337 Module/Handler for testing purposes/// ⚠️ ⚠️ ⚠️ DO NOT USE IN PRODUCTION ⚠️ ⚠️ ⚠️/// The module does not perform ANY validation, it just executes validateUserOp and execTransaction/// to perform the opcode level compliance by the bundler.contract Test4337ModuleAndHandler is SafeStorage {address public immutable myAddress;address public immutable entryPoint;address internal constant SENTINEL_MODULES = address(0x1);constructor(address entryPointAddress) {entryPoint = entryPointAddress;myAddress = address(this);}function validateUserOp(UserOperation calldata userOp, bytes32, uint256 missingAccountFunds) external returns (uint256 validationData) {address payable safeAddress = payable(userOp.sender);
contracts/test/ERC1155Token.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../interfaces/ERC1155TokenReceiver.sol";import "../external/SafeMath.sol";/*** @title ERC1155Token - A test ERC1155 token contract*/contract ERC1155Token {using SafeMath for uint256;// Mapping from token ID to owner balancesmapping(uint256 => mapping(address => uint256)) private _balances;// Mapping from owner to operator approvalsmapping(address => mapping(address => bool)) private _operatorApprovals;/*** @dev Get the specified address' balance for token with specified ID.* @param owner The address of the token holder* @param id ID of the token* @return The owner's balance of the token type requested*/function balanceOf(address owner, uint256 id) public view returns (uint256) {require(owner != address(0), "ERC1155: balance query for the zero address");return _balances[id][owner];}/*** @notice Transfers `value` amount of an `id` from the `from` address to the `to` address specified.* Caller must be approved to manage the tokens being transferred out of the `from` account.* If `to` is a smart contract, will call `onERC1155Received` on `to` and act appropriately.* @param from Source address* @param to Target address* @param id ID of the token type* @param value Transfer amount* @param data Data forwarded to `onERC1155Received` if `to` is a contract receiver*/function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external {require(to != address(0), "ERC1155: target address must be non-zero");
contracts/interfaces/ViewStorageAccessible.sol
pragma solidity >=0.5.0 <0.9.0;/// @title ViewStorageAccessible - Interface on top of StorageAccessible base class to allow simulations from view functions./// @notice Adjusted version of https://github.com/gnosis/util-contracts/blob/3db1e531cb243a48ea91c60a800d537c1000612a/contracts/StorageAccessible.solinterface ViewStorageAccessible {/*** @dev Same as `simulate` on StorageAccessible. Marked as view so that it can be called from external contracts* that want to run simulations from within view functions. Will revert if the invoked simulation attempts to change state.*/function simulate(address targetContract, bytes calldata calldataPayload) external view returns (bytes memory);}
contracts/examples/guards/DelegateCallTransactionGuard.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../../common/Enum.sol";import "../../base/GuardManager.sol";import "../../Safe.sol";/*** @title DelegateCallTransactionGuard - Limits delegate calls to a specific target.* @author Richard Meissner - @rmeissner*/contract DelegateCallTransactionGuard is BaseGuard {address public immutable allowedTarget;constructor(address target) {allowedTarget = target;}// solhint-disable-next-line payable-fallbackfallback() external {// We don't revert on fallback to avoid issues in case of a Safe upgrade// E.g. The expected check method might change and then the Safe would be locked.}/*** @notice Called by the Safe contract before a transaction is executed.* @dev Reverts if the transaction is a delegate call to contract other than the allowed one.* @param to Destination address of Safe transaction.* @param operation Operation type of Safe transaction.*/function checkTransaction(address to,uint256,bytes memory,Enum.Operation operation,uint256,uint256,uint256,address,// solhint-disable-next-line no-unused-varsaddress payable,
contracts/interfaces/ERC721TokenReceiver.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.interface ERC721TokenReceiver {/*** @notice Handle the receipt of an NFT* @dev The ERC721 smart contract calls this function on the recipient* after a `transfer`. This function MAY throw to revert and reject the* transfer. Return of other than the magic value MUST result in the* transaction being reverted.* Note: the contract address is always the message sender.* @param _operator The address which called `safeTransferFrom` function.* @param _from The address which previously owned the token.* @param _tokenId The NFT identifier which is being transferred.* @param _data Additional data with no specified format.* @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.* unless throwing*/function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns (bytes4);}
contracts/interfaces/IERC165.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/// @notice More details at https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.solinterface IERC165 {/*** @dev Returns true if this contract implements the interface defined by `interfaceId`.* See the corresponding EIP section* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified* to learn more about how these ids are created.** This function call must use less than 30 000 gas.*/function supportsInterface(bytes4 interfaceId) external view returns (bool);}
contracts/common/NativeCurrencyPaymentFallback.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title NativeCurrencyPaymentFallback - A contract that has a fallback to accept native currency payments.* @author Richard Meissner - @rmeissner*/abstract contract NativeCurrencyPaymentFallback {event SafeReceived(address indexed sender, uint256 value);/*** @notice Receive function accepts native currency transactions.* @dev Emits an event with sender and received value.*/receive() external payable {emit SafeReceived(msg.sender, msg.value);}}
contracts/common/StorageAccessible.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title StorageAccessible - A generic base contract that allows callers to access all internal storage.* @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol* It removes a method from the original contract not needed for the Safe contracts.* @author Gnosis Developers*/abstract contract StorageAccessible {/*** @notice Reads `length` bytes of storage in the currents contract* @param offset - the offset in the current contract's storage in words to start reading from* @param length - the number of words (32 bytes) of data to read* @return the bytes that were read.*/function getStorageAt(uint256 offset, uint256 length) public view returns (bytes memory) {bytes memory result = new bytes(length * 32);for (uint256 index = 0; index < length; index++) {// solhint-disable-next-line no-inline-assemblyassembly {let word := sload(add(offset, index))mstore(add(add(result, 0x20), mul(index, 0x20)), word)}}return result;}/*** @dev Performs a delegatecall on a targetContract in the context of self.* Internally reverts execution to avoid side effects (making it static).** This method reverts with data equal to `abi.encode(bool(success), bytes(response))`.* Specifically, the `returndata` after a call to this method will be:* `success:bool || response.length:uint256 || response:bytes`.** @param targetContract Address of the contract containing the code to execute.* @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).*/function simulateAndRevert(address targetContract, bytes memory calldataPayload) external {// solhint-disable-next-line no-inline-assembly
contracts/external/SafeMath.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title SafeMath* @notice Math operations with safety checks that revert on error (overflow/underflow)*/library SafeMath {/*** @notice Multiplies two numbers, reverts on overflow.* @param a First number* @param b Second number* @return Product of a and b*/function mul(uint256 a, uint256 b) internal pure returns (uint256) {// Gas optimization: this is cheaper than requiring 'a' not being zero, but the// benefit is lost if 'b' is also tested.// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522if (a == 0) {return 0;}uint256 c = a * b;require(c / a == b);return c;}/*** @notice Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).* @param a First number* @param b Second number* @return Difference of a and b*/function sub(uint256 a, uint256 b) internal pure returns (uint256) {require(b <= a);uint256 c = a - b;return c;}
@openzeppelin/contracts/math/SafeMath.sol
// SPDX-License-Identifier: MITpragma solidity >=0.6.0 <0.8.0;/*** @dev Wrappers over Solidity's arithmetic operations with added overflow* checks.** Arithmetic operations in Solidity wrap on overflow. This can easily result* in bugs, because programmers usually assume that an overflow raises an* error, which is the standard behavior in high level programming languages.* `SafeMath` restores this intuition by reverting the transaction when an* operation overflows.** Using this library instead of the unchecked operations eliminates an entire* class of bugs, so it's recommended to use it always.*/library SafeMath {/*** @dev Returns the addition of two unsigned integers, with an overflow flag.** _Available since v3.4._*/function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {uint256 c = a + b;if (c < a) return (false, 0);return (true, c);}/*** @dev Returns the substraction of two unsigned integers, with an overflow flag.** _Available since v3.4._*/function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {if (b > a) return (false, 0);return (true, a - b);}/*** @dev Returns the multiplication of two unsigned integers, with an overflow flag.
contracts/base/GuardManager.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../common/Enum.sol";import "../common/SelfAuthorized.sol";import "../interfaces/IERC165.sol";interface Guard is IERC165 {function checkTransaction(address to,uint256 value,bytes memory data,Enum.Operation operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address payable refundReceiver,bytes memory signatures,address msgSender) external;function checkAfterExecution(bytes32 txHash, bool success) external;}abstract contract BaseGuard is Guard {function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {returninterfaceId == type(Guard).interfaceId || // 0xe6d7a83ainterfaceId == type(IERC165).interfaceId; // 0x01ffc9a7}}/*** @title Guard Manager - A contract managing transaction guards which perform pre and post-checks on Safe transactions.* @author Richard Meissner - @rmeissner*/abstract contract GuardManager is SelfAuthorized {event ChangedGuard(address indexed guard);// keccak256("guard_manager.guard.address")
contracts/interfaces/ERC1155TokenReceiver.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;// Note: The ERC-165 identifier for this interface is 0x4e2312e0.interface ERC1155TokenReceiver {/*** @notice Handle the receipt of a single ERC1155 token type.* @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.* This function MUST return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61) if it accepts the transfer.* This function MUST revert if it rejects the transfer.* Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.* @param _operator The address which initiated the transfer (i.e. msg.sender).* @param _from The address which previously owned the token.* @param _id The ID of the token being transferred.* @param _value The amount of tokens being transferred.* @param _data Additional data with no specified format.* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`.*/function onERC1155Received(address _operator,address _from,uint256 _id,uint256 _value,bytes calldata _data) external returns (bytes4);/*** @notice Handle the receipt of multiple ERC1155 token types.* @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.* This function MUST return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81) if it accepts the transfer(s).* This function MUST revert if it rejects the transfer(s).* Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.* @param _operator The address which initiated the batch transfer (i.e. msg.sender).* @param _from The address which previously owned the token.* @param _ids An array containing ids of each token being transferred (order and length must match _values array).* @param _values An array containing amounts of each token being transferred (order and length must match _ids array).* @param _data Additional data with no specified format.* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`.*/function onERC1155BatchReceived(address _operator,
contracts/base/ModuleManager.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../common/Enum.sol";import "../common/SelfAuthorized.sol";import "./Executor.sol";/*** @title Module Manager - A contract managing Safe modules* @notice Modules are extensions with unlimited access to a Safe that can be added to a Safe by its owners.⚠️ WARNING: Modules are a security risk since they can execute arbitrary transactions,so only trusted and audited modules should be added to a Safe. A malicious module cancompletely takeover a Safe.* @author Stefan George - @Georgi87* @author Richard Meissner - @rmeissner*/abstract contract ModuleManager is SelfAuthorized, Executor {event EnabledModule(address indexed module);event DisabledModule(address indexed module);event ExecutionFromModuleSuccess(address indexed module);event ExecutionFromModuleFailure(address indexed module);address internal constant SENTINEL_MODULES = address(0x1);mapping(address => address) internal modules;/*** @notice Setup function sets the initial storage of the contract.* Optionally executes a delegate call to another contract to setup the modules.* @param to Optional destination address of call to execute.* @param data Optional data of call to execute.*/function setupModules(address to, bytes memory data) internal {require(modules[SENTINEL_MODULES] == address(0), "GS100");modules[SENTINEL_MODULES] = SENTINEL_MODULES;if (to != address(0)) {require(isContract(to), "GS002");// Setup has to complete successfully or transaction fails.require(execute(to, 0, data, Enum.Operation.DelegateCall, type(uint256).max), "GS000");}}
contracts/libraries/CreateCall.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title Create Call - Allows to use the different create opcodes to deploy a contract.* @author Richard Meissner - @rmeissner* @notice This contract provides functions for deploying a new contract using the create and create2 opcodes.*/contract CreateCall {/// @notice Emitted when a new contract is createdevent ContractCreation(address indexed newContract);/*** @notice Deploys a new contract using the create2 opcode.* @param value The value in wei to be sent with the contract creation.* @param deploymentData The initialisation code of the contract to be created.* @param salt The salt value to use for the contract creation.* @return newContract The address of the newly created contract.*/function performCreate2(uint256 value, bytes memory deploymentData, bytes32 salt) public returns (address newContract) {// solhint-disable-next-line no-inline-assemblyassembly {newContract := create2(value, add(0x20, deploymentData), mload(deploymentData), salt)}require(newContract != address(0), "Could not deploy contract");emit ContractCreation(newContract);}/*** @notice Deploys a new contract using the create opcode.* @param value The value in wei to be sent with the contract creation.* @param deploymentData The initialisation code of the contract to be created.* @return newContract The address of the newly created contract.*/function performCreate(uint256 value, bytes memory deploymentData) public returns (address newContract) {// solhint-disable-next-line no-inline-assemblyassembly {newContract := create(value, add(deploymentData, 0x20), mload(deploymentData))}require(newContract != address(0), "Could not deploy contract");
contracts/base/OwnerManager.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../common/SelfAuthorized.sol";/*** @title OwnerManager - Manages Safe owners and a threshold to authorize transactions.* @dev Uses a linked list to store the owners because the code generate by the solidity compiler* is more efficient than using a dynamic array.* @author Stefan George - @Georgi87* @author Richard Meissner - @rmeissner*/abstract contract OwnerManager is SelfAuthorized {event AddedOwner(address indexed owner);event RemovedOwner(address indexed owner);event ChangedThreshold(uint256 threshold);address internal constant SENTINEL_OWNERS = address(0x1);mapping(address => address) internal owners;uint256 internal ownerCount;uint256 internal threshold;/*** @notice Sets the initial storage of the contract.* @param _owners List of Safe owners.* @param _threshold Number of required confirmations for a Safe transaction.*/function setupOwners(address[] memory _owners, uint256 _threshold) internal {// Threshold can only be 0 at initialization.// Check ensures that setup function can only be called once.require(threshold == 0, "GS200");// Validate that threshold is smaller than number of added owners.require(_threshold <= _owners.length, "GS201");// There has to be at least one Safe owner.require(_threshold >= 1, "GS202");// Initializing Safe owners.address currentOwner = SENTINEL_OWNERS;for (uint256 i = 0; i < _owners.length; i++) {// Owner address cannot be null.address owner = _owners[i];require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this) && currentOwner != owner, "GS203");
contracts/test/ERC20Token.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.6.0 <0.8.0;import "@openzeppelin/contracts/token/ERC20/ERC20.sol";/*** @title ERC20Token* @dev This contract is an ERC20 token contract that extends the OpenZeppelin ERC20 contract.*/contract ERC20Token is ERC20 {/*** @dev Constructor that sets the name and symbol of the token and mints an initial supply to the contract deployer.*/constructor() public ERC20("TestToken", "TT") {_mint(msg.sender, 1000000000000000);}}
contracts/libraries/MultiSend.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title Multi Send - Allows to batch multiple transactions into one.* @author Nick Dodson - <nick.dodson@consensys.net>* @author Gonçalo Sá - <goncalo.sa@consensys.net>* @author Stefan George - @Georgi87* @author Richard Meissner - @rmeissner*/contract MultiSend {address private immutable multisendSingleton;constructor() {multisendSingleton = address(this);}/*** @dev Sends multiple transactions and reverts all if one fails.* @param transactions Encoded transactions. Each transaction is encoded as a packed bytes of* operation as a uint8 with 0 for a call or 1 for a delegatecall (=> 1 byte),* to as a address (=> 20 bytes),* value as a uint256 (=> 32 bytes),* data length as a uint256 (=> 32 bytes),* data as bytes.* see abi.encodePacked for more information on packed encoding* @notice This method is payable as delegatecalls keep the msg.value from the previous call* If the calling method (e.g. execTransaction) received ETH this would revert otherwise*/function multiSend(bytes memory transactions) public payable {require(address(this) != multisendSingleton, "MultiSend should only be called via delegatecall");// solhint-disable-next-line no-inline-assemblyassembly {let length := mload(transactions)let i := 0x20for {// Pre block is not used in "while mode"} lt(i, length) {// Post block is not used in "while mode"} {// First byte of the data is the operation.
contracts/libraries/SafeStorage.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;/*** @title SafeStorage - Storage layout of the Safe contracts to be used in libraries.* @dev Should be always the first base contract of a library that is used with a Safe.* @author Richard Meissner - @rmeissner*/contract SafeStorage {// From /common/Singleton.soladdress internal singleton;// From /common/ModuleManager.solmapping(address => address) internal modules;// From /common/OwnerManager.solmapping(address => address) internal owners;uint256 internal ownerCount;uint256 internal threshold;// From /Safe.soluint256 internal nonce;bytes32 internal _deprecatedDomainSeparator;mapping(bytes32 => uint256) internal signedMessages;mapping(address => mapping(bytes32 => uint256)) internal approvedHashes;}
contracts/examples/guards/ReentrancyTransactionGuard.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../../common/Enum.sol";import "../../base/GuardManager.sol";import "../../Safe.sol";/*** @title ReentrancyTransactionGuard - Prevents reentrancy into the transaction execution function.* @author Richard Meissner - @rmeissner*/contract ReentrancyTransactionGuard is BaseGuard {bytes32 internal constant GUARD_STORAGE_SLOT = keccak256("reentrancy_guard.guard.struct");struct GuardValue {bool active;}// solhint-disable-next-line payable-fallbackfallback() external {// We don't revert on fallback to avoid issues in case of a Safe upgrade// E.g. The expected check method might change and then the Safe would be locked.}/*** @notice Returns the guard value for the current context.* @dev The guard value is stored in a slot that is unique to the contract instance and the function in which it is called.* @return guard The guard value.*/function getGuard() internal pure returns (GuardValue storage guard) {bytes32 slot = GUARD_STORAGE_SLOT;// solhint-disable-next-line no-inline-assemblyassembly {guard.slot := slot}}/*** @notice Called by the Safe contract before a transaction is executed.* @dev Reverts if reentrancy is detected.*/
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MITpragma solidity >=0.6.0 <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.*
contracts/base/FallbackManager.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../common/SelfAuthorized.sol";/*** @title Fallback Manager - A contract managing fallback calls made to this contract* @author Richard Meissner - @rmeissner*/abstract contract FallbackManager is SelfAuthorized {event ChangedFallbackHandler(address indexed handler);// keccak256("fallback_manager.handler.address")bytes32 internal constant FALLBACK_HANDLER_STORAGE_SLOT = 0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5;/*** @notice Internal function to set the fallback handler.* @param handler contract to handle fallback calls.*/function internalSetFallbackHandler(address handler) internal {/*If a fallback handler is set to self, then the following attack vector is opened:Imagine we have a function like this:function withdraw() internal authorized {withdrawalAddress.call.value(address(this).balance)("");}If the fallback method is triggered, the fallback handler appends the msg.sender address to the calldata and calls the fallback handler.A potential attacker could call a Safe with the 3 bytes signature of a withdraw function. Since 3 bytes do not create a valid signature,the call would end in a fallback handler. Since it appends the msg.sender address to the calldata, the attacker could craft an addresswhere the first 3 bytes of the previous calldata + the first byte of the address make up a valid function signature. The subsequent call would result in unsanctioned access to Safe's internal protected methods.For some reason, solidity matches the first 4 bytes of the calldata to a function signature, regardless if more data follow these 4 bytes.*/require(handler != address(this), "GS400");bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;// solhint-disable-next-line no-inline-assemblyassembly {sstore(slot, handler)}}
contracts/examples/guards/OnlyOwnersGuard.sol
// SPDX-License-Identifier: LGPL-3.0-onlypragma solidity >=0.7.0 <0.9.0;import "../../common/Enum.sol";import "../../base/GuardManager.sol";import "../../Safe.sol";interface ISafe {function getOwners() external view returns (address[] memory);}/*** @title OnlyOwnersGuard - Only allows owners to execute transactions.* @author Richard Meissner - @rmeissner*/contract OnlyOwnersGuard is BaseGuard {ISafe public safe;constructor() {}// solhint-disable-next-line payable-fallbackfallback() external {// We don't revert on fallback to avoid issues in case of a Safe upgrade// E.g. The expected check method might change and then the Safe would be locked.}/*** @notice Called by the Safe contract before a transaction is executed.* @dev Reverts if the transaction is not executed by an owner.* @param msgSender Executor of the transaction.*/function checkTransaction(address,uint256,bytes memory,Enum.Operation,uint256,uint256,uint256,address,// solhint-disable-next-line no-unused-vars
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"]}},"optimizer":{"runs":200,"enabled":false},"metadata":{"useLiteralContent":true},"libraries":{}}
Contract ABI
[{"type":"constructor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"VERSION","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addOwnerWithThreshold","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"uint256","name":"_threshold","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"approveHash","inputs":[{"type":"bytes32","name":"hashToApprove","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"approvedHashes","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeThreshold","inputs":[{"type":"uint256","name":"_threshold","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkNSignatures","inputs":[{"type":"bytes32","name":"dataHash","internalType":"bytes32"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"bytes","name":"signatures","internalType":"bytes"},{"type":"uint256","name":"requiredSignatures","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkSignatures","inputs":[{"type":"bytes32","name":"dataHash","internalType":"bytes32"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"bytes","name":"signatures","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"disableModule","inputs":[{"type":"address","name":"prevModule","internalType":"address"},{"type":"address","name":"module","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"domainSeparator","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"enableModule","inputs":[{"type":"address","name":"module","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"encodeTransactionData","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"},{"type":"uint256","name":"safeTxGas","internalType":"uint256"},{"type":"uint256","name":"baseGas","internalType":"uint256"},{"type":"uint256","name":"gasPrice","internalType":"uint256"},{"type":"address","name":"gasToken","internalType":"address"},{"type":"address","name":"refundReceiver","internalType":"address"},{"type":"uint256","name":"_nonce","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bool","name":"success","internalType":"bool"}],"name":"execTransaction","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"},{"type":"uint256","name":"safeTxGas","internalType":"uint256"},{"type":"uint256","name":"baseGas","internalType":"uint256"},{"type":"uint256","name":"gasPrice","internalType":"uint256"},{"type":"address","name":"gasToken","internalType":"address"},{"type":"address","name":"refundReceiver","internalType":"address payable"},{"type":"bytes","name":"signatures","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"success","internalType":"bool"}],"name":"execTransactionFromModule","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}],"name":"execTransactionFromModuleReturnData","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getChainId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"array","internalType":"address[]"},{"type":"address","name":"next","internalType":"address"}],"name":"getModulesPaginated","inputs":[{"type":"address","name":"start","internalType":"address"},{"type":"uint256","name":"pageSize","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getOwners","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"getStorageAt","inputs":[{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"length","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getThreshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getTransactionHash","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"},{"type":"uint256","name":"safeTxGas","internalType":"uint256"},{"type":"uint256","name":"baseGas","internalType":"uint256"},{"type":"uint256","name":"gasPrice","internalType":"uint256"},{"type":"address","name":"gasToken","internalType":"address"},{"type":"address","name":"refundReceiver","internalType":"address"},{"type":"uint256","name":"_nonce","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isModuleEnabled","inputs":[{"type":"address","name":"module","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nonce","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeOwner","inputs":[{"type":"address","name":"prevOwner","internalType":"address"},{"type":"address","name":"owner","internalType":"address"},{"type":"uint256","name":"_threshold","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFallbackHandler","inputs":[{"type":"address","name":"handler","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setGuard","inputs":[{"type":"address","name":"guard","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setup","inputs":[{"type":"address[]","name":"_owners","internalType":"address[]"},{"type":"uint256","name":"_threshold","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"address","name":"fallbackHandler","internalType":"address"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"uint256","name":"payment","internalType":"uint256"},{"type":"address","name":"paymentReceiver","internalType":"address payable"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signedMessages","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"simulateAndRevert","inputs":[{"type":"address","name":"targetContract","internalType":"address"},{"type":"bytes","name":"calldataPayload","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapOwner","inputs":[{"type":"address","name":"prevOwner","internalType":"address"},{"type":"address","name":"oldOwner","internalType":"address"},{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"event","name":"AddedOwner","inputs":[{"type":"address","name":"owner","indexed":true}],"anonymous":false},{"type":"event","name":"ApproveHash","inputs":[{"type":"bytes32","name":"approvedHash","indexed":true},{"type":"address","name":"owner","indexed":true}],"anonymous":false},{"type":"event","name":"ChangedFallbackHandler","inputs":[{"type":"address","name":"handler","indexed":true}],"anonymous":false},{"type":"event","name":"ChangedGuard","inputs":[{"type":"address","name":"guard","indexed":true}],"anonymous":false},{"type":"event","name":"ChangedThreshold","inputs":[{"type":"uint256","name":"threshold","indexed":false}],"anonymous":false},{"type":"event","name":"DisabledModule","inputs":[{"type":"address","name":"module","indexed":true}],"anonymous":false},{"type":"event","name":"EnabledModule","inputs":[{"type":"address","name":"module","indexed":true}],"anonymous":false},{"type":"event","name":"ExecutionFailure","inputs":[{"type":"bytes32","name":"txHash","indexed":true},{"type":"uint256","name":"payment","indexed":false}],"anonymous":false},{"type":"event","name":"ExecutionFromModuleFailure","inputs":[{"type":"address","name":"module","indexed":true}],"anonymous":false},{"type":"event","name":"ExecutionFromModuleSuccess","inputs":[{"type":"address","name":"module","indexed":true}],"anonymous":false},{"type":"event","name":"ExecutionSuccess","inputs":[{"type":"bytes32","name":"txHash","indexed":true},{"type":"uint256","name":"payment","indexed":false}],"anonymous":false},{"type":"event","name":"RemovedOwner","inputs":[{"type":"address","name":"owner","indexed":true}],"anonymous":false},{"type":"event","name":"SafeReceived","inputs":[{"type":"address","name":"sender","indexed":true},{"type":"uint256","name":"value","indexed":false}],"anonymous":false},{"type":"event","name":"SafeSetup","inputs":[{"type":"address","name":"initiator","indexed":true},{"type":"address[]","name":"owners","indexed":false},{"type":"uint256","name":"threshold","indexed":false},{"type":"address","name":"initializer","indexed":false},{"type":"address","name":"fallbackHandler","indexed":false}],"anonymous":false},{"type":"event","name":"SignMsg","inputs":[{"type":"bytes32","name":"msgHash","indexed":true}],"anonymous":false},{"type":"receive"},{"type":"fallback"}]
Contract Creation Code
0x608060405234801561001057600080fd5b506001600481905550615c1b80620000296000396000f3fe6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a03231461156b578063f698da25146115bc578063f8dc5dd9146115e7578063ffa1ad741461166257610226565b8063e19a9dd9146112bf578063e318b52b14611310578063e75235b8146113a1578063e86637db146113cc57610226565b8063cc2f8452116100d1578063cc2f84521461100c578063d4d9bdcd146110d9578063d8d11f7814611114578063e009cfde1461124e57610226565b8063affed0e014610d89578063b4faba0914610db4578063b63e800d14610e9c57610226565b80635624b25b1161016f5780636a7612021161013e5780636a761202146109895780637d83297414610b45578063934f3a1114610bb4578063a0e67e2b14610d1d57610226565b80635624b25b146107f05780635ae6bd37146108ae578063610b5925146108fd578063694e80c31461094e57610226565b80632f54bf6e116101ab5780632f54bf6e146104c85780633408e4701461052f578063468721a71461055a5780635229073f1461066f57610226565b80630d582f131461029357806312fb68e0146102ee5780632d9ad53d1461046157610226565b36610226573373ffffffffffffffffffffffffffffffffffffffff167f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d346040518082815260200191505060405180910390a2005b34801561023257600080fd5b5060007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b905080548061026757600080f35b36600080373360601b365260008060143601600080855af13d6000803e8061028e573d6000fd5b3d6000f35b34801561029f57600080fd5b506102ec600480360360408110156102b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506116f2565b005b3480156102fa57600080fd5b5061045f6004803603608081101561031157600080fd5b81019080803590602001909291908035906020019064010000000081111561033857600080fd5b82018360208201111561034a57600080fd5b8035906020019184600183028401116401000000008311171561036c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001906401000000008111156103cf57600080fd5b8201836020820111156103e157600080fd5b8035906020019184600183028401116401000000008311171561040357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190505050611ad8565b005b34801561046d57600080fd5b506104b06004803603602081101561048457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506123d6565b60405180821515815260200191505060405180910390f35b3480156104d457600080fd5b50610517600480360360208110156104eb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506124a8565b60405180821515815260200191505060405180910390f35b34801561053b57600080fd5b5061054461257a565b6040518082815260200191505060405180910390f35b34801561056657600080fd5b506106576004803603608081101561057d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156105c457600080fd5b8201836020820111156105d657600080fd5b803590602001918460018302840111640100000000831117156105f857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff169060200190929190505050612587565b60405180821515815260200191505060405180910390f35b34801561067b57600080fd5b5061076c6004803603608081101561069257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156106d957600080fd5b8201836020820111156106eb57600080fd5b8035906020019184600183028401116401000000008311171561070d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff16906020019092919050505061278d565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107b4578082015181840152602081019050610799565b50505050905090810190601f1680156107e15780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156107fc57600080fd5b506108336004803603604081101561081357600080fd5b8101908080359060200190929190803590602001909291905050506127c3565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610873578082015181840152602081019050610858565b50505050905090810190601f1680156108a05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156108ba57600080fd5b506108e7600480360360208110156108d157600080fd5b810190808035906020019092919050505061284a565b6040518082815260200191505060405180910390f35b34801561090957600080fd5b5061094c6004803603602081101561092057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612862565b005b34801561095a57600080fd5b506109876004803603602081101561097157600080fd5b8101908080359060200190929190505050612bea565b005b610b2d60048036036101408110156109a057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109e757600080fd5b8201836020820111156109f957600080fd5b80359060200191846001830284011164010000000083111715610a1b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610aa757600080fd5b820183602082011115610ab957600080fd5b80359060200191846001830284011164010000000083111715610adb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612d24565b60405180821515815260200191505060405180910390f35b348015610b5157600080fd5b50610b9e60048036036040811015610b6857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613253565b6040518082815260200191505060405180910390f35b348015610bc057600080fd5b50610d1b60048036036060811015610bd757600080fd5b810190808035906020019092919080359060200190640100000000811115610bfe57600080fd5b820183602082011115610c1057600080fd5b80359060200191846001830284011164010000000083111715610c3257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190640100000000811115610c9557600080fd5b820183602082011115610ca757600080fd5b80359060200191846001830284011164010000000083111715610cc957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050613278565b005b348015610d2957600080fd5b50610d32613307565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610d75578082015181840152602081019050610d5a565b505050509050019250505060405180910390f35b348015610d9557600080fd5b50610d9e6134b0565b6040518082815260200191505060405180910390f35b348015610dc057600080fd5b50610e9a60048036036040811015610dd757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610e1457600080fd5b820183602082011115610e2657600080fd5b80359060200191846001830284011164010000000083111715610e4857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506134b6565b005b348015610ea857600080fd5b5061100a6004803603610100811015610ec057600080fd5b8101908080359060200190640100000000811115610edd57600080fd5b820183602082011115610eef57600080fd5b80359060200191846020830284011164010000000083111715610f1157600080fd5b909192939192939080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610f5c57600080fd5b820183602082011115610f6e57600080fd5b80359060200191846001830284011164010000000083111715610f9057600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134d8565b005b34801561101857600080fd5b506110656004803603604081101561102f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613696565b60405180806020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019060200280838360005b838110156110c45780820151818401526020810190506110a9565b50505050905001935050505060405180910390f35b3480156110e557600080fd5b50611112600480360360208110156110fc57600080fd5b81019080803590602001909291905050506139f9565b005b34801561112057600080fd5b50611238600480360361014081101561113857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561117f57600080fd5b82018360208201111561119157600080fd5b803590602001918460018302840111640100000000831117156111b357600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613b98565b6040518082815260200191505060405180910390f35b34801561125a57600080fd5b506112bd6004803603604081101561127157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613bc5565b005b3480156112cb57600080fd5b5061130e600480360360208110156112e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613f4c565b005b34801561131c57600080fd5b5061139f6004803603606081101561133357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614138565b005b3480156113ad57600080fd5b506113b6614796565b6040518082815260200191505060405180910390f35b3480156113d857600080fd5b506114f060048036036101408110156113f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561143757600080fd5b82018360208201111561144957600080fd5b8035906020019184600183028401116401000000008311171561146b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506147a0565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611530578082015181840152602081019050611515565b50505050905090810190601f16801561155d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561157757600080fd5b506115ba6004803603602081101561158e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614948565b005b3480156115c857600080fd5b506115d161499f565b6040518082815260200191505060405180910390f35b3480156115f357600080fd5b506116606004803603606081101561160a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614a1d565b005b34801561166e57600080fd5b50611677614e46565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156116b757808201518184015260208101905061169c565b50505050905090810190601f1680156116e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6116fa614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156117645750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561179c57503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b61180e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461190f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506003600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a28060045414611ad457611ad381612bea565b5b5050565b611aec604182614f2290919063ffffffff16565b82511015611b62576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000808060008060005b868110156123ca57611b7e8882614f5c565b80945081955082965050505060008460ff1614156120035789898051906020012014611c12576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323700000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8260001c9450611c2c604188614f2290919063ffffffff16565b8260001c1015611ca4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8751611cbd60208460001c614f8b90919063ffffffff16565b1115611d31576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006020838a01015190508851611d6782611d5960208760001c614f8b90919063ffffffff16565b614f8b90919063ffffffff16565b1115611ddb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60606020848b010190506320c13b0b60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168773ffffffffffffffffffffffffffffffffffffffff166320c13b0b8d846040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b83811015611e7d578082015181840152602081019050611e62565b50505050905090810190601f168015611eaa5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015611ee3578082015181840152602081019050611ec8565b50505050905090810190601f168015611f105780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015611f2f57600080fd5b505afa158015611f43573d6000803e3d6000fd5b505050506040513d6020811015611f5957600080fd5b81019080805190602001909291905050507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611ffc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5050612248565b60018460ff161415612117578260001c94508473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120a057506000600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008c81526020019081526020016000205414155b612112576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b612247565b601e8460ff1611156121df5760018a60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c018281526020019150506040516020818303038152906040528051906020012060048603858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156121ce573d6000803e3d6000fd5b505050602060405103519450612246565b60018a85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612239573d6000803e3d6000fd5b5050506020604051035194505b5b5b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1611801561230f5750600073ffffffffffffffffffffffffffffffffffffffff16600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b80156123485750600173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b6123ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8495508080600101915050611b6c565b50505050505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff16141580156124a15750600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156125735750600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000804690508091505090565b6000600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156126525750600073ffffffffffffffffffffffffffffffffffffffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b6126c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6126f1858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b90508015612741573373ffffffffffffffffffffffffffffffffffffffff167f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb860405160405180910390a2612785565b3373ffffffffffffffffffffffffffffffffffffffff167facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37560405160405180910390a25b949350505050565b6000606061279d86868686612587565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060006020830267ffffffffffffffff811180156127e157600080fd5b506040519080825280601f01601f1916602001820160405280156128145781602001600182028036833780820191505090505b50905060005b8381101561283f5780850154806020830260208501015250808060010191505061281a565b508091505092915050565b60076020528060005260406000206000915090505481565b61286a614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156128d45750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b612946576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844060405160405180910390a250565b612bf2614e7f565b600354811115612c6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001811015612ce1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b806004819055507f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c936004546040518082815260200191505060405180910390a150565b6000806000612d3e8e8e8e8e8e8e8e8e8e8e6005546147a0565b905060056000815480929190600101919050555080805190602001209150612d67828286613278565b506000612d72614ff6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612f58578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b8152600401808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c8152602001806020018a6001811115612e1557fe5b81526020018981526020018881526020018781526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff168152602001806020018473ffffffffffffffffffffffffffffffffffffffff16815260200183810383528d8d82818152602001925080828437600081840152601f19601f820116905080830192505050838103825285818151815260200191508051906020019080838360005b83811015612ee7578082015181840152602081019050612ecc565b50505050905090810190601f168015612f145780820380516001836020036101000a031916815260200191505b509e505050505050505050505050505050600060405180830381600087803b158015612f3f57600080fd5b505af1158015612f53573d6000803e3d6000fd5b505050505b6101f4612f7f6109c48b01603f60408d0281612f7057fe5b0461502790919063ffffffff16565b015a1015612ff5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60005a905061305e8f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e60008d14613053578e613059565b6109c45a035b614faa565b93506130735a8261504190919063ffffffff16565b90508380613082575060008a14155b8061308e575060008814155b613100576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008089111561311a57613117828b8b8b8b615061565b90505b841561315d57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e826040518082815260200191505060405180910390a2613196565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040518082815260200191505060405180910390a25b5050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614613242578073ffffffffffffffffffffffffffffffffffffffff16639327136883856040518363ffffffff1660e01b815260040180838152602001821515815260200192505050600060405180830381600087803b15801561322957600080fd5b505af115801561323d573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b6008602052816000526040600020602052806000526040600020600091509150505481565b60006004549050600081116132f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61330184848484611ad8565b50505050565b6060600060035467ffffffffffffffff8111801561332457600080fd5b506040519080825280602002602001820160405280156133535781602001602082028036833780820191505090505b50905060008060026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146134a757808383815181106133fe57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081806001019250506133bd565b82935050505090565b60055481565b600080825160208401855af4806000523d6020523d600060403e60403d016000fd5b6135238a8a80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505089615267565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146135615761356084615767565b5b6135af8787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050615838565b60008211156135c9576135c782600060018685615061565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b8960405180806020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281038252878782818152602001925060200280828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a250505050505050505050565b60606000600173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806136da57506136d9846123d6565b5b61374c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600083116137c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8267ffffffffffffffff811180156137d957600080fd5b506040519080825280602002602001820160405280156138085781602001602082028036833780820191505090505b5091506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156138da5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b80156138e557508381105b156139a057818382815181106138f757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508080600101915050613870565b600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146139ee578260018203815181106139e357fe5b602002602001015191505b808352509250929050565b600073ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415613afb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff16817ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c60405160405180910390a350565b6000613bad8c8c8c8c8c8c8c8c8c8c8c6147a0565b8051906020012090509b9a5050505050505050505050565b613bcd614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015613c375750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b613ca9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613da9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427660405160405180910390a25050565b613f54614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146140c6578073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77fe6d7a83a000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b15801561401857600080fd5b505afa15801561402c573d6000803e3d6000fd5b505050506040513d602081101561404257600080fd5b81019080805190602001909291905050506140c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475333303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b60007f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa260405160405180910390a25050565b614140614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156141aa5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156141e257503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b614254576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614355576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156143bf5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614431576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614531576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28073ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a2505050565b6000600454905090565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405180838380828437808301925050509250505060405180910390208c8c8c8c8c8c8c604051602001808c81526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a815260200189815260200188600181111561483157fe5b81526020018781526020018681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019b505050505050505050505050604051602081830303815290604052805190602001209050601960f81b600160f81b6148bd61499f565b8360405160200180857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101847effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018381526020018281526020019450505050506040516020818303038152906040529150509b9a5050505050505050505050565b614950614e7f565b61495981615767565b8073ffffffffffffffffffffffffffffffffffffffff167f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b060405160405180910390a250565b60007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921860001b6149cd61257a565b30604051602001808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405160208183030381529060405280519060200120905090565b614a25614e7f565b806001600354031015614aa0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015614b0a5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614b7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614c7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360008154809291906001900391905055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28060045414614e4157614e4081612bea565b5b505050565b6040518060400160405280600581526020017f312e342e3100000000000000000000000000000000000000000000000000000081525081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614f20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b600080831415614f355760009050614f56565b6000828402905082848281614f4657fe5b0414614f5157600080fd5b809150505b92915050565b60008060008360410260208101860151925060408101860151915060ff60418201870151169350509250925092565b600080828401905083811015614fa057600080fd5b8091505092915050565b6000600180811115614fb857fe5b836001811115614fc457fe5b1415614fdd576000808551602087018986f49050614fed565b600080855160208701888a87f190505b95945050505050565b6000807f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b9050805491505090565b6000818310156150375781615039565b825b905092915050565b60008282111561505057600080fd5b600082840390508091505092915050565b600080600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461509e57826150a0565b325b9050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156151b85761510a3a86106150e7573a6150e9565b855b6150fc888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050506151b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61525d565b6151dd856151cf888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91506151ea848284615b0e565b61525c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5095945050505050565b6000600454146152df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8151811115615356576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60018110156153cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006001905060005b83518110156156d35760008482815181106153ed57fe5b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156154615750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561549957503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156154d157508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b615543576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614615644576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508092505080806001019150506153d6565b506001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550825160038190555081600481905550505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415615809576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475334303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b90508181555050565b600073ffffffffffffffffffffffffffffffffffffffff1660016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461593a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001806000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614615b0a576159f682615bd2565b615a68576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b615a978260008360017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b615b09576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5050565b60008063a9059cbb8484604051602401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050602060008251602084016000896127105a03f13d60008114615bb55760208114615bbd5760009350615bc8565b819350615bc8565b600051158215171593505b5050509392505050565b600080823b90506000811191505091905056fea264697066735822122057398fa72884cf9a6cb78aab2fb58a6b927f0e9d97d75b015daaee0959a153bf64736f6c63430007060033
Deployed ByteCode
0x6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a03231461156b578063f698da25146115bc578063f8dc5dd9146115e7578063ffa1ad741461166257610226565b8063e19a9dd9146112bf578063e318b52b14611310578063e75235b8146113a1578063e86637db146113cc57610226565b8063cc2f8452116100d1578063cc2f84521461100c578063d4d9bdcd146110d9578063d8d11f7814611114578063e009cfde1461124e57610226565b8063affed0e014610d89578063b4faba0914610db4578063b63e800d14610e9c57610226565b80635624b25b1161016f5780636a7612021161013e5780636a761202146109895780637d83297414610b45578063934f3a1114610bb4578063a0e67e2b14610d1d57610226565b80635624b25b146107f05780635ae6bd37146108ae578063610b5925146108fd578063694e80c31461094e57610226565b80632f54bf6e116101ab5780632f54bf6e146104c85780633408e4701461052f578063468721a71461055a5780635229073f1461066f57610226565b80630d582f131461029357806312fb68e0146102ee5780632d9ad53d1461046157610226565b36610226573373ffffffffffffffffffffffffffffffffffffffff167f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d346040518082815260200191505060405180910390a2005b34801561023257600080fd5b5060007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b905080548061026757600080f35b36600080373360601b365260008060143601600080855af13d6000803e8061028e573d6000fd5b3d6000f35b34801561029f57600080fd5b506102ec600480360360408110156102b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506116f2565b005b3480156102fa57600080fd5b5061045f6004803603608081101561031157600080fd5b81019080803590602001909291908035906020019064010000000081111561033857600080fd5b82018360208201111561034a57600080fd5b8035906020019184600183028401116401000000008311171561036c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001906401000000008111156103cf57600080fd5b8201836020820111156103e157600080fd5b8035906020019184600183028401116401000000008311171561040357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190505050611ad8565b005b34801561046d57600080fd5b506104b06004803603602081101561048457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506123d6565b60405180821515815260200191505060405180910390f35b3480156104d457600080fd5b50610517600480360360208110156104eb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506124a8565b60405180821515815260200191505060405180910390f35b34801561053b57600080fd5b5061054461257a565b6040518082815260200191505060405180910390f35b34801561056657600080fd5b506106576004803603608081101561057d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156105c457600080fd5b8201836020820111156105d657600080fd5b803590602001918460018302840111640100000000831117156105f857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff169060200190929190505050612587565b60405180821515815260200191505060405180910390f35b34801561067b57600080fd5b5061076c6004803603608081101561069257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156106d957600080fd5b8201836020820111156106eb57600080fd5b8035906020019184600183028401116401000000008311171561070d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff16906020019092919050505061278d565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107b4578082015181840152602081019050610799565b50505050905090810190601f1680156107e15780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156107fc57600080fd5b506108336004803603604081101561081357600080fd5b8101908080359060200190929190803590602001909291905050506127c3565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610873578082015181840152602081019050610858565b50505050905090810190601f1680156108a05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156108ba57600080fd5b506108e7600480360360208110156108d157600080fd5b810190808035906020019092919050505061284a565b6040518082815260200191505060405180910390f35b34801561090957600080fd5b5061094c6004803603602081101561092057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612862565b005b34801561095a57600080fd5b506109876004803603602081101561097157600080fd5b8101908080359060200190929190505050612bea565b005b610b2d60048036036101408110156109a057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109e757600080fd5b8201836020820111156109f957600080fd5b80359060200191846001830284011164010000000083111715610a1b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610aa757600080fd5b820183602082011115610ab957600080fd5b80359060200191846001830284011164010000000083111715610adb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612d24565b60405180821515815260200191505060405180910390f35b348015610b5157600080fd5b50610b9e60048036036040811015610b6857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613253565b6040518082815260200191505060405180910390f35b348015610bc057600080fd5b50610d1b60048036036060811015610bd757600080fd5b810190808035906020019092919080359060200190640100000000811115610bfe57600080fd5b820183602082011115610c1057600080fd5b80359060200191846001830284011164010000000083111715610c3257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190640100000000811115610c9557600080fd5b820183602082011115610ca757600080fd5b80359060200191846001830284011164010000000083111715610cc957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050613278565b005b348015610d2957600080fd5b50610d32613307565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610d75578082015181840152602081019050610d5a565b505050509050019250505060405180910390f35b348015610d9557600080fd5b50610d9e6134b0565b6040518082815260200191505060405180910390f35b348015610dc057600080fd5b50610e9a60048036036040811015610dd757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610e1457600080fd5b820183602082011115610e2657600080fd5b80359060200191846001830284011164010000000083111715610e4857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506134b6565b005b348015610ea857600080fd5b5061100a6004803603610100811015610ec057600080fd5b8101908080359060200190640100000000811115610edd57600080fd5b820183602082011115610eef57600080fd5b80359060200191846020830284011164010000000083111715610f1157600080fd5b909192939192939080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610f5c57600080fd5b820183602082011115610f6e57600080fd5b80359060200191846001830284011164010000000083111715610f9057600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134d8565b005b34801561101857600080fd5b506110656004803603604081101561102f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613696565b60405180806020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019060200280838360005b838110156110c45780820151818401526020810190506110a9565b50505050905001935050505060405180910390f35b3480156110e557600080fd5b50611112600480360360208110156110fc57600080fd5b81019080803590602001909291905050506139f9565b005b34801561112057600080fd5b50611238600480360361014081101561113857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561117f57600080fd5b82018360208201111561119157600080fd5b803590602001918460018302840111640100000000831117156111b357600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613b98565b6040518082815260200191505060405180910390f35b34801561125a57600080fd5b506112bd6004803603604081101561127157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613bc5565b005b3480156112cb57600080fd5b5061130e600480360360208110156112e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613f4c565b005b34801561131c57600080fd5b5061139f6004803603606081101561133357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614138565b005b3480156113ad57600080fd5b506113b6614796565b6040518082815260200191505060405180910390f35b3480156113d857600080fd5b506114f060048036036101408110156113f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561143757600080fd5b82018360208201111561144957600080fd5b8035906020019184600183028401116401000000008311171561146b57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506147a0565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611530578082015181840152602081019050611515565b50505050905090810190601f16801561155d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561157757600080fd5b506115ba6004803603602081101561158e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614948565b005b3480156115c857600080fd5b506115d161499f565b6040518082815260200191505060405180910390f35b3480156115f357600080fd5b506116606004803603606081101561160a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614a1d565b005b34801561166e57600080fd5b50611677614e46565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156116b757808201518184015260208101905061169c565b50505050905090810190601f1680156116e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6116fa614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156117645750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561179c57503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b61180e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461190f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506003600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a28060045414611ad457611ad381612bea565b5b5050565b611aec604182614f2290919063ffffffff16565b82511015611b62576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000808060008060005b868110156123ca57611b7e8882614f5c565b80945081955082965050505060008460ff1614156120035789898051906020012014611c12576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323700000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8260001c9450611c2c604188614f2290919063ffffffff16565b8260001c1015611ca4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8751611cbd60208460001c614f8b90919063ffffffff16565b1115611d31576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006020838a01015190508851611d6782611d5960208760001c614f8b90919063ffffffff16565b614f8b90919063ffffffff16565b1115611ddb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60606020848b010190506320c13b0b60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168773ffffffffffffffffffffffffffffffffffffffff166320c13b0b8d846040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b83811015611e7d578082015181840152602081019050611e62565b50505050905090810190601f168015611eaa5780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015611ee3578082015181840152602081019050611ec8565b50505050905090810190601f168015611f105780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015611f2f57600080fd5b505afa158015611f43573d6000803e3d6000fd5b505050506040513d6020811015611f5957600080fd5b81019080805190602001909291905050507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611ffc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5050612248565b60018460ff161415612117578260001c94508473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120a057506000600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008c81526020019081526020016000205414155b612112576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b612247565b601e8460ff1611156121df5760018a60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c018281526020019150506040516020818303038152906040528051906020012060048603858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156121ce573d6000803e3d6000fd5b505050602060405103519450612246565b60018a85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612239573d6000803e3d6000fd5b5050506020604051035194505b5b5b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1611801561230f5750600073ffffffffffffffffffffffffffffffffffffffff16600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b80156123485750600173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b6123ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8495508080600101915050611b6c565b50505050505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff16141580156124a15750600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156125735750600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000804690508091505090565b6000600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156126525750600073ffffffffffffffffffffffffffffffffffffffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b6126c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6126f1858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b90508015612741573373ffffffffffffffffffffffffffffffffffffffff167f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb860405160405180910390a2612785565b3373ffffffffffffffffffffffffffffffffffffffff167facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37560405160405180910390a25b949350505050565b6000606061279d86868686612587565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060006020830267ffffffffffffffff811180156127e157600080fd5b506040519080825280601f01601f1916602001820160405280156128145781602001600182028036833780820191505090505b50905060005b8381101561283f5780850154806020830260208501015250808060010191505061281a565b508091505092915050565b60076020528060005260406000206000915090505481565b61286a614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156128d45750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b612946576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844060405160405180910390a250565b612bf2614e7f565b600354811115612c6a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001811015612ce1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b806004819055507f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c936004546040518082815260200191505060405180910390a150565b6000806000612d3e8e8e8e8e8e8e8e8e8e8e6005546147a0565b905060056000815480929190600101919050555080805190602001209150612d67828286613278565b506000612d72614ff6565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612f58578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b8152600401808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c8152602001806020018a6001811115612e1557fe5b81526020018981526020018881526020018781526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff168152602001806020018473ffffffffffffffffffffffffffffffffffffffff16815260200183810383528d8d82818152602001925080828437600081840152601f19601f820116905080830192505050838103825285818151815260200191508051906020019080838360005b83811015612ee7578082015181840152602081019050612ecc565b50505050905090810190601f168015612f145780820380516001836020036101000a031916815260200191505b509e505050505050505050505050505050600060405180830381600087803b158015612f3f57600080fd5b505af1158015612f53573d6000803e3d6000fd5b505050505b6101f4612f7f6109c48b01603f60408d0281612f7057fe5b0461502790919063ffffffff16565b015a1015612ff5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60005a905061305e8f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e60008d14613053578e613059565b6109c45a035b614faa565b93506130735a8261504190919063ffffffff16565b90508380613082575060008a14155b8061308e575060008814155b613100576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008089111561311a57613117828b8b8b8b615061565b90505b841561315d57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e826040518082815260200191505060405180910390a2613196565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040518082815260200191505060405180910390a25b5050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614613242578073ffffffffffffffffffffffffffffffffffffffff16639327136883856040518363ffffffff1660e01b815260040180838152602001821515815260200192505050600060405180830381600087803b15801561322957600080fd5b505af115801561323d573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b6008602052816000526040600020602052806000526040600020600091509150505481565b60006004549050600081116132f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61330184848484611ad8565b50505050565b6060600060035467ffffffffffffffff8111801561332457600080fd5b506040519080825280602002602001820160405280156133535781602001602082028036833780820191505090505b50905060008060026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146134a757808383815181106133fe57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081806001019250506133bd565b82935050505090565b60055481565b600080825160208401855af4806000523d6020523d600060403e60403d016000fd5b6135238a8a80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505089615267565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146135615761356084615767565b5b6135af8787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050615838565b60008211156135c9576135c782600060018685615061565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b8960405180806020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281038252878782818152602001925060200280828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a250505050505050505050565b60606000600173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806136da57506136d9846123d6565b5b61374c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600083116137c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8267ffffffffffffffff811180156137d957600080fd5b506040519080825280602002602001820160405280156138085781602001602082028036833780820191505090505b5091506000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156138da5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b80156138e557508381105b156139a057818382815181106138f757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508080600101915050613870565b600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146139ee578260018203815181106139e357fe5b602002602001015191505b808352509250929050565b600073ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415613afb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff16817ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c60405160405180910390a350565b6000613bad8c8c8c8c8c8c8c8c8c8c8c6147a0565b8051906020012090509b9a5050505050505050505050565b613bcd614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015613c375750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b613ca9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613da9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427660405160405180910390a25050565b613f54614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146140c6578073ffffffffffffffffffffffffffffffffffffffff166301ffc9a77fe6d7a83a000000000000000000000000000000000000000000000000000000006040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b15801561401857600080fd5b505afa15801561402c573d6000803e3d6000fd5b505050506040513d602081101561404257600080fd5b81019080805190602001909291905050506140c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475333303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b60007f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa260405160405180910390a25050565b614140614e7f565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156141aa5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156141e257503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b614254576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614355576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156143bf5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614431576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614531576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28073ffffffffffffffffffffffffffffffffffffffff167f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2660405160405180910390a2505050565b6000600454905090565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405180838380828437808301925050509250505060405180910390208c8c8c8c8c8c8c604051602001808c81526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a815260200189815260200188600181111561483157fe5b81526020018781526020018681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019b505050505050505050505050604051602081830303815290604052805190602001209050601960f81b600160f81b6148bd61499f565b8360405160200180857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101847effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018381526020018281526020019450505050506040516020818303038152906040529150509b9a5050505050505050505050565b614950614e7f565b61495981615767565b8073ffffffffffffffffffffffffffffffffffffffff167f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b060405160405180910390a250565b60007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921860001b6149cd61257a565b30604051602001808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405160208183030381529060405280519060200120905090565b614a25614e7f565b806001600354031015614aa0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015614b0a5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b614b7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614c7c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360008154809291906001900391905055508173ffffffffffffffffffffffffffffffffffffffff167ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf60405160405180910390a28060045414614e4157614e4081612bea565b5b505050565b6040518060400160405280600581526020017f312e342e3100000000000000000000000000000000000000000000000000000081525081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614f20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b600080831415614f355760009050614f56565b6000828402905082848281614f4657fe5b0414614f5157600080fd5b809150505b92915050565b60008060008360410260208101860151925060408101860151915060ff60418201870151169350509250925092565b600080828401905083811015614fa057600080fd5b8091505092915050565b6000600180811115614fb857fe5b836001811115614fc457fe5b1415614fdd576000808551602087018986f49050614fed565b600080855160208701888a87f190505b95945050505050565b6000807f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b9050805491505090565b6000818310156150375781615039565b825b905092915050565b60008282111561505057600080fd5b600082840390508091505092915050565b600080600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461509e57826150a0565b325b9050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156151b85761510a3a86106150e7573a6150e9565b855b6150fc888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050506151b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b61525d565b6151dd856151cf888a614f8b90919063ffffffff16565b614f2290919063ffffffff16565b91506151ea848284615b0e565b61525c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5095945050505050565b6000600454146152df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8151811115615356576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60018110156153cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006001905060005b83518110156156d35760008482815181106153ed57fe5b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156154615750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561549957503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b80156154d157508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b615543576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614615644576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508092505080806001019150506153d6565b506001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550825160038190555081600481905550505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415615809576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475334303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b90508181555050565b600073ffffffffffffffffffffffffffffffffffffffff1660016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461593a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001806000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614615b0a576159f682615bd2565b615a68576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b615a978260008360017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff614faa565b615b09576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5050565b60008063a9059cbb8484604051602401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050602060008251602084016000896127105a03f13d60008114615bb55760208114615bbd5760009350615bc8565b819350615bc8565b600051158215171593505b5050509392505050565b600080823b90506000811191505091905056fea264697066735822122057398fa72884cf9a6cb78aab2fb58a6b927f0e9d97d75b015daaee0959a153bf64736f6c63430007060033