Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
DharmaSmartWalletImplementationV10
Compiler Version
v0.5.17+commit.d19bba13
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-07-08 */ pragma solidity 0.5.17; // optimization runs: 200, evm version: istanbul // WARNING - `executeActionWithAtomicBatchCalls` has a `bytes[]` argument that // requires ABIEncoderV2. Exercise caution when calling that specific function. pragma experimental ABIEncoderV2; interface DharmaSmartWalletImplementationV1Interface { event CallSuccess( bytes32 actionID, bool rolledBack, uint256 nonce, address to, bytes data, bytes returnData ); event CallFailure( bytes32 actionID, uint256 nonce, address to, bytes data, string revertReason ); // ABIEncoderV2 uses an array of Calls for executing generic batch calls. struct Call { address to; bytes data; } // ABIEncoderV2 uses an array of CallReturns for handling generic batch calls. struct CallReturn { bool ok; bytes returnData; } function withdrawEther( uint256 amount, address payable recipient, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok); function executeAction( address to, bytes calldata data, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok, bytes memory returnData); function recover(address newUserSigningKey) external; function executeActionWithAtomicBatchCalls( Call[] calldata calls, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool[] memory ok, bytes[] memory returnData); function getNextGenericActionID( address to, bytes calldata data, uint256 minimumActionGas ) external view returns (bytes32 actionID); function getGenericActionID( address to, bytes calldata data, uint256 nonce, uint256 minimumActionGas ) external view returns (bytes32 actionID); function getNextGenericAtomicBatchActionID( Call[] calldata calls, uint256 minimumActionGas ) external view returns (bytes32 actionID); function getGenericAtomicBatchActionID( Call[] calldata calls, uint256 nonce, uint256 minimumActionGas ) external view returns (bytes32 actionID); } interface DharmaSmartWalletImplementationV3Interface { event Cancel(uint256 cancelledNonce); event EthWithdrawal(uint256 amount, address recipient); } interface DharmaSmartWalletImplementationV4Interface { event Escaped(); function setEscapeHatch( address account, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external; function removeEscapeHatch( uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external; function permanentlyDisableEscapeHatch( uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external; function escape() external; } interface DharmaSmartWalletImplementationV7Interface { // Fires when a new user signing key is set on the smart wallet. event NewUserSigningKey(address userSigningKey); // Fires when an error occurs as part of an attempted action. event ExternalError(address indexed source, string revertReason); // The smart wallet recognizes DAI, USDC, ETH, and SAI as supported assets. enum AssetType { DAI, USDC, ETH, SAI } // Actions, or protected methods (i.e. not deposits) each have an action type. enum ActionType { Cancel, SetUserSigningKey, Generic, GenericAtomicBatch, SAIWithdrawal, USDCWithdrawal, ETHWithdrawal, SetEscapeHatch, RemoveEscapeHatch, DisableEscapeHatch, DAIWithdrawal, SignatureVerification, TradeEthForDai, DAIBorrow, USDCBorrow } function initialize(address userSigningKey) external; function repayAndDeposit() external; function withdrawDai( uint256 amount, address recipient, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok); function withdrawUSDC( uint256 amount, address recipient, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok); function cancel( uint256 minimumActionGas, bytes calldata signature ) external; function setUserSigningKey( address userSigningKey, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external; function migrateSaiToDai() external; function migrateCSaiToDDai() external; function migrateCDaiToDDai() external; function migrateCUSDCToDUSDC() external; function getBalances() external view returns ( uint256 daiBalance, uint256 usdcBalance, uint256 etherBalance, uint256 dDaiUnderlyingDaiBalance, uint256 dUsdcUnderlyingUsdcBalance, uint256 dEtherUnderlyingEtherBalance // always returns zero ); function getUserSigningKey() external view returns (address userSigningKey); function getNonce() external view returns (uint256 nonce); function getNextCustomActionID( ActionType action, uint256 amount, address recipient, uint256 minimumActionGas ) external view returns (bytes32 actionID); function getCustomActionID( ActionType action, uint256 amount, address recipient, uint256 nonce, uint256 minimumActionGas ) external view returns (bytes32 actionID); function getVersion() external pure returns (uint256 version); } interface DharmaSmartWalletImplementationV8Interface { function tradeEthForDaiAndMintDDai( uint256 ethToSupply, uint256 minimumDaiReceived, address target, bytes calldata data, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok, bytes memory returnData); function getNextEthForDaiActionID( uint256 ethToSupply, uint256 minimumDaiReceived, address target, bytes calldata data, uint256 minimumActionGas ) external view returns (bytes32 actionID); function getEthForDaiActionID( uint256 ethToSupply, uint256 minimumDaiReceived, address target, bytes calldata data, uint256 nonce, uint256 minimumActionGas ) external view returns (bytes32 actionID); } interface ERC20Interface { function transfer(address recipient, uint256 amount) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function balanceOf(address account) external view returns (uint256); function allowance( address owner, address spender ) external view returns (uint256); } interface ERC1271Interface { function isValidSignature( bytes calldata data, bytes calldata signature ) external view returns (bytes4 magicValue); } interface CTokenInterface { function redeem(uint256 redeemAmount) external returns (uint256 err); function transfer(address recipient, uint256 value) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function balanceOf(address account) external view returns (uint256 balance); function allowance(address owner, address spender) external view returns (uint256); } interface DTokenInterface { // These external functions trigger accrual on the dToken and backing cToken. function mint(uint256 underlyingToSupply) external returns (uint256 dTokensMinted); function redeem(uint256 dTokensToBurn) external returns (uint256 underlyingReceived); function redeemUnderlying(uint256 underlyingToReceive) external returns (uint256 dTokensBurned); // These external functions only trigger accrual on the dToken. function mintViaCToken(uint256 cTokensToSupply) external returns (uint256 dTokensMinted); // View and pure functions do not trigger accrual on the dToken or the cToken. function balanceOfUnderlying(address account) external view returns (uint256 underlyingBalance); } interface USDCV1Interface { function isBlacklisted(address _account) external view returns (bool); function paused() external view returns (bool); } interface DharmaKeyRegistryInterface { function getKey() external view returns (address key); } interface DharmaEscapeHatchRegistryInterface { function setEscapeHatch(address newEscapeHatch) external; function removeEscapeHatch() external; function permanentlyDisableEscapeHatch() external; function getEscapeHatch() external view returns ( bool exists, address escapeHatch ); } interface TradeHelperInterface { function tradeEthForDai( uint256 daiExpected, address target, bytes calldata data ) external payable returns (uint256 daiReceived); } interface RevertReasonHelperInterface { function reason(uint256 code) external pure returns (string memory); } interface EtherizedInterface { function triggerEtherTransfer( address payable target, uint256 value ) external returns (bool success); } interface ConfigurationRegistryInterface { function get(bytes32 key) external view returns (bytes32 value); } library Address { function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0; } } library ECDSA { function recover( bytes32 hash, bytes memory signature ) internal pure returns (address) { if (signature.length != 65) { return (address(0)); } bytes32 r; bytes32 s; uint8 v; assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return address(0); } if (v != 27 && v != 28) { return address(0); } return ecrecover(hash, v, r, s); } function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } } contract Etherized is EtherizedInterface { address private constant _ETHERIZER = address( 0x723B51b72Ae89A3d0c2a2760f0458307a1Baa191 ); function triggerEtherTransfer( address payable target, uint256 amount ) external returns (bool success) { require(msg.sender == _ETHERIZER, "Etherized: only callable by Etherizer"); (success, ) = target.call.value(amount)(""); if (!success) { assembly { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } } } } /** * @title DharmaSmartWalletImplementationV10 * @author 0age * @notice The V10 implementation for the Dharma smart wallet is a non-custodial, * meta-transaction-enabled wallet with helper functions to facilitate lending * funds through Dharma Dai and Dharma USD Coin (which in turn use CompoundV2), * and with an added security backstop provided by Dharma Labs prior to making * withdrawals. It adds support for Dharma Dai and Dharma USD Coin - they employ * the respective cTokens as backing tokens and mint and redeem them internally * as interest-bearing collateral. This implementation also contains methods to * support account recovery, escape hatch functionality, and generic actions, * including in an atomic batch. The smart wallet instances utilizing this * implementation are deployed through the Dharma Smart Wallet Factory via * `CREATE2`, which allows for their address to be known ahead of time, and any * Dai or USDC that has already been sent into that address will automatically * be deposited into the respective Dharma Token upon deployment of the new * smart wallet instance. V10 allows for deactivation of automatic USDC deposits * into cUSDC and deprecates Sai-related functionality. */ contract DharmaSmartWalletImplementationV10 is DharmaSmartWalletImplementationV1Interface, DharmaSmartWalletImplementationV3Interface, DharmaSmartWalletImplementationV4Interface, DharmaSmartWalletImplementationV7Interface, DharmaSmartWalletImplementationV8Interface, ERC1271Interface, Etherized { using Address for address; using ECDSA for bytes32; // WARNING: DO NOT REMOVE OR REORDER STORAGE WHEN WRITING NEW IMPLEMENTATIONS! // The user signing key associated with this account is in storage slot 0. // It is the core differentiator when it comes to the account in question. address private _userSigningKey; // The nonce associated with this account is in storage slot 1. Every time a // signature is submitted, it must have the appropriate nonce, and once it has // been accepted the nonce will be incremented. uint256 private _nonce; // The self-call context flag is in storage slot 2. Some protected functions // may only be called externally from calls originating from other methods on // this contract, which enables appropriate exception handling on reverts. // Any storage should only be set immediately preceding a self-call and should // be cleared upon entering the protected function being called. bytes4 internal _selfCallContext; // END STORAGE DECLARATIONS - DO NOT REMOVE OR REORDER STORAGE ABOVE HERE! // The smart wallet version will be used when constructing valid signatures. uint256 internal constant _DHARMA_SMART_WALLET_VERSION = 10; // DharmaKeyRegistryV2 holds a public key for verifying meta-transactions. DharmaKeyRegistryInterface internal constant _DHARMA_KEY_REGISTRY = ( DharmaKeyRegistryInterface(0x000000000D38df53b45C5733c7b34000dE0BDF52) ); // Account recovery is facilitated using a hard-coded recovery manager, // controlled by Dharma and implementing appropriate timelocks. address internal constant _ACCOUNT_RECOVERY_MANAGER = address( 0x0000000000DfEd903aD76996FC07BF89C0127B1E ); // Users can designate an "escape hatch" account with the ability to sweep all // funds from their smart wallet by using the Dharma Escape Hatch Registry. DharmaEscapeHatchRegistryInterface internal constant _ESCAPE_HATCH_REGISTRY = ( DharmaEscapeHatchRegistryInterface(0x00000000005280B515004B998a944630B6C663f8) ); // Interface with dDai, dUSDC, Dai, USDC, Sai, cSai, cDai, cUSDC, & migrator. DTokenInterface internal constant _DDAI = DTokenInterface( 0x00000000001876eB1444c986fD502e618c587430 // mainnet ); DTokenInterface internal constant _DUSDC = DTokenInterface( 0x00000000008943c65cAf789FFFCF953bE156f6f8 // mainnet ); ERC20Interface internal constant _DAI = ERC20Interface( 0x6B175474E89094C44Da98b954EedeAC495271d0F // mainnet ); ERC20Interface internal constant _USDC = ERC20Interface( 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 // mainnet ); CTokenInterface internal constant _CDAI = CTokenInterface( 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643 // mainnet ); CTokenInterface internal constant _CUSDC = CTokenInterface( 0x39AA39c021dfbaE8faC545936693aC917d5E7563 // mainnet ); // The "trade helper" facilitates Eth-to-Dai trades in an isolated context. TradeHelperInterface internal constant _TRADE_HELPER = TradeHelperInterface( 0x421816CDFe2073945173c0c35799ec21261fB399 ); // The "revert reason helper" contains a collection of revert reason strings. RevertReasonHelperInterface internal constant _REVERT_REASON_HELPER = ( RevertReasonHelperInterface(0x9C0ccB765D3f5035f8b5Dd30fE375d5F4997D8E4) ); ConfigurationRegistryInterface internal constant _CONFIG_REGISTRY = ( ConfigurationRegistryInterface(0xC5C0ead7Df3CeFC45c8F4592E3a0f1500949E75D) ); bytes32 internal constant _ENABLE_USDC_MINTING_KEY = bytes32( 0x596746115f08448433597980d42b4541c0197187d07ffad9c7f66a471c49dbba ); // keccak256("allowAvailableUSDCToBeUsedToMintCUSDC") // Compound returns a value of 0 to indicate success, or lack of an error. uint256 internal constant _COMPOUND_SUCCESS = 0; // ERC-1271 must return this magic value when `isValidSignature` is called. bytes4 internal constant _ERC_1271_MAGIC_VALUE = bytes4(0x20c13b0b); // Minimum supported deposit & non-maximum withdrawal size is .001 underlying. uint256 private constant _JUST_UNDER_ONE_1000th_DAI = 999999999999999; uint256 private constant _JUST_UNDER_ONE_1000th_USDC = 999; // Specify the amount of gas to supply when making Ether transfers. uint256 private constant _ETH_TRANSFER_GAS = 4999; constructor() public { assert( _ENABLE_USDC_MINTING_KEY == keccak256( bytes("allowAvailableUSDCToBeUsedToMintCUSDC") ) ); } /** * @notice Accept Ether in the fallback. */ function () external payable {} /** * @notice In the initializer, set up the initial user signing key, set * approval on the Dharma Dai and Dharma USD Coin contracts, and deposit any * Dai or USDC already at this address to receive dDai or dUSDC. Note that * this initializer is only callable while the smart wallet instance is still * in the contract creation phase. * @param userSigningKey address The initial user signing key for the smart * wallet. */ function initialize(address userSigningKey) external { // Ensure that this function is only callable during contract construction. assembly { if extcodesize(address) { revert(0, 0) } } // Set up the user's signing key and emit a corresponding event. _setUserSigningKey(userSigningKey); // Approve the dDai contract to transfer Dai on behalf of this contract. if (_setFullApproval(AssetType.DAI)) { // Get the current Dai balance on this contract. uint256 daiBalance = _DAI.balanceOf(address(this)); // Try to deposit the full Dai balance to Dharma Dai. _depositDharmaToken(AssetType.DAI, daiBalance); } // Approve the dUSDC contract to transfer USDC on behalf of this contract. if (_setFullApproval(AssetType.USDC)) { // Get the current USDC balance on this contract. uint256 usdcBalance = _USDC.balanceOf(address(this)); // Try to deposit the full Dai balance to Dharma USDC. _depositDharmaToken(AssetType.USDC, usdcBalance); } } /** * @notice Deposit all Dai and USDC currently residing at this address and * receive Dharma Dai or Dharma USD Coin in return. Note that "repay" is not * currently implemented, though it may be in a future implementation. If some * step of this function fails, the function itself will still succeed, but an * `ExternalError` with information on what went wrong will be emitted. */ function repayAndDeposit() external { // Get the current Dai balance on this contract. uint256 daiBalance = _DAI.balanceOf(address(this)); // If there is any Dai balance, check for adequate approval for dDai. if (daiBalance > 0) { uint256 daiAllowance = _DAI.allowance(address(this), address(_DDAI)); // If allowance is insufficient, try to set it before depositing. if (daiAllowance < daiBalance) { if (_setFullApproval(AssetType.DAI)) { // Deposit the full available Dai balance to Dharma Dai. _depositDharmaToken(AssetType.DAI, daiBalance); } // Otherwise, just go ahead and try the Dai deposit. } else { // Deposit the full available Dai balance to Dharma Dai. _depositDharmaToken(AssetType.DAI, daiBalance); } } // Get the current USDC balance on this contract. uint256 usdcBalance = _USDC.balanceOf(address(this)); // If there is any USDC balance, check for adequate approval for dUSDC. if (usdcBalance > 0) { uint256 usdcAllowance = _USDC.allowance(address(this), address(_DUSDC)); // If allowance is insufficient, try to set it before depositing. if (usdcAllowance < usdcBalance) { if (_setFullApproval(AssetType.USDC)) { // Deposit the full available USDC balance to Dharma USDC. _depositDharmaToken(AssetType.USDC, usdcBalance); } // Otherwise, just go ahead and try the USDC deposit. } else { // Deposit the full available USDC balance to Dharma USDC. _depositDharmaToken(AssetType.USDC, usdcBalance); } } } /** * @notice Withdraw Dai to a provided recipient address by redeeming the * underlying Dai from the dDai contract and transferring it to the recipient. * All Dai in Dharma Dai and in the smart wallet itself can be withdrawn by * providing an amount of uint256(-1) or 0xfff...fff. This function can be * called directly by the account set as the global key on the Dharma Key * Registry, or by any relayer that provides a signed message from the same * keyholder. The nonce used for the signature must match the current nonce on * the smart wallet, and gas supplied to the call must exceed the specified * minimum action gas, plus the gas that will be spent before the gas check is * reached - usually somewhere around 25,000 gas. If the withdrawal fails, an * `ExternalError` with additional details on what went wrong will be emitted. * Note that some dust may still be left over, even in the event of a max * withdrawal, due to the fact that Dai has a higher precision than dDai. Also * note that the withdrawal will fail in the event that Compound does not have * sufficient Dai available to withdraw. * @param amount uint256 The amount of Dai to withdraw. * @param recipient address The account to transfer the withdrawn Dai to. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. * @return True if the withdrawal succeeded, otherwise false. */ function withdrawDai( uint256 amount, address recipient, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok) { // Ensure caller and/or supplied signatures are valid and increment nonce. _validateActionAndIncrementNonce( ActionType.DAIWithdrawal, abi.encode(amount, recipient), minimumActionGas, userSignature, dharmaSignature ); // Ensure that an amount of at least 0.001 Dai has been supplied. if (amount <= _JUST_UNDER_ONE_1000th_DAI) { revert(_revertReason(0)); } // Ensure that a non-zero recipient has been supplied. if (recipient == address(0)) { revert(_revertReason(1)); } // Set the self-call context in order to call _withdrawDaiAtomic. _selfCallContext = this.withdrawDai.selector; // Make the atomic self-call - if redeemUnderlying fails on dDai, it will // succeed but nothing will happen except firing an ExternalError event. If // the second part of the self-call (the Dai transfer) fails, it will revert // and roll back the first part of the call as well as fire an ExternalError // event after returning from the failed call. bytes memory returnData; (ok, returnData) = address(this).call(abi.encodeWithSelector( this._withdrawDaiAtomic.selector, amount, recipient )); // If the atomic call failed, emit an event signifying a transfer failure. if (!ok) { emit ExternalError(address(_DAI), _revertReason(2)); } else { // Set ok to false if the call succeeded but the withdrawal failed. ok = abi.decode(returnData, (bool)); } } /** * @notice Protected function that can only be called from `withdrawDai` on * this contract. It will attempt to withdraw the supplied amount of Dai, or * the maximum amount if specified using `uint256(-1)`, to the supplied * recipient address by redeeming the underlying Dai from the dDai contract * and transferring it to the recipient. An ExternalError will be emitted and * the transfer will be skipped if the call to `redeem` or `redeemUnderlying` * fails, and any revert will be caught by `withdrawDai` and diagnosed in * order to emit an appropriate `ExternalError` as well. * @param amount uint256 The amount of Dai to withdraw. * @param recipient address The account to transfer the withdrawn Dai to. * @return True if the withdrawal succeeded, otherwise false. */ function _withdrawDaiAtomic( uint256 amount, address recipient ) external returns (bool success) { // Ensure caller is this contract and self-call context is correctly set. _enforceSelfCallFrom(this.withdrawDai.selector); // If amount = 0xfff...fff, withdraw the maximum amount possible. bool maxWithdraw = (amount == uint256(-1)); if (maxWithdraw) { // First attempt to redeem all dDai if there is a balance. _withdrawMaxFromDharmaToken(AssetType.DAI); // Then transfer all Dai to recipient if there is a balance. require(_transferMax(_DAI, recipient, false)); success = true; } else { // Attempt to withdraw specified Dai from Dharma Dai before proceeding. if (_withdrawFromDharmaToken(AssetType.DAI, amount)) { // At this point Dai transfer should never fail - wrap it just in case. require(_DAI.transfer(recipient, amount)); success = true; } } } /** * @notice Withdraw USDC to a provided recipient address by redeeming the * underlying USDC from the dUSDC contract and transferring it to recipient. * All USDC in Dharma USD Coin and in the smart wallet itself can be withdrawn * by providing an amount of uint256(-1) or 0xfff...fff. This function can be * called directly by the account set as the global key on the Dharma Key * Registry, or by any relayer that provides a signed message from the same * keyholder. The nonce used for the signature must match the current nonce on * the smart wallet, and gas supplied to the call must exceed the specified * minimum action gas, plus the gas that will be spent before the gas check is * reached - usually somewhere around 25,000 gas. If the withdrawal fails, an * `ExternalError` with additional details on what went wrong will be emitted. * Note that the USDC contract can be paused and also allows for blacklisting * accounts - either of these possibilities may cause a withdrawal to fail. In * addition, Compound may not have sufficient USDC available at the time to * withdraw. * @param amount uint256 The amount of USDC to withdraw. * @param recipient address The account to transfer the withdrawn USDC to. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. * @return True if the withdrawal succeeded, otherwise false. */ function withdrawUSDC( uint256 amount, address recipient, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok) { // Ensure caller and/or supplied signatures are valid and increment nonce. _validateActionAndIncrementNonce( ActionType.USDCWithdrawal, abi.encode(amount, recipient), minimumActionGas, userSignature, dharmaSignature ); // Ensure that an amount of at least 0.001 USDC has been supplied. if (amount <= _JUST_UNDER_ONE_1000th_USDC) { revert(_revertReason(3)); } // Ensure that a non-zero recipient has been supplied. if (recipient == address(0)) { revert(_revertReason(1)); } // Set the self-call context in order to call _withdrawUSDCAtomic. _selfCallContext = this.withdrawUSDC.selector; // Make the atomic self-call - if redeemUnderlying fails on dUSDC, it will // succeed but nothing will happen except firing an ExternalError event. If // the second part of the self-call (USDC transfer) fails, it will revert // and roll back the first part of the call as well as fire an ExternalError // event after returning from the failed call. bytes memory returnData; (ok, returnData) = address(this).call(abi.encodeWithSelector( this._withdrawUSDCAtomic.selector, amount, recipient )); if (!ok) { // Find out why USDC transfer reverted (doesn't give revert reasons). _diagnoseAndEmitUSDCSpecificError(_USDC.transfer.selector); } else { // Set ok to false if the call succeeded but the withdrawal failed. ok = abi.decode(returnData, (bool)); } } /** * @notice Protected function that can only be called from `withdrawUSDC` on * this contract. It will attempt to withdraw the supplied amount of USDC, or * the maximum amount if specified using `uint256(-1)`, to the supplied * recipient address by redeeming the underlying USDC from the dUSDC contract * and transferring it to the recipient. An ExternalError will be emitted and * the transfer will be skipped if the call to `redeemUnderlying` fails, and * any revert will be caught by `withdrawUSDC` and diagnosed in order to emit * an appropriate ExternalError as well. * @param amount uint256 The amount of USDC to withdraw. * @param recipient address The account to transfer the withdrawn USDC to. * @return True if the withdrawal succeeded, otherwise false. */ function _withdrawUSDCAtomic( uint256 amount, address recipient ) external returns (bool success) { // Ensure caller is this contract and self-call context is correctly set. _enforceSelfCallFrom(this.withdrawUSDC.selector); // If amount = 0xfff...fff, withdraw the maximum amount possible. bool maxWithdraw = (amount == uint256(-1)); if (maxWithdraw) { // Attempt to redeem all dUSDC from Dharma USDC if there is a balance. _withdrawMaxFromDharmaToken(AssetType.USDC); // Then transfer all USDC to recipient if there is a balance. require(_transferMax(_USDC, recipient, false)); success = true; } else { // Attempt to withdraw specified USDC from Dharma USDC before proceeding. if (_withdrawFromDharmaToken(AssetType.USDC, amount)) { // Ensure that the USDC transfer does not fail. require(_USDC.transfer(recipient, amount)); success = true; } } } /** * @notice Withdraw Ether to a provided recipient address by transferring it * to a recipient. * @param amount uint256 The amount of Ether to withdraw. * @param recipient address The account to transfer the Ether to. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. * @return True if the transfer succeeded, otherwise false. */ function withdrawEther( uint256 amount, address payable recipient, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok) { // Ensure caller and/or supplied signatures are valid and increment nonce. _validateActionAndIncrementNonce( ActionType.ETHWithdrawal, abi.encode(amount, recipient), minimumActionGas, userSignature, dharmaSignature ); // Ensure that a non-zero amount of Ether has been supplied. if (amount == 0) { revert(_revertReason(4)); } // Ensure that a non-zero recipient has been supplied. if (recipient == address(0)) { revert(_revertReason(1)); } // Attempt to transfer Ether to the recipient and emit an appropriate event. ok = _transferETH(recipient, amount); } /** * @notice Allow a signatory to increment the nonce at any point. The current * nonce needs to be provided as an argument to the signature so as not to * enable griefing attacks. All arguments can be omitted if called directly. * No value is returned from this function - it will either succeed or revert. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param signature bytes A signature that resolves to either the public key * set for this account in storage slot zero, `_userSigningKey`, or the public * key returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. */ function cancel( uint256 minimumActionGas, bytes calldata signature ) external { // Get the current nonce. uint256 nonceToCancel = _nonce; // Ensure the caller or the supplied signature is valid and increment nonce. _validateActionAndIncrementNonce( ActionType.Cancel, abi.encode(), minimumActionGas, signature, signature ); // Emit an event to validate that the nonce is no longer valid. emit Cancel(nonceToCancel); } /** * @notice Perform a generic call to another contract. Note that accounts with * no code may not be specified, nor may the smart wallet itself or the escape * hatch registry. In order to increment the nonce and invalidate the * signatures, a call to this function with a valid target, signatutes, and * gas will always succeed. To determine whether the call made as part of the * action was successful or not, either the return values or the `CallSuccess` * or `CallFailure` event can be used. * @param to address The contract to call. * @param data bytes The calldata to provide when making the call. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. * @return A boolean signifying the status of the call, as well as any data * returned from the call. */ function executeAction( address to, bytes calldata data, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok, bytes memory returnData) { // Ensure that the `to` address is a contract and is not this contract. _ensureValidGenericCallTarget(to); // Ensure caller and/or supplied signatures are valid and increment nonce. (bytes32 actionID, uint256 nonce) = _validateActionAndIncrementNonce( ActionType.Generic, abi.encode(to, data), minimumActionGas, userSignature, dharmaSignature ); // Note: from this point on, there are no reverts (apart from out-of-gas or // call-depth-exceeded) originating from this action. However, the call // itself may revert, in which case the function will return `false`, along // with the revert reason encoded as bytes, and fire an CallFailure event. // Perform the action via low-level call and set return values using result. (ok, returnData) = to.call(data); // Emit a CallSuccess or CallFailure event based on the outcome of the call. if (ok) { // Note: while the call succeeded, the action may still have "failed" // (for example, successful calls to Compound can still return an error). emit CallSuccess(actionID, false, nonce, to, data, returnData); } else { // Note: while the call failed, the nonce will still be incremented, which // will invalidate all supplied signatures. emit CallFailure(actionID, nonce, to, data, string(returnData)); } } /** * @notice Allow signatory to set a new user signing key. The current nonce * needs to be provided as an argument to the signature so as not to enable * griefing attacks. No value is returned from this function - it will either * succeed or revert. * @param userSigningKey address The new user signing key to set on this smart * wallet. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. */ function setUserSigningKey( address userSigningKey, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external { // Ensure caller and/or supplied signatures are valid and increment nonce. _validateActionAndIncrementNonce( ActionType.SetUserSigningKey, abi.encode(userSigningKey), minimumActionGas, userSignature, dharmaSignature ); // Set new user signing key on smart wallet and emit a corresponding event. _setUserSigningKey(userSigningKey); } /** * @notice Set a dedicated address as the "escape hatch" account. This account * can then call `escape()` at any point to "sweep" the entire Dai, USDC, * residual cDai, cUSDC, dDai, dUSDC, and Ether balance from the smart wallet. * This function call will revert if the smart wallet has previously called * `permanentlyDisableEscapeHatch` at any point and disabled the escape hatch. * No value is returned from this function - it will either succeed or revert. * @param account address The account to set as the escape hatch account. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. */ function setEscapeHatch( address account, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external { // Ensure caller and/or supplied signatures are valid and increment nonce. _validateActionAndIncrementNonce( ActionType.SetEscapeHatch, abi.encode(account), minimumActionGas, userSignature, dharmaSignature ); // Ensure that an escape hatch account has been provided. if (account == address(0)) { revert(_revertReason(5)); } // Set a new escape hatch for the smart wallet unless it has been disabled. _ESCAPE_HATCH_REGISTRY.setEscapeHatch(account); } /** * @notice Remove the "escape hatch" account if one is currently set. This * function call will revert if the smart wallet has previously called * `permanentlyDisableEscapeHatch` at any point and disabled the escape hatch. * No value is returned from this function - it will either succeed or revert. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. */ function removeEscapeHatch( uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external { // Ensure caller and/or supplied signatures are valid and increment nonce. _validateActionAndIncrementNonce( ActionType.RemoveEscapeHatch, abi.encode(), minimumActionGas, userSignature, dharmaSignature ); // Remove the escape hatch for the smart wallet if one is currently set. _ESCAPE_HATCH_REGISTRY.removeEscapeHatch(); } /** * @notice Permanently disable the "escape hatch" mechanism for this smart * wallet. This function call will revert if the smart wallet has already * called `permanentlyDisableEscapeHatch` at any point in the past. No value * is returned from this function - it will either succeed or revert. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. */ function permanentlyDisableEscapeHatch( uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external { // Ensure caller and/or supplied signatures are valid and increment nonce. _validateActionAndIncrementNonce( ActionType.DisableEscapeHatch, abi.encode(), minimumActionGas, userSignature, dharmaSignature ); // Permanently disable the escape hatch mechanism for this smart wallet. _ESCAPE_HATCH_REGISTRY.permanentlyDisableEscapeHatch(); } /** * @notice Swap Ether for Dai and use it to mint Dharma Dai. The trade is * facilitated by a "trade helper" contract in order to protect against * malicious calls related to processing swaps via potentially unsafe call * targets or other parameters. In the event that a swap does not result in * sufficient Dai being received, the swap will be rolled back. In either * case the nonce will still be incremented as long as signatures are valid. * @param ethToSupply uint256 The Ether to supply as part of the swap. * @param minimumDaiReceived uint256 The minimum amount of Dai that must be * received in exchange for the supplied Ether. * @param target address The contract that the trade helper should call in * order to facilitate the swap. * @param data bytes The payload that will be passed to the target, along with * the supplied Ether, by the trade helper in order to facilitate the swap. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getEthForDaiActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getEthForDaiActionIDActionID` is prefixed and hashed to * create the signed message. */ function tradeEthForDaiAndMintDDai( uint256 ethToSupply, uint256 minimumDaiReceived, address target, bytes calldata data, uint256 minimumActionGas, bytes calldata userSignature, bytes calldata dharmaSignature ) external returns (bool ok, bytes memory returnData) { // Ensure caller and/or supplied signatures are valid and increment nonce. _validateActionAndIncrementNonce( ActionType.TradeEthForDai, abi.encode(ethToSupply, minimumDaiReceived, target, data), minimumActionGas, userSignature, dharmaSignature ); // Ensure that an amount of at least 0.001 Dai will be received. if (minimumDaiReceived <= _JUST_UNDER_ONE_1000th_DAI) { revert(_revertReason(31)); } // Set the self-call context in order to call _tradeEthForDaiAndMintDDaiAtomic. _selfCallContext = this.tradeEthForDaiAndMintDDai.selector; // Make the atomic self-call - if the swap fails or the received dai is not // greater than or equal to the requirement, it will revert and roll back the // atomic call as well as fire an ExternalError. If dDai is not successfully // minted, the swap will succeed but an ExternalError for dDai will be fired. bytes memory returnData; (ok, returnData) = address(this).call(abi.encodeWithSelector( this._tradeEthForDaiAndMintDDaiAtomic.selector, ethToSupply, minimumDaiReceived, target, data )); // If the atomic call failed, emit an event signifying a trade failure. if (!ok) { emit ExternalError( address(_TRADE_HELPER), _decodeRevertReason(returnData) ); } } function _tradeEthForDaiAndMintDDaiAtomic( uint256 ethToSupply, uint256 minimumDaiReceived, address target, bytes calldata data ) external returns (bool ok, bytes memory returnData) { // Ensure caller is this contract and self-call context is correctly set. _enforceSelfCallFrom(this.tradeEthForDaiAndMintDDai.selector); // Do swap using supplied Ether amount, minimum Dai, target, and data. uint256 daiReceived = _TRADE_HELPER.tradeEthForDai.value(ethToSupply)( minimumDaiReceived, target, data ); // Ensure that sufficient Dai was returned as a result of the swap. if (daiReceived < minimumDaiReceived) { revert(_revertReason(32)); } // Attempt to deposit the dai received and mint Dharma Dai. _depositDharmaToken(AssetType.DAI, daiReceived); } /** * @notice Allow the designated escape hatch account to redeem and "sweep" * the entire Dai, USDC, residual dDai, dUSDC, cDai, cUSDC, & Ether balance * from the smart wallet. The call will revert for any other caller, or if * there is no escape hatch account on this smart wallet. First, an attempt * will be made to redeem any dDai or dUSDC that is currently deposited in a * dToken. Then, attempts will be made to transfer any balance in Dai, USDC, * residual cDai & cUSDC, and Ether to the escape hatch account. If any * portion of this operation does not succeed, it will simply be skipped, * allowing the rest of the operation to proceed. Finally, an `Escaped` event * will be emitted. No value is returned from this function - it will either * succeed or revert. */ function escape() external { // Get the escape hatch account, if one exists, for this account. (bool exists, address escapeHatch) = _ESCAPE_HATCH_REGISTRY.getEscapeHatch(); // Ensure that an escape hatch is currently set for this smart wallet. if (!exists) { revert(_revertReason(6)); } // Ensure that the escape hatch account is the caller. if (msg.sender != escapeHatch) { revert(_revertReason(7)); } // Attempt to redeem all dDai for Dai on Dharma Dai. _withdrawMaxFromDharmaToken(AssetType.DAI); // Attempt to redeem all dUSDC for USDC on Dharma USDC. _withdrawMaxFromDharmaToken(AssetType.USDC); // Attempt to transfer the total Dai balance to the caller. _transferMax(_DAI, msg.sender, true); // Attempt to transfer the total USDC balance to the caller. _transferMax(_USDC, msg.sender, true); // Attempt to transfer any residual cDai to the caller. _transferMax(ERC20Interface(address(_CDAI)), msg.sender, true); // Attempt to transfer any residual cUSDC to the caller. _transferMax(ERC20Interface(address(_CUSDC)), msg.sender, true); // Attempt to transfer any residual dDai to the caller. _transferMax(ERC20Interface(address(_DDAI)), msg.sender, true); // Attempt to transfer any residual dUSDC to the caller. _transferMax(ERC20Interface(address(_DUSDC)), msg.sender, true); // Determine if there is Ether at this address that should be transferred. uint256 balance = address(this).balance; if (balance > 0) { // Attempt to transfer any Ether to caller and emit an appropriate event. _transferETH(msg.sender, balance); } // Emit an `Escaped` event. emit Escaped(); } /** * @notice Allow the account recovery manager to set a new user signing key on * the smart wallet. The call will revert for any other caller. The account * recovery manager implements a set of controls around the process, including * a timelock and an option to permanently opt out of account recover. No * value is returned from this function - it will either succeed or revert. * @param newUserSigningKey address The new user signing key to set on this * smart wallet. */ function recover(address newUserSigningKey) external { // Only the Account Recovery Manager contract may call this function. if (msg.sender != _ACCOUNT_RECOVERY_MANAGER) { revert(_revertReason(8)); } // Increment nonce to prevent signature reuse should original key be reset. _nonce++; // Set up the user's new dharma key and emit a corresponding event. _setUserSigningKey(newUserSigningKey); } /** * @notice This call is no longer supported. */ function migrateSaiToDai() external { revert(); } /** * @notice This call is no longer supported. */ function migrateCSaiToDDai() external { revert(); } /** * @notice Redeem all available cDAI for Dai and use that Dai to mint dDai. If * any step in the process fails, the call will revert and prior steps will be * rolled back. Also note that existing Sai and Dai are not included as part * of this operation. */ function migrateCDaiToDDai() external { _migrateCTokenToDToken(AssetType.DAI); } /** * @notice Redeem all available cUSDC for USDC and use that USDC to mint * dUSDC. If any step in the process fails, the call will revert and prior * steps will be rolled back. Also note that existing USDC is not included as * part of this operation. */ function migrateCUSDCToDUSDC() external { _migrateCTokenToDToken(AssetType.USDC); } /** * @notice View function to retrieve the Dai and USDC balances held by the * smart wallet, both directly and held in Dharma Dai and Dharma USD Coin, as * well as the Ether balance (the underlying dEther balance will always return * zero in this implementation, as there is no dEther yet). * @return The Dai balance, the USDC balance, the Ether balance, the * underlying Dai balance of the dDai balance, and the underlying USDC balance * of the dUSDC balance (zero will always be returned as the underlying Ether * balance of the dEther balance in this implementation). */ function getBalances() external view returns ( uint256 daiBalance, uint256 usdcBalance, uint256 etherBalance, uint256 dDaiUnderlyingDaiBalance, uint256 dUsdcUnderlyingUsdcBalance, uint256 dEtherUnderlyingEtherBalance // always returns 0 ) { daiBalance = _DAI.balanceOf(address(this)); usdcBalance = _USDC.balanceOf(address(this)); etherBalance = address(this).balance; dDaiUnderlyingDaiBalance = _DDAI.balanceOfUnderlying(address(this)); dUsdcUnderlyingUsdcBalance = _DUSDC.balanceOfUnderlying(address(this)); } /** * @notice View function for getting the current user signing key for the * smart wallet. * @return The current user signing key. */ function getUserSigningKey() external view returns (address userSigningKey) { userSigningKey = _userSigningKey; } /** * @notice View function for getting the current nonce of the smart wallet. * This nonce is incremented whenever an action is taken that requires a * signature and/or a specific caller. * @return The current nonce. */ function getNonce() external view returns (uint256 nonce) { nonce = _nonce; } /** * @notice View function that, given an action type and arguments, will return * the action ID or message hash that will need to be prefixed (according to * EIP-191 0x45), hashed, and signed by both the user signing key and by the * key returned for this smart wallet by the Dharma Key Registry in order to * construct a valid signature for the corresponding action. Any nonce value * may be supplied, which enables constructing valid message hashes for * multiple future actions ahead of time. * @param action uint8 The type of action, designated by it's index. Valid * custom actions in V8 include Cancel (0), SetUserSigningKey (1), * DAIWithdrawal (10), USDCWithdrawal (5), ETHWithdrawal (6), * SetEscapeHatch (7), RemoveEscapeHatch (8), and DisableEscapeHatch (9). * @param amount uint256 The amount to withdraw for Withdrawal actions. This * value is ignored for non-withdrawal action types. * @param recipient address The account to transfer withdrawn funds to or the * new user signing key. This value is ignored for Cancel, RemoveEscapeHatch, * and DisableEscapeHatch action types. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @return The action ID, which will need to be prefixed, hashed and signed in * order to construct a valid signature. */ function getNextCustomActionID( ActionType action, uint256 amount, address recipient, uint256 minimumActionGas ) external view returns (bytes32 actionID) { // Determine the actionID - this serves as a signature hash for an action. actionID = _getActionID( action, _validateCustomActionTypeAndGetArguments(action, amount, recipient), _nonce, minimumActionGas, _userSigningKey, _getDharmaSigningKey() ); } /** * @notice View function that, given an action type and arguments, will return * the action ID or message hash that will need to be prefixed (according to * EIP-191 0x45), hashed, and signed by both the user signing key and by the * key returned for this smart wallet by the Dharma Key Registry in order to * construct a valid signature for the corresponding action. The current nonce * will be used, which means that it will only be valid for the next action * taken. * @param action uint8 The type of action, designated by it's index. Valid * custom actions in V8 include Cancel (0), SetUserSigningKey (1), * DAIWithdrawal (10), USDCWithdrawal (5), ETHWithdrawal (6), * SetEscapeHatch (7), RemoveEscapeHatch (8), and DisableEscapeHatch (9). * @param amount uint256 The amount to withdraw for Withdrawal actions. This * value is ignored for non-withdrawal action types. * @param recipient address The account to transfer withdrawn funds to or the * new user signing key. This value is ignored for Cancel, RemoveEscapeHatch, * and DisableEscapeHatch action types. * @param nonce uint256 The nonce to use. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @return The action ID, which will need to be prefixed, hashed and signed in * order to construct a valid signature. */ function getCustomActionID( ActionType action, uint256 amount, address recipient, uint256 nonce, uint256 minimumActionGas ) external view returns (bytes32 actionID) { // Determine the actionID - this serves as a signature hash for an action. actionID = _getActionID( action, _validateCustomActionTypeAndGetArguments(action, amount, recipient), nonce, minimumActionGas, _userSigningKey, _getDharmaSigningKey() ); } /** * @notice View function that will return the action ID or message hash that * will need to be prefixed (according to EIP-191 0x45), hashed, and signed by * both the user signing key and by the key returned for this smart wallet by * the Dharma Key Registry in order to construct a valid signature for a given * generic action. The current nonce will be used, which means that it will * only be valid for the next action taken. * @param to address The target to call into as part of the generic action. * @param data bytes The data to supply when calling into the target. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @return The action ID, which will need to be prefixed, hashed and signed in * order to construct a valid signature. */ function getNextGenericActionID( address to, bytes calldata data, uint256 minimumActionGas ) external view returns (bytes32 actionID) { // Determine the actionID - this serves as a signature hash for an action. actionID = _getActionID( ActionType.Generic, abi.encode(to, data), _nonce, minimumActionGas, _userSigningKey, _getDharmaSigningKey() ); } /** * @notice View function that will return the action ID or message hash that * will need to be prefixed (according to EIP-191 0x45), hashed, and signed by * both the user signing key and by the key returned for this smart wallet by * the Dharma Key Registry in order to construct a valid signature for a given * generic action. Any nonce value may be supplied, which enables constructing * valid message hashes for multiple future actions ahead of time. * @param to address The target to call into as part of the generic action. * @param data bytes The data to supply when calling into the target. * @param nonce uint256 The nonce to use. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @return The action ID, which will need to be prefixed, hashed and signed in * order to construct a valid signature. */ function getGenericActionID( address to, bytes calldata data, uint256 nonce, uint256 minimumActionGas ) external view returns (bytes32 actionID) { // Determine the actionID - this serves as a signature hash for an action. actionID = _getActionID( ActionType.Generic, abi.encode(to, data), nonce, minimumActionGas, _userSigningKey, _getDharmaSigningKey() ); } /** * @notice View function that will return the action ID or message hash that * will need to be prefixed (according to EIP-191 0x45), hashed, and signed by * both the user signing key and by the key returned for this smart wallet by * the Dharma Key Registry in order to construct a valid signature for an * Eth-to-Dai swap. The current nonce will be used, which means that it will * only be valid for the next action taken. * @param ethToSupply uint256 The Ether to supply as part of the swap. * @param minimumDaiReceived uint256 The minimum amount of Dai that must be * received in exchange for the supplied Ether. * @param target address The contract that the trade helper should call in * order to facilitate the swap. * @param data bytes The payload that will be passed to the target, along with * the supplied Ether, by the trade helper in order to facilitate the swap. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @return The action ID, which will need to be prefixed, hashed and signed in * order to construct a valid signature. */ function getNextEthForDaiActionID( uint256 ethToSupply, uint256 minimumDaiReceived, address target, bytes calldata data, uint256 minimumActionGas ) external view returns (bytes32 actionID) { // Determine the actionID - this serves as a signature hash for an action. actionID = _getActionID( ActionType.TradeEthForDai, abi.encode(ethToSupply, minimumDaiReceived, target, data), _nonce, minimumActionGas, _userSigningKey, _getDharmaSigningKey() ); } /** * @notice View function that will return the action ID or message hash that * will need to be prefixed (according to EIP-191 0x45), hashed, and signed by * both the user signing key and by the key returned for this smart wallet by * the Dharma Key Registry in order to construct a valid signature for an * Eth-to-Dai swap. Any nonce value may be supplied, which enables * constructing valid message hashes for multiple future actions ahead of * time. * @param ethToSupply uint256 The Ether to supply as part of the swap. * @param minimumDaiReceived uint256 The minimum amount of Dai that must be * received in exchange for the supplied Ether. * @param target address The contract that the trade helper should call in * order to facilitate the swap. * @param data bytes The payload that will be passed to the target, along with * the supplied Ether, by the trade helper in order to facilitate the swap. * @param nonce uint256 The nonce to use. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @return The action ID, which will need to be prefixed, hashed and signed in * order to construct a valid signature. */ function getEthForDaiActionID( uint256 ethToSupply, uint256 minimumDaiReceived, address target, bytes calldata data, uint256 nonce, uint256 minimumActionGas ) external view returns (bytes32 actionID) { // Determine the actionID - this serves as a signature hash for an action. actionID = _getActionID( ActionType.TradeEthForDai, abi.encode(ethToSupply, minimumDaiReceived, target, data), nonce, minimumActionGas, _userSigningKey, _getDharmaSigningKey() ); } /** * @notice View function that implements ERC-1271 and validates a set of * signatures, one from the owner (using ERC-1271 as well if the user signing * key is a contract) and one from the Dharma Key Registry against the * supplied data. The data must be ABI encoded as (bytes32, bytes), where the * first bytes32 parameter represents the hash digest for validating the * supplied signatures and the second bytes parameter contains context for the * requested validation. The two signatures are packed together, with the one * from Dharma coming first and that from the user coming second - this is so * that, in future versions, multiple user signatures may be supplied if the * associated key ring requires them. * @param data bytes The data used to validate the signature. * @param signatures bytes The two signatures, each 65 bytes - one from the * owner (using ERC-1271 as well if the user signing key is a contract) and * one from the Dharma Key Registry. * @return The 4-byte magic value to signify a valid signature in ERC-1271, if * the signatures are both valid. */ function isValidSignature( bytes calldata data, bytes calldata signatures ) external view returns (bytes4 magicValue) { // Get message hash digest and any additional context from data argument. bytes32 digest; bytes memory context; if (data.length == 32) { digest = abi.decode(data, (bytes32)); } else { if (data.length < 64) { revert(_revertReason(30)); } (digest, context) = abi.decode(data, (bytes32, bytes)); } // Get Dharma signature & user signature from combined signatures argument. if (signatures.length != 130) { revert(_revertReason(11)); } bytes memory signaturesInMemory = signatures; bytes32 r; bytes32 s; uint8 v; assembly { r := mload(add(signaturesInMemory, 0x20)) s := mload(add(signaturesInMemory, 0x40)) v := byte(0, mload(add(signaturesInMemory, 0x60))) } bytes memory dharmaSignature = abi.encodePacked(r, s, v); assembly { r := mload(add(signaturesInMemory, 0x61)) s := mload(add(signaturesInMemory, 0x81)) v := byte(0, mload(add(signaturesInMemory, 0xa1))) } bytes memory userSignature = abi.encodePacked(r, s, v); // Validate user signature with `SignatureVerification` as the action type. if ( !_validateUserSignature( digest, ActionType.SignatureVerification, context, _userSigningKey, userSignature ) ) { revert(_revertReason(12)); } // Recover Dharma signature against key returned from Dharma Key Registry. if (_getDharmaSigningKey() != digest.recover(dharmaSignature)) { revert(_revertReason(13)); } // Return the ERC-1271 magic value to indicate success. magicValue = _ERC_1271_MAGIC_VALUE; } /** * @notice View function for getting the current Dharma Smart Wallet * implementation contract address set on the upgrade beacon. * @return The current Dharma Smart Wallet implementation contract. */ function getImplementation() external view returns (address implementation) { (bool ok, bytes memory returnData) = address( 0x000000000026750c571ce882B17016557279ADaa ).staticcall(""); require(ok && returnData.length == 32, "Invalid implementation."); implementation = abi.decode(returnData, (address)); } /** * @notice Pure function for getting the current Dharma Smart Wallet version. * @return The current Dharma Smart Wallet version. */ function getVersion() external pure returns (uint256 version) { version = _DHARMA_SMART_WALLET_VERSION; } /** * @notice Perform a series of generic calls to other contracts. If any call * fails during execution, the preceding calls will be rolled back, but their * original return data will still be accessible. Calls that would otherwise * occur after the failed call will not be executed. Note that accounts with * no code may not be specified, nor may the smart wallet itself or the escape * hatch registry. In order to increment the nonce and invalidate the * signatures, a call to this function with valid targets, signatutes, and gas * will always succeed. To determine whether each call made as part of the * action was successful or not, either the corresponding return value or the * corresponding `CallSuccess` or `CallFailure` event can be used - note that * even calls that return a success status will have been rolled back unless * all of the calls returned a success status. Finally, note that this * function must currently be implemented as a public function (instead of as * an external one) due to an ABIEncoderV2 `UnimplementedFeatureError`. * @param calls Call[] A struct containing the target and calldata to provide * when making each call. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. * @return An array of structs signifying the status of each call, as well as * any data returned from that call. Calls that are not executed will return * empty data. */ function executeActionWithAtomicBatchCalls( Call[] memory calls, uint256 minimumActionGas, bytes memory userSignature, bytes memory dharmaSignature ) public returns (bool[] memory ok, bytes[] memory returnData) { // Ensure that each `to` address is a contract and is not this contract. for (uint256 i = 0; i < calls.length; i++) { _ensureValidGenericCallTarget(calls[i].to); } // Ensure caller and/or supplied signatures are valid and increment nonce. (bytes32 actionID, uint256 nonce) = _validateActionAndIncrementNonce( ActionType.GenericAtomicBatch, abi.encode(calls), minimumActionGas, userSignature, dharmaSignature ); // Note: from this point on, there are no reverts (apart from out-of-gas or // call-depth-exceeded) originating from this contract. However, one of the // calls may revert, in which case the function will return `false`, along // with the revert reason encoded as bytes, and fire an CallFailure event. // Specify length of returned values in order to work with them in memory. ok = new bool[](calls.length); returnData = new bytes[](calls.length); // Set self-call context to call _executeActionWithAtomicBatchCallsAtomic. _selfCallContext = this.executeActionWithAtomicBatchCalls.selector; // Make the atomic self-call - if any call fails, calls that preceded it // will be rolled back and calls that follow it will not be made. (bool externalOk, bytes memory rawCallResults) = address(this).call( abi.encodeWithSelector( this._executeActionWithAtomicBatchCallsAtomic.selector, calls ) ); // Parse data returned from self-call into each call result and store / log. CallReturn[] memory callResults = abi.decode(rawCallResults, (CallReturn[])); for (uint256 i = 0; i < callResults.length; i++) { Call memory currentCall = calls[i]; // Set the status and the return data / revert reason from the call. ok[i] = callResults[i].ok; returnData[i] = callResults[i].returnData; // Emit CallSuccess or CallFailure event based on the outcome of the call. if (callResults[i].ok) { // Note: while the call succeeded, the action may still have "failed". emit CallSuccess( actionID, !externalOk, // If another call failed this will have been rolled back nonce, currentCall.to, currentCall.data, callResults[i].returnData ); } else { // Note: while the call failed, the nonce will still be incremented, // which will invalidate all supplied signatures. emit CallFailure( actionID, nonce, currentCall.to, currentCall.data, string(callResults[i].returnData) ); // exit early - any calls after the first failed call will not execute. break; } } } /** * @notice Protected function that can only be called from * `executeActionWithAtomicBatchCalls` on this contract. It will attempt to * perform each specified call, populating the array of results as it goes, * unless a failure occurs, at which point it will revert and "return" the * array of results as revert data. Otherwise, it will simply return the array * upon successful completion of each call. Finally, note that this function * must currently be implemented as a public function (instead of as an * external one) due to an ABIEncoderV2 `UnimplementedFeatureError`. * @param calls Call[] A struct containing the target and calldata to provide * when making each call. * @return An array of structs signifying the status of each call, as well as * any data returned from that call. Calls that are not executed will return * empty data. If any of the calls fail, the array will be returned as revert * data. */ function _executeActionWithAtomicBatchCallsAtomic( Call[] memory calls ) public returns (CallReturn[] memory callResults) { // Ensure caller is this contract and self-call context is correctly set. _enforceSelfCallFrom(this.executeActionWithAtomicBatchCalls.selector); bool rollBack = false; callResults = new CallReturn[](calls.length); for (uint256 i = 0; i < calls.length; i++) { // Perform low-level call and set return values using result. (bool ok, bytes memory returnData) = calls[i].to.call(calls[i].data); callResults[i] = CallReturn({ok: ok, returnData: returnData}); if (!ok) { // Exit early - any calls after the first failed call will not execute. rollBack = true; break; } } if (rollBack) { // Wrap in length encoding and revert (provide data instead of a string). bytes memory callResultsBytes = abi.encode(callResults); assembly { revert(add(32, callResultsBytes), mload(callResultsBytes)) } } } /** * @notice View function that, given an action type and arguments, will return * the action ID or message hash that will need to be prefixed (according to * EIP-191 0x45), hashed, and signed by both the user signing key and by the * key returned for this smart wallet by the Dharma Key Registry in order to * construct a valid signature for a given generic atomic batch action. The * current nonce will be used, which means that it will only be valid for the * next action taken. Finally, note that this function must currently be * implemented as a public function (instead of as an external one) due to an * ABIEncoderV2 `UnimplementedFeatureError`. * @param calls Call[] A struct containing the target and calldata to provide * when making each call. * @param calls Call[] A struct containing the target and calldata to provide * when making each call. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @return The action ID, which will need to be prefixed, hashed and signed in * order to construct a valid signature. */ function getNextGenericAtomicBatchActionID( Call[] memory calls, uint256 minimumActionGas ) public view returns (bytes32 actionID) { // Determine the actionID - this serves as a signature hash for an action. actionID = _getActionID( ActionType.GenericAtomicBatch, abi.encode(calls), _nonce, minimumActionGas, _userSigningKey, _getDharmaSigningKey() ); } /** * @notice View function that, given an action type and arguments, will return * the action ID or message hash that will need to be prefixed (according to * EIP-191 0x45), hashed, and signed by both the user signing key and by the * key returned for this smart wallet by the Dharma Key Registry in order to * construct a valid signature for a given generic atomic batch action. Any * nonce value may be supplied, which enables constructing valid message * hashes for multiple future actions ahead of time. Finally, note that this * function must currently be implemented as a public function (instead of as * an external one) due to an ABIEncoderV2 `UnimplementedFeatureError`. * @param calls Call[] A struct containing the target and calldata to provide * when making each call. * @param calls Call[] A struct containing the target and calldata to provide * when making each call. * @param nonce uint256 The nonce to use. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @return The action ID, which will need to be prefixed, hashed and signed in * order to construct a valid signature. */ function getGenericAtomicBatchActionID( Call[] memory calls, uint256 nonce, uint256 minimumActionGas ) public view returns (bytes32 actionID) { // Determine the actionID - this serves as a signature hash for an action. actionID = _getActionID( ActionType.GenericAtomicBatch, abi.encode(calls), nonce, minimumActionGas, _userSigningKey, _getDharmaSigningKey() ); } /** * @notice Internal function for setting a new user signing key. Called by the * initializer, by the `setUserSigningKey` function, and by the `recover` * function. A `NewUserSigningKey` event will also be emitted. * @param userSigningKey address The new user signing key to set on this smart * wallet. */ function _setUserSigningKey(address userSigningKey) internal { // Ensure that a user signing key is set on this smart wallet. if (userSigningKey == address(0)) { revert(_revertReason(14)); } _userSigningKey = userSigningKey; emit NewUserSigningKey(userSigningKey); } /** * @notice Internal function for setting the allowance of a given ERC20 asset * to the maximum value. This enables the corresponding dToken for the asset * to pull in tokens in order to make deposits. * @param asset uint256 The ID of the asset, either Dai (0) or USDC (1). * @return True if the approval succeeded, otherwise false. */ function _setFullApproval(AssetType asset) internal returns (bool ok) { // Get asset's underlying token address and corresponding dToken address. address token; address dToken; if (asset == AssetType.DAI) { token = address(_DAI); dToken = address(_DDAI); } else { token = address(_USDC); dToken = address(_DUSDC); } // Approve dToken contract to transfer underlying on behalf of this wallet. (ok, ) = address(token).call(abi.encodeWithSelector( // Note: since both Tokens have the same interface, just use DAI's. _DAI.approve.selector, dToken, uint256(-1) )); // Emit a corresponding event if the approval failed. if (!ok) { if (asset == AssetType.DAI) { emit ExternalError(address(_DAI), _revertReason(17)); } else { // Find out why USDC transfer reverted (it doesn't give revert reasons). _diagnoseAndEmitUSDCSpecificError(_USDC.approve.selector); } } } /** * @notice Internal function for depositing a given ERC20 asset and balance on * the corresponding dToken. No value is returned, as no additional steps need * to be conditionally performed after the deposit. * @param asset uint256 The ID of the asset, either Dai (0) or USDC (1). * @param balance uint256 The amount of the asset to deposit. Note that an * attempt to deposit "dust" (i.e. very small amounts) may result in fewer * dTokens being minted than is implied by the current exchange rate due to a * lack of sufficient precision on the tokens in question. USDC deposits are * also dependent on a flag being set on the Configuration Registry contract. */ function _depositDharmaToken(AssetType asset, uint256 balance) internal { // Only perform a deposit if the balance is at least .001 Dai or USDC. if ( asset == AssetType.DAI && balance > _JUST_UNDER_ONE_1000th_DAI || asset == AssetType.USDC && ( balance > _JUST_UNDER_ONE_1000th_USDC && uint256(_CONFIG_REGISTRY.get(_ENABLE_USDC_MINTING_KEY)) != 0 ) ) { // Get dToken address for the asset type. address dToken = asset == AssetType.DAI ? address(_DDAI) : address(_DUSDC); // Attempt to mint the balance on the dToken contract. (bool ok, bytes memory data) = dToken.call(abi.encodeWithSelector( // Note: since both dTokens have the same interface, just use dDai's. _DDAI.mint.selector, balance )); // Log an external error if something went wrong with the attempt. _checkDharmaTokenInteractionAndLogAnyErrors( asset, _DDAI.mint.selector, ok, data ); } } /** * @notice Internal function for withdrawing a given underlying asset balance * from the corresponding dToken. Note that the requested balance may not be * currently available on Compound, which will cause the withdrawal to fail. * @param asset uint256 The asset's ID, either Dai (0) or USDC (1). * @param balance uint256 The amount of the asset to withdraw, denominated in * the underlying token. Note that an attempt to withdraw "dust" (i.e. very * small amounts) may result in 0 underlying tokens being redeemed, or in * fewer tokens being redeemed than is implied by the current exchange rate * (due to lack of sufficient precision on the tokens). * @return True if the withdrawal succeeded, otherwise false. */ function _withdrawFromDharmaToken( AssetType asset, uint256 balance ) internal returns (bool success) { // Get dToken address for the asset type. (No custom ETH withdrawal action.) address dToken = asset == AssetType.DAI ? address(_DDAI) : address(_DUSDC); // Attempt to redeem the underlying balance from the dToken contract. (bool ok, bytes memory data) = dToken.call(abi.encodeWithSelector( // Note: function selector is the same for each dToken so just use dDai's. _DDAI.redeemUnderlying.selector, balance )); // Log an external error if something went wrong with the attempt. success = _checkDharmaTokenInteractionAndLogAnyErrors( asset, _DDAI.redeemUnderlying.selector, ok, data ); } /** * @notice Internal function for withdrawing the total underlying asset * balance from the corresponding dToken. Note that the requested balance may * not be currently available on Compound, which will cause the withdrawal to * fail. * @param asset uint256 The asset's ID, either Dai (0) or USDC (1). */ function _withdrawMaxFromDharmaToken(AssetType asset) internal { // Get dToken address for the asset type. (No custom ETH withdrawal action.) address dToken = asset == AssetType.DAI ? address(_DDAI) : address(_DUSDC); // Try to retrieve the current dToken balance for this account. ERC20Interface dTokenBalance; (bool ok, bytes memory data) = dToken.call(abi.encodeWithSelector( dTokenBalance.balanceOf.selector, address(this) )); uint256 redeemAmount = 0; if (ok && data.length == 32) { redeemAmount = abi.decode(data, (uint256)); } else { // Something went wrong with the balance check - log an ExternalError. _checkDharmaTokenInteractionAndLogAnyErrors( asset, dTokenBalance.balanceOf.selector, ok, data ); } // Only perform the call to redeem if there is a non-zero balance. if (redeemAmount > 0) { // Attempt to redeem the underlying balance from the dToken contract. (ok, data) = dToken.call(abi.encodeWithSelector( // Function selector is the same for all dTokens, so just use dDai's. _DDAI.redeem.selector, redeemAmount )); // Log an external error if something went wrong with the attempt. _checkDharmaTokenInteractionAndLogAnyErrors( asset, _DDAI.redeem.selector, ok, data ); } } /** * @notice Internal function for transferring the total underlying balance of * the corresponding token to a designated recipient. It will return true if * tokens were successfully transferred (or there is no balance), signified by * the boolean returned by the transfer function, or the call status if the * `suppressRevert` boolean is set to true. * @param token IERC20 The interface of the token in question. * @param recipient address The account that will receive the tokens. * @param suppressRevert bool A boolean indicating whether reverts should be * suppressed or not. Used by the escape hatch so that a problematic transfer * will not block the rest of the call from executing. * @return True if tokens were successfully transferred or if there is no * balance, else false. */ function _transferMax( ERC20Interface token, address recipient, bool suppressRevert ) internal returns (bool success) { // Get the current balance on the smart wallet for the supplied ERC20 token. uint256 balance = 0; bool balanceCheckWorked = true; if (!suppressRevert) { balance = token.balanceOf(address(this)); } else { // Try to retrieve current token balance for this account with 1/2 gas. (bool ok, bytes memory data) = address(token).call.gas(gasleft() / 2)( abi.encodeWithSelector(token.balanceOf.selector, address(this)) ); if (ok && data.length == 32) { balance = abi.decode(data, (uint256)); } else { // Something went wrong with the balance check. balanceCheckWorked = false; } } // Only perform the call to transfer if there is a non-zero balance. if (balance > 0) { if (!suppressRevert) { // Perform the transfer and pass along the returned boolean (or revert). success = token.transfer(recipient, balance); } else { // Attempt transfer with 1/2 gas, allow reverts, and return call status. (success, ) = address(token).call.gas(gasleft() / 2)( abi.encodeWithSelector(token.transfer.selector, recipient, balance) ); } } else { // Skip the transfer and return true as long as the balance check worked. success = balanceCheckWorked; } } /** * @notice Internal function for transferring Ether to a designated recipient. * It will return true and emit an `EthWithdrawal` event if Ether was * successfully transferred - otherwise, it will return false and emit an * `ExternalError` event. * @param recipient address payable The account that will receive the Ether. * @param amount uint256 The amount of Ether to transfer. * @return True if Ether was successfully transferred, else false. */ function _transferETH( address payable recipient, uint256 amount ) internal returns (bool success) { // Attempt to transfer any Ether to caller and emit an event if it fails. (success, ) = recipient.call.gas(_ETH_TRANSFER_GAS).value(amount)(""); if (!success) { emit ExternalError(recipient, _revertReason(18)); } else { emit EthWithdrawal(amount, recipient); } } /** * @notice Internal function for validating supplied gas (if specified), * retrieving the signer's public key from the Dharma Key Registry, deriving * the action ID, validating the provided caller and/or signatures using that * action ID, and incrementing the nonce. This function serves as the * entrypoint for all protected "actions" on the smart wallet, and is the only * area where these functions should revert (other than due to out-of-gas * errors, which can be guarded against by supplying a minimum action gas * requirement). * @param action uint8 The type of action, designated by it's index. Valid * actions in V8 include Cancel (0), SetUserSigningKey (1), Generic (2), * GenericAtomicBatch (3), DAIWithdrawal (10), USDCWithdrawal (5), * ETHWithdrawal (6), SetEscapeHatch (7), RemoveEscapeHatch (8), and * DisableEscapeHatch (9). * @param arguments bytes ABI-encoded arguments for the action. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. A unique hash returned from `getCustomActionID` is prefixed * and hashed to create the message hash for the signature. * @param dharmaSignature bytes A signature that resolves to the public key * returned for this account from the Dharma Key Registry. A unique hash * returned from `getCustomActionID` is prefixed and hashed to create the * signed message. * @return The nonce of the current action (prior to incrementing it). */ function _validateActionAndIncrementNonce( ActionType action, bytes memory arguments, uint256 minimumActionGas, bytes memory userSignature, bytes memory dharmaSignature ) internal returns (bytes32 actionID, uint256 actionNonce) { // Ensure that the current gas exceeds the minimum required action gas. // This prevents griefing attacks where an attacker can invalidate a // signature without providing enough gas for the action to succeed. Also // note that some gas will be spent before this check is reached - supplying // ~30,000 additional gas should suffice when submitting transactions. To // skip this requirement, supply zero for the minimumActionGas argument. if (minimumActionGas != 0) { if (gasleft() < minimumActionGas) { revert(_revertReason(19)); } } // Get the current nonce for the action to be performed. actionNonce = _nonce; // Get the user signing key that will be used to verify their signature. address userSigningKey = _userSigningKey; // Get the Dharma signing key that will be used to verify their signature. address dharmaSigningKey = _getDharmaSigningKey(); // Determine the actionID - this serves as the signature hash. actionID = _getActionID( action, arguments, actionNonce, minimumActionGas, userSigningKey, dharmaSigningKey ); // Compute the message hash - the hashed, EIP-191-0x45-prefixed action ID. bytes32 messageHash = actionID.toEthSignedMessageHash(); // Actions other than Cancel require both signatures; Cancel only needs one. if (action != ActionType.Cancel) { // Validate user signing key signature unless it is `msg.sender`. if (msg.sender != userSigningKey) { if ( !_validateUserSignature( messageHash, action, arguments, userSigningKey, userSignature ) ) { revert(_revertReason(20)); } } // Validate Dharma signing key signature unless it is `msg.sender`. if (msg.sender != dharmaSigningKey) { if (dharmaSigningKey != messageHash.recover(dharmaSignature)) { revert(_revertReason(21)); } } } else { // Validate signing key signature unless user or Dharma is `msg.sender`. if (msg.sender != userSigningKey && msg.sender != dharmaSigningKey) { if ( dharmaSigningKey != messageHash.recover(dharmaSignature) && !_validateUserSignature( messageHash, action, arguments, userSigningKey, userSignature ) ) { revert(_revertReason(22)); } } } // Increment nonce in order to prevent reuse of signatures after the call. _nonce++; } /** * @notice Use all available cTokens to mint the respective dTokens. If any * step in the process fails, the call will revert and prior steps will be * rolled back. Also note that existing underlying tokens are not included as * part of this operation. */ function _migrateCTokenToDToken(AssetType token) internal { CTokenInterface cToken; DTokenInterface dToken; if (token == AssetType.DAI) { cToken = _CDAI; dToken = _DDAI; } else { cToken = _CUSDC; dToken = _DUSDC; } // Get the current cToken balance for this account. uint256 balance = cToken.balanceOf(address(this)); // Only perform the conversion if there is a non-zero balance. if (balance > 0) { // If the allowance is insufficient, set it before depositing. if (cToken.allowance(address(this), address(dToken)) < balance) { if (!cToken.approve(address(dToken), uint256(-1))) { revert(_revertReason(23)); } } // Deposit the new balance on the Dharma Token. if (dToken.mintViaCToken(balance) == 0) { revert(_revertReason(24)); } } } /** * @notice Internal function to determine whether a call to a given dToken * succeeded, and to emit a relevant ExternalError event if it failed. * @param asset uint256 The ID of the asset, either Dai (0) or USDC (1). * @param functionSelector bytes4 The function selector that was called on the * corresponding dToken of the asset type. * @param ok bool A boolean representing whether the call returned or * reverted. * @param data bytes The data provided by the returned or reverted call. * @return True if the interaction was successful, otherwise false. This will * be used to determine if subsequent steps in the action should be attempted * or not, specifically a transfer following a withdrawal. */ function _checkDharmaTokenInteractionAndLogAnyErrors( AssetType asset, bytes4 functionSelector, bool ok, bytes memory data ) internal returns (bool success) { // Log an external error if something went wrong with the attempt. if (ok) { if (data.length == 32) { uint256 amount = abi.decode(data, (uint256)); if (amount > 0) { success = true; } else { // Get called contract address, name of contract, and function name. (address account, string memory name, string memory functionName) = ( _getDharmaTokenDetails(asset, functionSelector) ); emit ExternalError( account, string( abi.encodePacked( name, " gave no tokens calling ", functionName, "." ) ) ); } } else { // Get called contract address, name of contract, and function name. (address account, string memory name, string memory functionName) = ( _getDharmaTokenDetails(asset, functionSelector) ); emit ExternalError( account, string( abi.encodePacked( name, " gave bad data calling ", functionName, "." ) ) ); } } else { // Get called contract address, name of contract, and function name. (address account, string memory name, string memory functionName) = ( _getDharmaTokenDetails(asset, functionSelector) ); // Decode the revert reason in the event one was returned. string memory revertReason = _decodeRevertReason(data); emit ExternalError( account, string( abi.encodePacked( name, " reverted calling ", functionName, ": ", revertReason ) ) ); } } /** * @notice Internal function to diagnose the reason that a call to the USDC * contract failed and to emit a corresponding ExternalError event. USDC can * blacklist accounts and pause the contract, which can both cause a transfer * or approval to fail. * @param functionSelector bytes4 The function selector that was called on the * USDC contract. */ function _diagnoseAndEmitUSDCSpecificError(bytes4 functionSelector) internal { // Determine the name of the function that was called on USDC. string memory functionName; if (functionSelector == _USDC.transfer.selector) { functionName = "transfer"; } else { functionName = "approve"; } USDCV1Interface usdcNaughty = USDCV1Interface(address(_USDC)); // Find out why USDC transfer reverted (it doesn't give revert reasons). if (usdcNaughty.isBlacklisted(address(this))) { emit ExternalError( address(_USDC), string( abi.encodePacked( functionName, " failed - USDC has blacklisted this user." ) ) ); } else { // Note: `else if` breaks coverage. if (usdcNaughty.paused()) { emit ExternalError( address(_USDC), string( abi.encodePacked( functionName, " failed - USDC contract is currently paused." ) ) ); } else { emit ExternalError( address(_USDC), string( abi.encodePacked( "USDC contract reverted on ", functionName, "." ) ) ); } } } /** * @notice Internal function to ensure that protected functions can only be * called from this contract and that they have the appropriate context set. * The self-call context is then cleared. It is used as an additional guard * against reentrancy, especially once generic actions are supported by the * smart wallet in future versions. * @param selfCallContext bytes4 The expected self-call context, equal to the * function selector of the approved calling function. */ function _enforceSelfCallFrom(bytes4 selfCallContext) internal { // Ensure caller is this contract and self-call context is correctly set. if (msg.sender != address(this) || _selfCallContext != selfCallContext) { revert(_revertReason(25)); } // Clear the self-call context. delete _selfCallContext; } /** * @notice Internal view function for validating a user's signature. If the * user's signing key does not have contract code, it will be validated via * ecrecover; otherwise, it will be validated using ERC-1271, passing the * message hash that was signed, the action type, and the arguments as data. * @param messageHash bytes32 The message hash that is signed by the user. It * is derived by prefixing (according to EIP-191 0x45) and hashing an actionID * returned from `getCustomActionID`. * @param action uint8 The type of action, designated by it's index. Valid * actions in V8 include Cancel (0), SetUserSigningKey (1), Generic (2), * GenericAtomicBatch (3), DAIWithdrawal (10), USDCWithdrawal (5), * ETHWithdrawal (6), SetEscapeHatch (7), RemoveEscapeHatch (8), and * DisableEscapeHatch (9). * @param arguments bytes ABI-encoded arguments for the action. * @param userSignature bytes A signature that resolves to the public key * set for this account in storage slot zero, `_userSigningKey`. If the user * signing key is not a contract, ecrecover will be used; otherwise, ERC1271 * will be used. * @return A boolean representing the validity of the supplied user signature. */ function _validateUserSignature( bytes32 messageHash, ActionType action, bytes memory arguments, address userSigningKey, bytes memory userSignature ) internal view returns (bool valid) { if (!userSigningKey.isContract()) { valid = userSigningKey == messageHash.recover(userSignature); } else { bytes memory data = abi.encode(messageHash, action, arguments); valid = ( ERC1271Interface(userSigningKey).isValidSignature( data, userSignature ) == _ERC_1271_MAGIC_VALUE ); } } /** * @notice Internal view function to get the Dharma signing key for the smart * wallet from the Dharma Key Registry. This key can be set for each specific * smart wallet - if none has been set, a global fallback key will be used. * @return The address of the Dharma signing key, or public key corresponding * to the secondary signer. */ function _getDharmaSigningKey() internal view returns ( address dharmaSigningKey ) { dharmaSigningKey = _DHARMA_KEY_REGISTRY.getKey(); } /** * @notice Internal view function that, given an action type and arguments, * will return the action ID or message hash that will need to be prefixed * (according to EIP-191 0x45), hashed, and signed by the key designated by * the Dharma Key Registry in order to construct a valid signature for the * corresponding action. The current nonce will be supplied to this function * when reconstructing an action ID during protected function execution based * on the supplied parameters. * @param action uint8 The type of action, designated by it's index. Valid * actions in V8 include Cancel (0), SetUserSigningKey (1), Generic (2), * GenericAtomicBatch (3), DAIWithdrawal (10), USDCWithdrawal (5), * ETHWithdrawal (6), SetEscapeHatch (7), RemoveEscapeHatch (8), and * DisableEscapeHatch (9). * @param arguments bytes ABI-encoded arguments for the action. * @param nonce uint256 The nonce to use. * @param minimumActionGas uint256 The minimum amount of gas that must be * provided to this call - be aware that additional gas must still be included * to account for the cost of overhead incurred up until the start of this * function call. * @param dharmaSigningKey address The address of the secondary key, or public * key corresponding to the secondary signer. * @return The action ID, which will need to be prefixed, hashed and signed in * order to construct a valid signature. */ function _getActionID( ActionType action, bytes memory arguments, uint256 nonce, uint256 minimumActionGas, address userSigningKey, address dharmaSigningKey ) internal view returns (bytes32 actionID) { // actionID is constructed according to EIP-191-0x45 to prevent replays. actionID = keccak256( abi.encodePacked( address(this), _DHARMA_SMART_WALLET_VERSION, userSigningKey, dharmaSigningKey, nonce, minimumActionGas, action, arguments ) ); } /** * @notice Internal pure function to get the dToken address, it's name, and * the name of the called function, based on a supplied asset type and * function selector. It is used to help construct ExternalError events. * @param asset uint256 The ID of the asset, either Dai (0) or USDC (1). * @param functionSelector bytes4 The function selector that was called on the * corresponding dToken of the asset type. * @return The dToken address, it's name, and the name of the called function. */ function _getDharmaTokenDetails( AssetType asset, bytes4 functionSelector ) internal pure returns ( address account, string memory name, string memory functionName ) { if (asset == AssetType.DAI) { account = address(_DDAI); name = "Dharma Dai"; } else { account = address(_DUSDC); name = "Dharma USD Coin"; } // Note: since both dTokens have the same interface, just use dDai's. if (functionSelector == _DDAI.mint.selector) { functionName = "mint"; } else { if (functionSelector == ERC20Interface(account).balanceOf.selector) { functionName = "balanceOf"; } else { functionName = string(abi.encodePacked( "redeem", functionSelector == _DDAI.redeem.selector ? "" : "Underlying" )); } } } /** * @notice Internal view function to ensure that a given `to` address provided * as part of a generic action is valid. Calls cannot be performed to accounts * without code or back into the smart wallet itself. Additionally, generic * calls cannot supply the address of the Dharma Escape Hatch registry - the * specific, designated functions must be used in order to make calls into it. * @param to address The address that will be targeted by the generic call. */ function _ensureValidGenericCallTarget(address to) internal view { if (!to.isContract()) { revert(_revertReason(26)); } if (to == address(this)) { revert(_revertReason(27)); } if (to == address(_ESCAPE_HATCH_REGISTRY)) { revert(_revertReason(28)); } } /** * @notice Internal pure function to ensure that a given action type is a * "custom" action type (i.e. is not a generic action type) and to construct * the "arguments" input to an actionID based on that action type. * @param action uint8 The type of action, designated by it's index. Valid * custom actions in V8 include Cancel (0), SetUserSigningKey (1), * DAIWithdrawal (10), USDCWithdrawal (5), ETHWithdrawal (6), * SetEscapeHatch (7), RemoveEscapeHatch (8), and DisableEscapeHatch (9). * @param amount uint256 The amount to withdraw for Withdrawal actions. This * value is ignored for all non-withdrawal action types. * @param recipient address The account to transfer withdrawn funds to or the * new user signing key. This value is ignored for Cancel, RemoveEscapeHatch, * and DisableEscapeHatch action types. * @return A bytes array containing the arguments that will be provided as * a component of the inputs when constructing a custom action ID. */ function _validateCustomActionTypeAndGetArguments( ActionType action, uint256 amount, address recipient ) internal pure returns (bytes memory arguments) { // Ensure that the action type is a valid custom action type. bool validActionType = ( action == ActionType.Cancel || action == ActionType.SetUserSigningKey || action == ActionType.DAIWithdrawal || action == ActionType.USDCWithdrawal || action == ActionType.ETHWithdrawal || action == ActionType.SetEscapeHatch || action == ActionType.RemoveEscapeHatch || action == ActionType.DisableEscapeHatch ); if (!validActionType) { revert(_revertReason(29)); } // Use action type to determine parameters to include in returned arguments. if ( action == ActionType.Cancel || action == ActionType.RemoveEscapeHatch || action == ActionType.DisableEscapeHatch ) { // Ignore parameters for Cancel, RemoveEscapeHatch, or DisableEscapeHatch. arguments = abi.encode(); } else if ( action == ActionType.SetUserSigningKey || action == ActionType.SetEscapeHatch ) { // Ignore `amount` parameter for other, non-withdrawal actions. arguments = abi.encode(recipient); } else { // Use both `amount` and `recipient` parameters for withdrawals. arguments = abi.encode(amount, recipient); } } /** * @notice Internal pure function to decode revert reasons. The revert reason * prefix is removed and the remaining string argument is decoded. * @param revertData bytes The raw data supplied alongside the revert. * @return The decoded revert reason string. */ function _decodeRevertReason( bytes memory revertData ) internal pure returns (string memory revertReason) { // Solidity prefixes revert reason with 0x08c379a0 -> Error(string) selector if ( revertData.length > 68 && // prefix (4) + position (32) + length (32) revertData[0] == byte(0x08) && revertData[1] == byte(0xc3) && revertData[2] == byte(0x79) && revertData[3] == byte(0xa0) ) { // Get the revert reason without the prefix from the revert data. bytes memory revertReasonBytes = new bytes(revertData.length - 4); for (uint256 i = 4; i < revertData.length; i++) { revertReasonBytes[i - 4] = revertData[i]; } // Decode the resultant revert reason as a string. revertReason = abi.decode(revertReasonBytes, (string)); } else { // Simply return the default, with no revert reason. revertReason = _revertReason(uint256(-1)); } } /** * @notice Internal pure function call the revert reason helper contract, * supplying a revert "code" and receiving back a revert reason string. * @param code uint256 The code for the revert reason. * @return The revert reason string. */ function _revertReason( uint256 code ) internal pure returns (string memory reason) { reason = _REVERT_REASON_HELPER.reason(code); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"actionID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"string","name":"revertReason","type":"string"}],"name":"CallFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"actionID","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"rolledBack","type":"bool"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"returnData","type":"bytes"}],"name":"CallSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"cancelledNonce","type":"uint256"}],"name":"Cancel","type":"event"},{"anonymous":false,"inputs":[],"name":"Escaped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"EthWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"string","name":"revertReason","type":"string"}],"name":"ExternalError","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userSigningKey","type":"address"}],"name":"NewUserSigningKey","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":false,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.Call[]","name":"calls","type":"tuple[]"}],"name":"_executeActionWithAtomicBatchCallsAtomic","outputs":[{"components":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.CallReturn[]","name":"callResults","type":"tuple[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"ethToSupply","type":"uint256"},{"internalType":"uint256","name":"minimumDaiReceived","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"_tradeEthForDaiAndMintDDaiAtomic","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"_withdrawDaiAtomic","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"_withdrawUSDCAtomic","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"cancel","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"escape","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"executeAction","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.Call[]","name":"calls","type":"tuple[]"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"executeActionWithAtomicBatchCalls","outputs":[{"internalType":"bool[]","name":"ok","type":"bool[]"},{"internalType":"bytes[]","name":"returnData","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBalances","outputs":[{"internalType":"uint256","name":"daiBalance","type":"uint256"},{"internalType":"uint256","name":"usdcBalance","type":"uint256"},{"internalType":"uint256","name":"etherBalance","type":"uint256"},{"internalType":"uint256","name":"dDaiUnderlyingDaiBalance","type":"uint256"},{"internalType":"uint256","name":"dUsdcUnderlyingUsdcBalance","type":"uint256"},{"internalType":"uint256","name":"dEtherUnderlyingEtherBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum DharmaSmartWalletImplementationV7Interface.ActionType","name":"action","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getCustomActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"ethToSupply","type":"uint256"},{"internalType":"uint256","name":"minimumDaiReceived","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getEthForDaiActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getGenericActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.Call[]","name":"calls","type":"tuple[]"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getGenericAtomicBatchActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"implementation","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"enum DharmaSmartWalletImplementationV7Interface.ActionType","name":"action","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getNextCustomActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"ethToSupply","type":"uint256"},{"internalType":"uint256","name":"minimumDaiReceived","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getNextEthForDaiActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getNextGenericActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct DharmaSmartWalletImplementationV1Interface.Call[]","name":"calls","type":"tuple[]"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"}],"name":"getNextGenericAtomicBatchActionID","outputs":[{"internalType":"bytes32","name":"actionID","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getUserSigningKey","outputs":[{"internalType":"address","name":"userSigningKey","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getVersion","outputs":[{"internalType":"uint256","name":"version","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"userSigningKey","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signatures","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"migrateCDaiToDDai","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"migrateCSaiToDDai","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"migrateCUSDCToDUSDC","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"migrateSaiToDai","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"permanentlyDisableEscapeHatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newUserSigningKey","type":"address"}],"name":"recover","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"removeEscapeHatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"repayAndDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"setEscapeHatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"userSigningKey","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"setUserSigningKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"ethToSupply","type":"uint256"},{"internalType":"uint256","name":"minimumDaiReceived","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"tradeEthForDaiAndMintDDai","outputs":[{"internalType":"bool","name":"ok","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"target","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"triggerEtherTransfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"withdrawDai","outputs":[{"internalType":"bool","name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"withdrawEther","outputs":[{"internalType":"bool","name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"minimumActionGas","type":"uint256"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"bytes","name":"dharmaSignature","type":"bytes"}],"name":"withdrawUSDC","outputs":[{"internalType":"bool","name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405180606001604052806025815260200162005c856025913980516020909101207f596746115f08448433597980d42b4541c0197187d07ffad9c7f66a471c49dbba146200005d57fe5b615c18806200006d6000396000f3fe6080604052600436106102245760003560e01c8063a553d94111610123578063c77a1594116100ab578063ec9e14d41161006f578063ec9e14d41461064e578063f05fe81a1461067b578063fbaf10e314610690578063fc522bce146106b0578063fd8137d61461047757610224565b8063c77a1594146105c4578063cc90530a146105e4578063d087d28814610604578063d180667d14610619578063d771d75a1461062e57610224565b8063ae0f1f33116100f2578063ae0f1f3314610516578063b3461f2f14610536578063b848821d14610564578063baf260e114610584578063c4d66de8146105a457610224565b8063a553d941146104ac578063aaf10f42146104cc578063ab8ac8fd146104e1578063ad67283b1461050157610224565b8063550c9f36116101b157806381a078d01161017557806381a078d0146104155780638c5bf80f146104375780638cf422b514610457578063974f302114610477578063a3ccb2801461048c57610224565b8063550c9f36146103735780635a0d31f7146103935780635d8f1661146103a8578063680a3423146103c85780638016b320146103f557610224565b8063168d88b9116101f8578063168d88b9146102b85780631c9e742e146102e657806320c13b0b1461030657806344f62b3c146103335780634b3622021461035357610224565b8062113e0814610226578063094ed15e146102565780630cd865ec146102835780630d8e6e2c146102a3575b005b34801561023257600080fd5b5061023b6106d0565b60405161024d969594939291906159d9565b60405180910390f35b34801561026257600080fd5b50610276610271366004614c5c565b61090a565b60405161024d9190615712565b34801561028f57600080fd5b5061022461029e3660046143a3565b610963565b3480156102af57600080fd5b506102766109b9565b3480156102c457600080fd5b506102d86102d33660046146fa565b6109be565b60405161024d92919061569d565b3480156102f257600080fd5b50610224610301366004614b20565b610cf1565b34801561031257600080fd5b506103266103213660046148e5565b610db0565b60405161024d91906158e3565b34801561033f57600080fd5b5061022461034e3660046145c6565b610f3e565b34801561035f57600080fd5b5061027661036e366004614dd9565b610fe0565b34801561037f57600080fd5b5061022461038e366004614b75565b611034565b34801561039f57600080fd5b5061022461111b565b3480156103b457600080fd5b506102766103c33660046146c5565b611127565b3480156103d457600080fd5b506103e86103e3366004614a74565b611146565b60405161024d91906156e4565b34801561040157600080fd5b506102766104103660046149a8565b6112fd565b34801561042157600080fd5b5061042a611330565b60405161024d919061562a565b34801561044357600080fd5b50610276610452366004614419565b61133f565b34801561046357600080fd5b50610276610472366004614549565b611364565b34801561048357600080fd5b50610224611380565b34801561049857600080fd5b506102246104a7366004614b75565b611385565b3480156104b857600080fd5b506103e86104c7366004614a74565b61144d565b3480156104d857600080fd5b5061042a61149a565b3480156104ed57600080fd5b506103e86104fc366004614a44565b61154e565b34801561050d57600080fd5b50610224611657565b34801561052257600080fd5b506103e8610531366004614a44565b611661565b34801561054257600080fd5b50610556610551366004614ceb565b6116f1565b60405161024d9291906156f2565b34801561057057600080fd5b5061022461057f3660046145c6565b6118d6565b34801561059057600080fd5b506103e861059f366004614a74565b611972565b3480156105b057600080fd5b506102246105bf3660046143a3565b611ac5565b3480156105d057600080fd5b506105566105df366004614482565b611c2c565b3480156105f057600080fd5b506103e86105ff3660046143df565b611dd5565b34801561061057600080fd5b50610276611e7e565b34801561062557600080fd5b50610224611e84565b34801561063a57600080fd5b50610276610649366004614793565b612044565b34801561065a57600080fd5b5061066e610669366004614691565b612064565b60405161024d91906156c2565b34801561068757600080fd5b506102246121d4565b34801561069c57600080fd5b506105566106ab366004614bfa565b61249d565b3480156106bc57600080fd5b506102766106cb366004614953565b61256f565b600080600080600080736b175474e89094c44da98b954eedeac495271d0f6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016107199190615638565b60206040518083038186803b15801561073157600080fd5b505afa158015610745573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107699190810190614862565b6040516370a0823160e01b815290965073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a08231906107a3903090600401615638565b60206040518083038186803b1580156107bb57600080fd5b505afa1580156107cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107f39190810190614862565b604051633af9e66960e01b81529095504794506e1876eb1444c986fd502e618c58743090633af9e6699061082b903090600401615638565b60206040518083038186803b15801561084357600080fd5b505afa158015610857573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061087b9190810190614862565b604051633af9e66960e01b81529093506e8943c65caf789fffcf953be156f6f890633af9e669906108b0903090600401615638565b60206040518083038186803b1580156108c857600080fd5b505afa1580156108dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109009190810190614862565b9150909192939495565b6000610958600c888888888860405160200161092a95949392919061599e565b60408051601f1981840301815291905260015460005486906001600160a01b0316610953612595565b61261d565b979650505050505050565b336edfed903ad76996fc07bf89c0127b1e146109a5576109836008612661565b60405162461bcd60e51b815260040161099c9190615916565b60405180910390fd5b60018054810190556109b6816126ef565b50565b600a90565b60608060005b86518110156109f5576109ed8782815181106109dc57fe5b60200260200101516000015161275d565b6001016109c4565b50600080610a26600389604051602001610a0f91906156d3565b6040516020818303038152906040528989896127c2565b915091508751604051908082528060200260200182016040528015610a55578160200160208202803883390190505b5093508751604051908082528060200260200182016040528015610a8d57816020015b6060815260200190600190039081610a785790505b506002805463ffffffff191663168d88b91790556040519093506000906060903090633b27853560e21b90610ac6908d906024016156d3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610b04919061550d565b6000604051808303816000865af19150503d8060008114610b41576040519150601f19603f3d011682016040523d82523d6000602084013e610b46565b606091505b5091509150606081806020019051610b61919081019061465d565b905060005b8151811015610ce257610b776140e8565b8c8281518110610b8357fe5b60200260200101519050828281518110610b9957fe5b602002602001015160000151898381518110610bb157fe5b602002602001019015159081151581525050828281518110610bcf57fe5b602002602001015160200151888381518110610be757fe5b6020026020010181905250828281518110610bfe57fe5b60200260200101516000015115610c75577fb4a7946c0772f99411b9461db61ae510087dfb48bc453a75b0b9915588f0c5cc8786158884600001518560200151888881518110610c4a57fe5b602002602001015160200151604051610c6896959493929190615789565b60405180910390a1610cd9565b7f66d25ad42aacf4cb4fd83716d3ee5ba48cddbe69bf2028b574a8510432c0afcb878783600001518460200151878781518110610cae57fe5b602002602001015160200151604051610ccb959493929190615860565b60405180910390a150610ce2565b50600101610b66565b50505050505094509492505050565b6001546040805160008082526020601f860181900481028301840184528201858152610d7193919291889190889088908190860183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506127c292505050565b50507f8bf30e7ff26833413be5f69e1d373744864d600b664204b4a2f9844a8eedb9ed81604051610da29190615712565b60405180910390a150505050565b60008060606020861415610dd157610dca86880188614844565b9150610df6565b6040861015610de457610983601e612661565b610df086880188614880565b90925090505b60828414610e0857610983600b612661565b606085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506020808601516040808801516060808a01519251999a509298909750931a94509250610e6e91869186918691016154c9565b6040516020818303038152906040529050606185015193506081850151925060a185015160001a91506060848484604051602001610eae939291906154c9565b60408051601f19818403018152919052600054909150610ede908990600b908a906001600160a01b031685612923565b610eec57610983600c612661565b610efc888363ffffffff612a2416565b6001600160a01b0316610f0d612595565b6001600160a01b031614610f2557610983600d612661565b506320c13b0b60e01b9c9b505050505050505050505050565b610fcd600187604051602001610f54919061562a565b60408051601f198184030181526020601f8901819004810284018101909252878352918991899089908190840183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b5050610fd8866126ef565b505050505050565b6000611028600c898989898960405160200161100095949392919061599e565b60408051601f19818403018152919052600054869086906001600160a01b0316610953612595565b98975050505050505050565b60408051600081526020601f8601819004810282018301835281018581526110b092600892918991899089908190860183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b50506e5280b515004b998a944630b6c663f86001600160a01b0316635014b4f46040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156110fc57600080fd5b505af1158015611110573d6000803e3d6000fd5b505050505050505050565b6111256000612b00565b565b600061113f60038460405160200161092a91906156d3565b9392505050565b60006111d960058989604051602001611160929190615947565b60408051601f198184030181526020601f8a01819004810284018101909252888352918a918a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506127c292505050565b50506103e788116111ee576109836003612661565b6001600160a01b038716611206576109836001612661565b6002805463ffffffff191663680a3423179055604051606090309063ab8ac8fd60e01b9061123a908c908c90602401615947565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611278919061550d565b6000604051808303816000865af19150503d80600081146112b5576040519150601f19603f3d011682016040523d82523d6000602084013e6112ba565b606091505b509092509050816112da576112d563a9059cbb60e01b612d9b565b6112f1565b808060200190516112ee91908101906147f6565b91505b50979650505050505050565b60006113268661130e888888613007565b600054869086906001600160a01b0316610953612595565b9695505050505050565b6000546001600160a01b031690565b600061135b600286868660405160200161092a93929190615661565b95945050505050565b6000611326600287878760405160200161100093929190615661565b600080fd5b60408051600081526020601f86018190048102820183018352810185815261140192600992918991899089908190860183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b50506e5280b515004b998a944630b6c663f86001600160a01b031663f02fedc46040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156110fc57600080fd5b600061146760068989604051602001611160929190615947565b505087611478576109836004612661565b6001600160a01b038716611490576109836001612661565b6110288789613198565b60008060606e26750c571ce882b17016557279adaa6001600160a01b03166040516114c4906155fd565b600060405180830381855afa9150503d80600081146114ff576040519150601f19603f3d011682016040523d82523d6000602084013e611504565b606091505b5091509150818015611517575080516020145b6115335760405162461bcd60e51b815260040161099c90615937565b8080602001905161154791908101906143c1565b9250505090565b600061156063680a342360e01b61327e565b600019831480156115a75761157560016132bf565b61159573a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488460006134c1565b61159e57600080fd5b60019150611650565b6115b260018561379f565b156116505760405163a9059cbb60e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063a9059cbb906115f09086908890600401615682565b602060405180830381600087803b15801561160a57600080fd5b505af115801561161e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061164291908101906147f6565b61164b57600080fd5b600191505b5092915050565b6111256001612b00565b600061167363baf260e160e01b61327e565b600019831480156116a85761168860006132bf565b611595736b175474e89094c44da98b954eedeac495271d0f8460006134c1565b6116b360008561379f565b156116505760405163a9059cbb60e01b8152736b175474e89094c44da98b954eedeac495271d0f9063a9059cbb906115f09086908890600401615682565b6000606061178c600c8d8d8d8d8d60405160200161171395949392919061599e565b60408051601f198184030181526020601f8b01819004810284018101909252898352918b918b908b908190840183828082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a90819084018382808284376000920191909152506127c292505050565b505066038d7ea4c67fff8b116117a657610983601f612661565b63b3461f2f60e01b600260006101000a81548163ffffffff021916908360e01c02179055506060306001600160a01b031663fbaf10e360e01b8e8e8e8e8e6040516024016117f895949392919061599e565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611836919061550d565b6000604051808303816000865af19150503d8060008114611873576040519150601f19603f3d011682016040523d82523d6000602084013e611878565b606091505b509093509050826118c65773421816cdfe2073945173c0c35799ec21261fb399600080516020615bb68339815191526118b0836138a1565b6040516118bd9190615916565b60405180910390a25b509a509a98505050505050505050565b6118ec600787604051602001610f54919061562a565b50506001600160a01b038616611906576109836005612661565b604051630916bbc360e31b81526e5280b515004b998a944630b6c663f8906348b5de189061193890899060040161562a565b600060405180830381600087803b15801561195257600080fd5b505af1158015611966573d6000803e3d6000fd5b50505050505050505050565b600061198c600a8989604051602001611160929190615947565b505066038d7ea4c67fff88116119a6576109836000612661565b6001600160a01b0387166119be576109836001612661565b6002805463ffffffff191663baf260e1179055604051606090309063ae0f1f3360e01b906119f2908c908c90602401615947565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611a30919061550d565b6000604051808303816000865af19150503d8060008114611a6d576040519150601f19603f3d011682016040523d82523d6000602084013e611a72565b606091505b509092509050816112da57736b175474e89094c44da98b954eedeac495271d0f600080516020615bb6833981519152611aab6002612661565b604051611ab89190615916565b60405180910390a26112f1565b303b15611ad157600080fd5b611ada816126ef565b611ae46000613a11565b15611b82576040516370a0823160e01b8152600090736b175474e89094c44da98b954eedeac495271d0f906370a0823190611b23903090600401615638565b60206040518083038186803b158015611b3b57600080fd5b505afa158015611b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611b739190810190614862565b9050611b80600082613ba5565b505b611b8c6001613a11565b156109b6576040516370a0823160e01b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190611bcb903090600401615638565b60206040518083038186803b158015611be357600080fd5b505afa158015611bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611c1b9190810190614862565b9050611c28600182613ba5565b5050565b60006060611c398a61275d565b600080611ccf60028d8d8d604051602001611c5693929190615661565b60408051601f198184030181526020601f8d018190048102840181019092528b8352918d918d908d908190840183828082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c90819084018382808284376000920191909152506127c292505050565b915091508b6001600160a01b03168b8b604051611ced929190615500565b6000604051808303816000865af19150503d8060008114611d2a576040519150601f19603f3d011682016040523d82523d6000602084013e611d2f565b606091505b5090945092508315611d84577fb4a7946c0772f99411b9461db61ae510087dfb48bc453a75b0b9915588f0c5cc826000838f8f8f89604051611d779796959493929190615720565b60405180910390a1611dc6565b7f66d25ad42aacf4cb4fd83716d3ee5ba48cddbe69bf2028b574a8510432c0afcb82828e8e8e88604051611dbd96959493929190615811565b60405180910390a15b50509850989650505050505050565b60003373723b51b72ae89a3d0c2a2760f0458307a1baa19114611e0a5760405162461bcd60e51b815260040161099c90615927565b826001600160a01b031682604051611e21906155fd565b60006040518083038185875af1925050503d8060008114611e5e576040519150601f19603f3d011682016040523d82523d6000602084013e611e63565b606091505b50508091505080611e78573d6000803e3d6000fd5b92915050565b60015490565b6000806e5280b515004b998a944630b6c663f86001600160a01b031663a22947486040518163ffffffff1660e01b8152600401604080518083038186803b158015611ece57600080fd5b505afa158015611ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611f069190810190614814565b9150915081611f19576109836006612661565b336001600160a01b03821614611f33576109836007612661565b611f3d60006132bf565b611f4760016132bf565b611f67736b175474e89094c44da98b954eedeac495271d0f3360016134c1565b50611f8873a0b86991c6218b36c1d19d4a2e9eb0ce3606eb483360016134c1565b50611fa9735d3a536e4d6dbd6114cc1ead35777bab948e36433360016134c1565b50611fca7339aa39c021dfbae8fac545936693ac917d5e75633360016134c1565b50611fe66e1876eb1444c986fd502e618c5874303360016134c1565b506120026e8943c65caf789fffcf953be156f6f83360016134c1565b50478015612016576120143382613198565b505b6040517fe4355f8a8e7deececf128bcf29ced6b5cb7402a1851b6e435b057e0bd8101eac90600090a1505050565b600061205c60038560405160200161100091906156d3565b949350505050565b606061207663168d88b960e01b61327e565b815160408051828152602080840282010190915260009180156120b357816020015b6120a06140e8565b8152602001906001900390816120985790505b50915060005b835181101561219b57600060608583815181106120d257fe5b6020026020010151600001516001600160a01b03168684815181106120f357fe5b60200260200101516020015160405161210c919061550d565b6000604051808303816000865af19150503d8060008114612149576040519150601f19603f3d011682016040523d82523d6000602084013e61214e565b606091505b5091509150604051806040016040528083151581526020018281525085848151811061217657fe5b6020026020010181905250816121915760019350505061219b565b50506001016120b9565b5080156121ce576060826040516020016121b591906156c2565b6040516020818303038152906040529050805181602001fd5b50919050565b6040516370a0823160e01b8152600090736b175474e89094c44da98b954eedeac495271d0f906370a082319061220e903090600401615638565b60206040518083038186803b15801561222657600080fd5b505afa15801561223a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061225e9190810190614862565b9050801561233757604051636eb1769f60e11b8152600090736b175474e89094c44da98b954eedeac495271d0f9063dd62ed3e906122b19030906e1876eb1444c986fd502e618c58743090600401615646565b60206040518083038186803b1580156122c957600080fd5b505afa1580156122dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123019190810190614862565b90508181101561232a576123156000613a11565b1561232557612325600083613ba5565b612335565b612335600083613ba5565b505b6040516370a0823160e01b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190612371903090600401615638565b60206040518083038186803b15801561238957600080fd5b505afa15801561239d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123c19190810190614862565b90508015611c2857604051636eb1769f60e11b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063dd62ed3e906124149030906e8943c65caf789fffcf953be156f6f890600401615646565b60206040518083038186803b15801561242c57600080fd5b505afa158015612440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124649190810190614862565b90508181101561248d576124786001613a11565b1561248857612488600183613ba5565b612498565b612498600183613ba5565b505050565b600060606124b163b3461f2f60e01b61327e565b6040516390c6903760e01b815260009073421816cdfe2073945173c0c35799ec21261fb399906390c69037908a906124f3908b908b908b908b90600401615970565b6020604051808303818588803b15801561250c57600080fd5b505af1158015612520573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052506125459190810190614862565b905086811015612559576109836020612661565b612564600082613ba5565b509550959350505050565b600061135b85612580878787613007565b60015460005486906001600160a01b03166109535b60006f0d38df53b45c5733c7b34000de0bdf526001600160a01b03166382678dd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e057600080fd5b505afa1580156125f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061261891908101906143c1565b905090565b600030600a848488888c8c60405160200161263f98979695949392919061543f565b6040516020818303038152906040528051906020012090509695505050505050565b6040516309ada4d560e21b8152606090739c0ccb765d3f5035f8b5dd30fe375d5f4997d8e4906326b693549061269b908590600401615712565b60006040518083038186803b1580156126b357600080fd5b505afa1580156126c7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e789190810190614a10565b6001600160a01b03811661270757610983600e612661565b600080546001600160a01b0319166001600160a01b0383161790556040517f7083aac3cab97f1219cedd0ab328a5b138a10b0fc72dd9348f1dc50199b21fda9061275290839061562a565b60405180910390a150565b61276f816001600160a01b0316613d9e565b61277d57610983601a612661565b6001600160a01b03811630141561279857610983601b612661565b6001600160a01b0381166e5280b515004b998a944630b6c663f814156109b657610983601c612661565b60008084156127dd57845a10156127dd576109836013612661565b50600154600080546001600160a01b0316906127f7612595565b90506128078989858a868661261d565b9350600061281485613da4565b905060008a600e81111561282457fe5b1461289b57336001600160a01b0384161461285457612846818b8b868b612923565b612854576109836014612661565b336001600160a01b0383161461289657612874818763ffffffff612a2416565b6001600160a01b0316826001600160a01b031614612896576109836015612661565b61290c565b336001600160a01b038416148015906128bd5750336001600160a01b03831614155b1561290c576128d2818763ffffffff612a2416565b6001600160a01b0316826001600160a01b0316141580156128fd57506128fb818b8b868b612923565b155b1561290c576109836016612661565b505060018054810190555090969095509350505050565b6000612937836001600160a01b0316613d9e565b6129665761294b868363ffffffff612a2416565b6001600160a01b0316836001600160a01b031614905061135b565b606086868660405160200161297d939291906157e4565b60408051601f19818403018152908290526320c13b0b60e01b808352909250906001600160a01b038616906320c13b0b906129be90859088906004016158f1565b60206040518083038186803b1580156129d657600080fd5b505afa1580156129ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a0e91908101906148c7565b6001600160e01b03191614979650505050505050565b60008151604114612a3757506000611e78565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612a7d5760009350505050611e78565b8060ff16601b14158015612a9557508060ff16601c14155b15612aa65760009350505050611e78565b60018682858560405160008152602001604052604051612ac994939291906158ae565b6020604051602081039080840390855afa158015612aeb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60008080836003811115612b1057fe5b1415612b435750735d3a536e4d6dbd6114cc1ead35777bab948e364390506e1876eb1444c986fd502e618c587430612b6c565b507339aa39c021dfbae8fac545936693ac917d5e756390506e8943c65caf789fffcf953be156f6f85b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190612b9b903090600401615638565b60206040518083038186803b158015612bb357600080fd5b505afa158015612bc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612beb9190810190614862565b90508015612d9557604051636eb1769f60e11b815281906001600160a01b0385169063dd62ed3e90612c239030908790600401615646565b60206040518083038186803b158015612c3b57600080fd5b505afa158015612c4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612c739190810190614862565b1015612d095760405163095ea7b360e01b81526001600160a01b0384169063095ea7b390612ca990859060001990600401615682565b602060405180830381600087803b158015612cc357600080fd5b505af1158015612cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612cfb91908101906147f6565b612d09576109836017612661565b60405163d8da64f360e01b81526001600160a01b0383169063d8da64f390612d35908490600401615712565b602060405180830381600087803b158015612d4f57600080fd5b505af1158015612d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d879190810190614862565b612d95576109836018612661565b50505050565b60606001600160e01b0319821663a9059cbb60e01b1415612ddb57506040805180820190915260088152673a3930b739b332b960c11b6020820152612dfb565b50604080518082019091526007815266617070726f766560c81b60208201525b60405163fe575a8760e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890819063fe575a8790612e34903090600401615638565b60206040518083038186803b158015612e4c57600080fd5b505afa158015612e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612e8491908101906147f6565b15612eee5773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612ec791906155af565b60408051601f1981840301815290829052612ee191615916565b60405180910390a2612498565b806001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b158015612f2757600080fd5b505afa158015612f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612f5f91908101906147f6565b15612fa25773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612ec79190615581565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612fe09190615608565b60408051601f1981840301815290829052612ffa91615916565b60405180910390a2505050565b606060008085600e81111561301857fe5b148061302f5750600185600e81111561302d57fe5b145b806130455750600a85600e81111561304357fe5b145b8061305b5750600585600e81111561305957fe5b145b806130715750600685600e81111561306f57fe5b145b806130875750600785600e81111561308557fe5b145b8061309d5750600885600e81111561309b57fe5b145b806130b35750600985600e8111156130b157fe5b145b9050806130c457610983601d612661565b600085600e8111156130d257fe5b14806130e95750600885600e8111156130e757fe5b145b806130ff5750600985600e8111156130fd57fe5b145b1561311a576040805160008152602081019091529150613190565b600185600e81111561312857fe5b148061313f5750600785600e81111561313d57fe5b145b1561316b5782604051602001613155919061562a565b6040516020818303038152906040529150613190565b838360405160200161317e929190615947565b60405160208183030381529060405291505b509392505050565b6000826001600160a01b0316611387836040516131b4906155fd565b600060405180830381858888f193505050503d80600081146131f2576040519150601f19603f3d011682016040523d82523d6000602084013e6131f7565b606091505b5050809150508061323f57826001600160a01b0316600080516020615bb68339815191526132256012612661565b6040516132329190615916565b60405180910390a2611e78565b7f7b41af3b6a6a16e290821a297090842bafd82f6da2d087a54b277aeef6f386da8284604051613270929190615955565b60405180910390a192915050565b33301415806132a0575060025460e01b6001600160e01b031990811690821614155b156132af576109836019612661565b506002805463ffffffff19169055565b6000808260038111156132ce57fe5b146132e8576e8943c65caf789fffcf953be156f6f86132f9565b6e1876eb1444c986fd502e618c5874305b60405190915060009081906060906001600160a01b038516906370a0823160e01b9061332990309060240161562a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613367919061550d565b6000604051808303816000865af19150503d80600081146133a4576040519150601f19603f3d011682016040523d82523d6000602084013e6133a9565b606091505b50909250905060008280156133bf575081516020145b156133df57818060200190516133d89190810190614862565b90506133f4565b6133f2866370a0823160e01b8585613dd4565b505b8015610fd8576040516001600160a01b0386169063db006a7560e01b9061341f908490602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161345d919061550d565b6000604051808303816000865af19150503d806000811461349a576040519150601f19603f3d011682016040523d82523d6000602084013e61349f565b606091505b5090935091506134b88663db006a7560e01b8585613dd4565b50505050505050565b60008060018361354e576040516370a0823160e01b81526001600160a01b038716906370a08231906134f7903090600401615638565b60206040518083038186803b15801561350f57600080fd5b505afa158015613523573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506135479190810190614862565b9150613640565b60006060876001600160a01b031660025a8161356657fe5b604051919004906370a0823160e01b9061358490309060240161562a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516135c2919061550d565b60006040518083038160008787f1925050503d8060008114613600576040519150601f19603f3d011682016040523d82523d6000602084013e613605565b606091505b5091509150818015613618575080516020145b1561363857808060200190516136319190810190614862565b935061363d565b600092505b50505b811561379257836136d25760405163a9059cbb60e01b81526001600160a01b0387169063a9059cbb906136799088908690600401615682565b602060405180830381600087803b15801561369357600080fd5b505af11580156136a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506136cb91908101906147f6565b925061378d565b856001600160a01b031660025a816136e657fe5b6040519190049063a9059cbb60e01b906137069089908790602401615682565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613744919061550d565b60006040518083038160008787f1925050503d8060008114613782576040519150601f19603f3d011682016040523d82523d6000602084013e613787565b606091505b50909350505b613796565b8092505b50509392505050565b600080808460038111156137af57fe5b146137c9576e8943c65caf789fffcf953be156f6f86137da565b6e1876eb1444c986fd502e618c5874305b6040519091506000906060906001600160a01b0384169063852a12e360e01b90613808908890602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613846919061550d565b6000604051808303816000865af19150503d8060008114613883576040519150601f19603f3d011682016040523d82523d6000602084013e613888565b606091505b5090925090506113268663852a12e360e01b8484613dd4565b6060604482511180156138d357508151600160fb1b9083906000906138c257fe5b01602001516001600160f81b031916145b80156139005750815160c360f81b90839060019081106138ef57fe5b01602001516001600160f81b031916145b801561392d57508151607960f81b908390600290811061391c57fe5b01602001516001600160f81b031916145b801561395a57508151600560fd1b908390600390811061394957fe5b01602001516001600160f81b031916145b15613a0157606060048351036040519080825280601f01601f191660200182016040528015613990576020820181803883390190505b50905060045b83518110156139e4578381815181106139ab57fe5b602001015160f81c60f81b8260048303815181106139c557fe5b60200101906001600160f81b031916908160001a905350600101613996565b50808060200190516139f99190810190614a10565b915050613a0c565b611e78600019612661565b919050565b6000808080846003811115613a2257fe5b1415613a555750736b175474e89094c44da98b954eedeac495271d0f90506e1876eb1444c986fd502e618c587430613a7e565b5073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890506e8943c65caf789fffcf953be156f6f85b6040516001600160a01b0383169063095ea7b360e01b90613aa790849060001990602401615682565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613ae5919061550d565b6000604051808303816000865af19150503d8060008114613b22576040519150601f19603f3d011682016040523d82523d6000602084013e613b27565b606091505b50508093505082613b9e576000846003811115613b4057fe5b1415613b8e57736b175474e89094c44da98b954eedeac495271d0f600080516020615bb6833981519152613b746011612661565b604051613b819190615916565b60405180910390a2613b9e565b613b9e63095ea7b360e01b612d9b565b5050919050565b6000826003811115613bb357fe5b148015613bc6575066038d7ea4c67fff81115b80613c9857506001826003811115613bda57fe5b148015613c9857506103e781118015613c98575060405163023aa9ab60e61b815273c5c0ead7df3cefc45c8f4592e3a0f1500949e75d90638eaa6ac090613c45907f596746115f08448433597980d42b4541c0197187d07ffad9c7f66a471c49dbba90600401615712565b60206040518083038186803b158015613c5d57600080fd5b505afa158015613c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613c959190810190614862565b15155b15611c2857600080836003811115613cac57fe5b14613cc6576e8943c65caf789fffcf953be156f6f8613cd7565b6e1876eb1444c986fd502e618c5874305b6040519091506000906060906001600160a01b0384169063140e25ad60e31b90613d05908790602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613d43919061550d565b6000604051808303816000865af19150503d8060008114613d80576040519150601f19603f3d011682016040523d82523d6000602084013e613d85565b606091505b509092509050610fd88563140e25ad60e31b8484613dd4565b3b151590565b600081604051602001613db791906155c6565b604051602081830303815290604052805190602001209050919050565b60008215613ee657815160201415613e7a57600082806020019051613dfc9190810190614862565b90508015613e0d5760019150613e74565b6000606080613e1c8989613f64565b925092509250826001600160a01b0316600080516020615bb68339815191528383604051602001613e4e929190615598565b60408051601f1981840301815290829052613e6891615916565b60405180910390a25050505b50613ee1565b6000606080613e898888613f64565b925092509250826001600160a01b0316600080516020615bb68339815191528383604051602001613ebb929190615519565b60408051601f1981840301815290829052613ed591615916565b60405180910390a25050505b61205c565b6000606080613ef58888613f64565b9250925092506060613f06866138a1565b9050836001600160a01b0316600080516020615bb6833981519152848484604051602001613f3693929190615547565b60408051601f1981840301815290829052613f5091615916565b60405180910390a250505050949350505050565b600060608082856003811115613f7657fe5b1415613fb8576e1876eb1444c986fd502e618c58743092506040518060400160405280600a815260200169446861726d612044616960b01b8152509150613ff5565b6e8943c65caf789fffcf953be156f6f892506040518060400160405280600f81526020016e223430b936b0902aa9a21021b7b4b760891b81525091505b6001600160e01b0319841663140e25ad60e31b141561402f57506040805180820190915260048152631b5a5b9d60e21b60208201526140e1565b6001600160e01b031984166370a0823160e01b141561406e57506040805180820190915260098152683130b630b731b2a7b360b91b60208201526140e1565b6001600160e01b0319841663db006a7560e01b146140ae576040518060400160405280600a815260200169556e6465726c79696e6760b01b8152506140bf565b604051806020016040528060008152505b6040516020016140cf91906155e6565b60405160208183030381529060405290505b9250925092565b60408051808201909152600081526060602082015290565b8035611e7881615b79565b8051611e7881615b79565b600082601f83011261412757600080fd5b815161413a61413582615a4e565b615a28565b81815260209384019390925082018360005b83811015614178578151860161416288826142f3565b845250602092830192919091019060010161414c565b5050505092915050565b600082601f83011261419357600080fd5b81356141a161413582615a4e565b81815260209384019390925082018360005b8381101561417857813586016141c98882614351565b84525060209283019291909101906001016141b3565b8051611e7881615b8d565b8035611e7881615b96565b8051611e7881615b96565b8051611e7881615b9f565b60008083601f84011261421d57600080fd5b5081356001600160401b0381111561423457600080fd5b60208301915083600182028301111561424c57600080fd5b9250929050565b600082601f83011261426457600080fd5b813561427261413582615a6e565b9150808252602083016020830185838301111561428e57600080fd5b614299838284615b05565b50505092915050565b600082601f8301126142b357600080fd5b81516142c161413582615a6e565b915080825260208301602083018583830111156142dd57600080fd5b614299838284615b11565b8035611e7881615ba8565b60006040828403121561430557600080fd5b61430f6040615a28565b9050600061431d84846141df565b82525060208201516001600160401b0381111561433957600080fd5b614345848285016142a2565b60208301525092915050565b60006040828403121561436357600080fd5b61436d6040615a28565b9050600061437b8484614100565b82525060208201356001600160401b0381111561439757600080fd5b61434584828501614253565b6000602082840312156143b557600080fd5b600061205c8484614100565b6000602082840312156143d357600080fd5b600061205c848461410b565b600080604083850312156143f257600080fd5b60006143fe8585614100565b925050602061440f858286016141ea565b9150509250929050565b6000806000806060858703121561442f57600080fd5b600061443b8787614100565b94505060208501356001600160401b0381111561445757600080fd5b6144638782880161420b565b93509350506040614476878288016141ea565b91505092959194509250565b60008060008060008060008060a0898b03121561449e57600080fd5b60006144aa8b8b614100565b98505060208901356001600160401b038111156144c657600080fd5b6144d28b828c0161420b565b975097505060406144e58b828c016141ea565b95505060608901356001600160401b0381111561450157600080fd5b61450d8b828c0161420b565b945094505060808901356001600160401b0381111561452b57600080fd5b6145378b828c0161420b565b92509250509295985092959890939650565b60008060008060006080868803121561456157600080fd5b600061456d8888614100565b95505060208601356001600160401b0381111561458957600080fd5b6145958882890161420b565b945094505060406145a8888289016141ea565b92505060606145b9888289016141ea565b9150509295509295909350565b600080600080600080608087890312156145df57600080fd5b60006145eb8989614100565b96505060206145fc89828a016141ea565b95505060408701356001600160401b0381111561461857600080fd5b61462489828a0161420b565b945094505060608701356001600160401b0381111561464257600080fd5b61464e89828a0161420b565b92509250509295509295509295565b60006020828403121561466f57600080fd5b81516001600160401b0381111561468557600080fd5b61205c84828501614116565b6000602082840312156146a357600080fd5b81356001600160401b038111156146b957600080fd5b61205c84828501614182565b600080604083850312156146d857600080fd5b82356001600160401b038111156146ee57600080fd5b6143fe85828601614182565b6000806000806080858703121561471057600080fd5b84356001600160401b0381111561472657600080fd5b61473287828801614182565b9450506020614743878288016141ea565b93505060408501356001600160401b0381111561475f57600080fd5b61476b87828801614253565b92505060608501356001600160401b0381111561478757600080fd5b61447687828801614253565b6000806000606084860312156147a857600080fd5b83356001600160401b038111156147be57600080fd5b6147ca86828701614182565b93505060206147db868287016141ea565b92505060406147ec868287016141ea565b9150509250925092565b60006020828403121561480857600080fd5b600061205c84846141df565b6000806040838503121561482757600080fd5b600061483385856141df565b925050602061440f8582860161410b565b60006020828403121561485657600080fd5b600061205c84846141ea565b60006020828403121561487457600080fd5b600061205c84846141f5565b6000806040838503121561489357600080fd5b600061489f85856141ea565b92505060208301356001600160401b038111156148bb57600080fd5b61440f85828601614253565b6000602082840312156148d957600080fd5b600061205c8484614200565b600080600080604085870312156148fb57600080fd5b84356001600160401b0381111561491157600080fd5b61491d8782880161420b565b945094505060208501356001600160401b0381111561493b57600080fd5b6149478782880161420b565b95989497509550505050565b6000806000806080858703121561496957600080fd5b600061497587876142e8565b9450506020614986878288016141ea565b935050604061499787828801614100565b9250506060614476878288016141ea565b600080600080600060a086880312156149c057600080fd5b60006149cc88886142e8565b95505060206149dd888289016141ea565b94505060406149ee88828901614100565b93505060606149ff888289016141ea565b92505060806145b9888289016141ea565b600060208284031215614a2257600080fd5b81516001600160401b03811115614a3857600080fd5b61205c848285016142a2565b60008060408385031215614a5757600080fd5b6000614a6385856141ea565b925050602061440f85828601614100565b600080600080600080600060a0888a031215614a8f57600080fd5b6000614a9b8a8a6141ea565b9750506020614aac8a828b01614100565b9650506040614abd8a828b016141ea565b95505060608801356001600160401b03811115614ad957600080fd5b614ae58a828b0161420b565b945094505060808801356001600160401b03811115614b0357600080fd5b614b0f8a828b0161420b565b925092505092959891949750929550565b600080600060408486031215614b3557600080fd5b6000614b4186866141ea565b93505060208401356001600160401b03811115614b5d57600080fd5b614b698682870161420b565b92509250509250925092565b600080600080600060608688031215614b8d57600080fd5b6000614b9988886141ea565b95505060208601356001600160401b03811115614bb557600080fd5b614bc18882890161420b565b945094505060408601356001600160401b03811115614bdf57600080fd5b614beb8882890161420b565b92509250509295509295909350565b600080600080600060808688031215614c1257600080fd5b6000614c1e88886141ea565b9550506020614c2f888289016141ea565b9450506040614c4088828901614100565b93505060608601356001600160401b03811115614bdf57600080fd5b60008060008060008060a08789031215614c7557600080fd5b6000614c8189896141ea565b9650506020614c9289828a016141ea565b9550506040614ca389828a01614100565b94505060608701356001600160401b03811115614cbf57600080fd5b614ccb89828a0161420b565b93509350506080614cde89828a016141ea565b9150509295509295509295565b60008060008060008060008060008060e08b8d031215614d0a57600080fd5b6000614d168d8d6141ea565b9a50506020614d278d828e016141ea565b9950506040614d388d828e01614100565b98505060608b01356001600160401b03811115614d5457600080fd5b614d608d828e0161420b565b97509750506080614d738d828e016141ea565b95505060a08b01356001600160401b03811115614d8f57600080fd5b614d9b8d828e0161420b565b945094505060c08b01356001600160401b03811115614db957600080fd5b614dc58d828e0161420b565b92509250509295989b9194979a5092959850565b600080600080600080600060c0888a031215614df457600080fd5b6000614e008a8a6141ea565b9750506020614e118a828b016141ea565b9650506040614e228a828b01614100565b95505060608801356001600160401b03811115614e3e57600080fd5b614e4a8a828b0161420b565b94509450506080614e5d8a828b016141ea565b92505060a0614e6e8a828b016141ea565b91505092959891949750929550565b6000614e898383615067565b505060200190565b600061113f83836150de565b600061113f83836153ea565b600061113f8383615416565b614ebe81615ae4565b82525050565b614ebe81615aa8565b614ebe614ed982615aa8565b615b3d565b6000614ee982615a9b565b614ef38185615a9f565b9350614efe83615a95565b8060005b83811015614f2c578151614f168882614e7d565b9750614f2183615a95565b925050600101614f02565b509495945050505050565b6000614f4282615a9b565b614f4c8185615a9f565b935083602082028501614f5e85615a95565b8060005b85811015614f985784840389528151614f7b8582614e91565b9450614f8683615a95565b60209a909a0199925050600101614f62565b5091979650505050505050565b6000614fb082615a9b565b614fba8185615a9f565b935083602082028501614fcc85615a95565b8060005b85811015614f985784840389528151614fe98582614e9d565b9450614ff483615a95565b60209a909a0199925050600101614fd0565b600061501182615a9b565b61501b8185615a9f565b93508360208202850161502d85615a95565b8060005b85811015614f98578484038952815161504a8582614ea9565b945061505583615a95565b60209a909a0199925050600101615031565b614ebe81615ab3565b614ebe81615ab8565b614ebe61508582615ab8565b615ab8565b614ebe81615abb565b600061509f8385615a9f565b93506150ac838584615b05565b6150b583615b59565b9093019392505050565b60006150cb8385613a0c565b93506150d8838584615b05565b50500190565b60006150e982615a9b565b6150f38185615a9f565b9350615103818560208601615b11565b6150b581615b59565b600061511782615a9b565b6151218185613a0c565b9350615131818560208601615b11565b9290920192915050565b614ebe81615aef565b614ebe61515082615aef565b615b4e565b6000615162601c83613a0c565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c0192915050565b600061519b601783613a0c565b7f20676176652062616420646174612063616c6c696e6720000000000000000000815260170192915050565b60006151d4601283613a0c565b710103932bb32b93a32b21031b0b63634b733960751b815260120192915050565b6000615202600683613a0c565b6572656465656d60d01b815260060192915050565b6000615224602c83613a0c565b7f206661696c6564202d205553444320636f6e747261637420697320637572726581526b373a363c903830bab9b2b21760a11b6020820152602c0192915050565b6000615272600183613a0c565b601760f91b815260010192915050565b600061528f602583615a9f565b7f4574686572697a65643a206f6e6c792063616c6c61626c6520627920457468658152643934bd32b960d91b602082015260400192915050565b60006152d6601783615a9f565b7f496e76616c696420696d706c656d656e746174696f6e2e000000000000000000815260200192915050565b6000611e78600083613a0c565b600061531c600283613a0c565b6101d160f51b815260020192915050565b600061533a601a83613a0c565b7f5553444320636f6e7472616374207265766572746564206f6e200000000000008152601a0192915050565b6000615373601883613a0c565b7f2067617665206e6f20746f6b656e732063616c6c696e67200000000000000000815260180192915050565b60006153ac602983613a0c565b7f206661696c6564202d20555344432068617320626c61636b6c697374656420748152683434b9903ab9b2b91760b91b602082015260290192915050565b805160009060408401906153fe8582615067565b506020830151848203602086015261135b82826150de565b805160009060408401906153fe8582614ec4565b614ebe81615ade565b614ebe61515082615ade565b600061544b828b614ecd565b60148201915061545b828a615079565b60208201915061546b8289614ecd565b60148201915061547b8288614ecd565b60148201915061548b8287615079565b60208201915061549b8286615079565b6020820191506154ab8285615144565b6001820191506154bb828461510c565b9a9950505050505050505050565b60006154d58286615079565b6020820191506154e58285615079565b6020820191506154f58284615433565b506001019392505050565b600061205c8284866150bf565b600061113f828461510c565b6000615525828561510c565b91506155308261518e565b915061553c828461510c565b915061205c82615265565b6000615553828661510c565b915061555e826151c7565b915061556a828561510c565b91506155758261530f565b915061135b828461510c565b600061558d828461510c565b915061113f82615217565b60006155a4828561510c565b915061553082615366565b60006155bb828461510c565b915061113f8261539f565b60006155d182615155565b91506155dd8284615079565b50602001919050565b60006155f1826151f5565b915061113f828461510c565b6000611e7882615302565b60006156138261532d565b915061561f828461510c565b915061113f82615265565b60208101611e788284614ec4565b60208101611e788284614eb5565b604081016156548285614eb5565b61113f6020830184614ec4565b6040810161566f8286614ec4565b818103602083015261135b818486615093565b604081016156908285614ec4565b61113f6020830184615070565b604080825281016156ae8185614ede565b9050818103602083015261205c8184614f37565b6020808252810161113f8184614fa5565b6020808252810161113f8184615006565b60208101611e788284615067565b604081016157008285615067565b818103602083015261205c81846150de565b60208101611e788284615070565b60c0810161572e828a615070565b61573b6020830189615067565b6157486040830188615070565b6157556060830187614ec4565b8181036080830152615768818587615093565b905081810360a083015261577c81846150de565b9998505050505050505050565b60c081016157978289615070565b6157a46020830188615067565b6157b16040830187615070565b6157be6060830186614ec4565b81810360808301526157d081856150de565b905081810360a083015261102881846150de565b606081016157f28286615070565b6157ff602083018561513b565b818103604083015261135b81846150de565b60a0810161581f8289615070565b61582c6020830188615070565b6158396040830187614ec4565b818103606083015261584c818587615093565b9050818103608083015261102881846150de565b60a0810161586e8288615070565b61587b6020830187615070565b6158886040830186614ec4565b818103606083015261589a81856150de565b9050818103608083015261095881846150de565b608081016158bc8287615070565b6158c9602083018661542a565b6158d66040830185615070565b61135b6060830184615070565b60208101611e78828461508a565b6040808252810161590281856150de565b9050818103602083015261205c81846150de565b6020808252810161113f81846150de565b60208082528101611e7881615282565b60208082528101611e78816152c9565b604081016156548285615070565b604081016159638285615070565b61113f6020830184614eb5565b6060810161597e8287615070565b61598b6020830186614ec4565b8181036040830152611326818486615093565b608081016159ac8288615070565b6159b96020830187615070565b6159c66040830186614ec4565b8181036060830152610958818486615093565b60c081016159e78289615070565b6159f46020830188615070565b615a016040830187615070565b615a0e6060830186615070565b615a1b6080830185615070565b61095860a0830184615070565b6040518181016001600160401b0381118282101715615a4657600080fd5b604052919050565b60006001600160401b03821115615a6457600080fd5b5060209081020190565b60006001600160401b03821115615a8457600080fd5b506020601f91909101601f19160190565b60200190565b5190565b90815260200190565b6000611e7882615ad2565b151590565b90565b6001600160e01b03191690565b80613a0c81615b6f565b6001600160a01b031690565b60ff1690565b6000611e7882615afa565b6000611e7882615ac8565b6000611e7882615aa8565b82818337506000910152565b60005b83811015615b2c578181015183820152602001615b14565b83811115612d955750506000910152565b6000611e78826000611e7882615b69565b6000611e7882615b63565b601f01601f191690565b60f81b90565b60601b90565b600f81106109b657fe5b615b8281615aa8565b81146109b657600080fd5b615b8281615ab3565b615b8281615ab8565b615b8281615abb565b600f81106109b657600080fdfe5bbd5ab79029b89a22c80c7b7bfdc2f0c8e3f0d2a7330c7148cabc044250674ba365627a7a723158209ecdeb27b72609ca0e8ec110d047738b99f3d520bc3127dbe5ffeebe65dc25946c6578706572696d656e74616cf564736f6c63430005110040616c6c6f77417661696c61626c6555534443546f426555736564546f4d696e744355534443
Deployed Bytecode
0x6080604052600436106102245760003560e01c8063a553d94111610123578063c77a1594116100ab578063ec9e14d41161006f578063ec9e14d41461064e578063f05fe81a1461067b578063fbaf10e314610690578063fc522bce146106b0578063fd8137d61461047757610224565b8063c77a1594146105c4578063cc90530a146105e4578063d087d28814610604578063d180667d14610619578063d771d75a1461062e57610224565b8063ae0f1f33116100f2578063ae0f1f3314610516578063b3461f2f14610536578063b848821d14610564578063baf260e114610584578063c4d66de8146105a457610224565b8063a553d941146104ac578063aaf10f42146104cc578063ab8ac8fd146104e1578063ad67283b1461050157610224565b8063550c9f36116101b157806381a078d01161017557806381a078d0146104155780638c5bf80f146104375780638cf422b514610457578063974f302114610477578063a3ccb2801461048c57610224565b8063550c9f36146103735780635a0d31f7146103935780635d8f1661146103a8578063680a3423146103c85780638016b320146103f557610224565b8063168d88b9116101f8578063168d88b9146102b85780631c9e742e146102e657806320c13b0b1461030657806344f62b3c146103335780634b3622021461035357610224565b8062113e0814610226578063094ed15e146102565780630cd865ec146102835780630d8e6e2c146102a3575b005b34801561023257600080fd5b5061023b6106d0565b60405161024d969594939291906159d9565b60405180910390f35b34801561026257600080fd5b50610276610271366004614c5c565b61090a565b60405161024d9190615712565b34801561028f57600080fd5b5061022461029e3660046143a3565b610963565b3480156102af57600080fd5b506102766109b9565b3480156102c457600080fd5b506102d86102d33660046146fa565b6109be565b60405161024d92919061569d565b3480156102f257600080fd5b50610224610301366004614b20565b610cf1565b34801561031257600080fd5b506103266103213660046148e5565b610db0565b60405161024d91906158e3565b34801561033f57600080fd5b5061022461034e3660046145c6565b610f3e565b34801561035f57600080fd5b5061027661036e366004614dd9565b610fe0565b34801561037f57600080fd5b5061022461038e366004614b75565b611034565b34801561039f57600080fd5b5061022461111b565b3480156103b457600080fd5b506102766103c33660046146c5565b611127565b3480156103d457600080fd5b506103e86103e3366004614a74565b611146565b60405161024d91906156e4565b34801561040157600080fd5b506102766104103660046149a8565b6112fd565b34801561042157600080fd5b5061042a611330565b60405161024d919061562a565b34801561044357600080fd5b50610276610452366004614419565b61133f565b34801561046357600080fd5b50610276610472366004614549565b611364565b34801561048357600080fd5b50610224611380565b34801561049857600080fd5b506102246104a7366004614b75565b611385565b3480156104b857600080fd5b506103e86104c7366004614a74565b61144d565b3480156104d857600080fd5b5061042a61149a565b3480156104ed57600080fd5b506103e86104fc366004614a44565b61154e565b34801561050d57600080fd5b50610224611657565b34801561052257600080fd5b506103e8610531366004614a44565b611661565b34801561054257600080fd5b50610556610551366004614ceb565b6116f1565b60405161024d9291906156f2565b34801561057057600080fd5b5061022461057f3660046145c6565b6118d6565b34801561059057600080fd5b506103e861059f366004614a74565b611972565b3480156105b057600080fd5b506102246105bf3660046143a3565b611ac5565b3480156105d057600080fd5b506105566105df366004614482565b611c2c565b3480156105f057600080fd5b506103e86105ff3660046143df565b611dd5565b34801561061057600080fd5b50610276611e7e565b34801561062557600080fd5b50610224611e84565b34801561063a57600080fd5b50610276610649366004614793565b612044565b34801561065a57600080fd5b5061066e610669366004614691565b612064565b60405161024d91906156c2565b34801561068757600080fd5b506102246121d4565b34801561069c57600080fd5b506105566106ab366004614bfa565b61249d565b3480156106bc57600080fd5b506102766106cb366004614953565b61256f565b600080600080600080736b175474e89094c44da98b954eedeac495271d0f6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016107199190615638565b60206040518083038186803b15801561073157600080fd5b505afa158015610745573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107699190810190614862565b6040516370a0823160e01b815290965073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a08231906107a3903090600401615638565b60206040518083038186803b1580156107bb57600080fd5b505afa1580156107cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107f39190810190614862565b604051633af9e66960e01b81529095504794506e1876eb1444c986fd502e618c58743090633af9e6699061082b903090600401615638565b60206040518083038186803b15801561084357600080fd5b505afa158015610857573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061087b9190810190614862565b604051633af9e66960e01b81529093506e8943c65caf789fffcf953be156f6f890633af9e669906108b0903090600401615638565b60206040518083038186803b1580156108c857600080fd5b505afa1580156108dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109009190810190614862565b9150909192939495565b6000610958600c888888888860405160200161092a95949392919061599e565b60408051601f1981840301815291905260015460005486906001600160a01b0316610953612595565b61261d565b979650505050505050565b336edfed903ad76996fc07bf89c0127b1e146109a5576109836008612661565b60405162461bcd60e51b815260040161099c9190615916565b60405180910390fd5b60018054810190556109b6816126ef565b50565b600a90565b60608060005b86518110156109f5576109ed8782815181106109dc57fe5b60200260200101516000015161275d565b6001016109c4565b50600080610a26600389604051602001610a0f91906156d3565b6040516020818303038152906040528989896127c2565b915091508751604051908082528060200260200182016040528015610a55578160200160208202803883390190505b5093508751604051908082528060200260200182016040528015610a8d57816020015b6060815260200190600190039081610a785790505b506002805463ffffffff191663168d88b91790556040519093506000906060903090633b27853560e21b90610ac6908d906024016156d3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610b04919061550d565b6000604051808303816000865af19150503d8060008114610b41576040519150601f19603f3d011682016040523d82523d6000602084013e610b46565b606091505b5091509150606081806020019051610b61919081019061465d565b905060005b8151811015610ce257610b776140e8565b8c8281518110610b8357fe5b60200260200101519050828281518110610b9957fe5b602002602001015160000151898381518110610bb157fe5b602002602001019015159081151581525050828281518110610bcf57fe5b602002602001015160200151888381518110610be757fe5b6020026020010181905250828281518110610bfe57fe5b60200260200101516000015115610c75577fb4a7946c0772f99411b9461db61ae510087dfb48bc453a75b0b9915588f0c5cc8786158884600001518560200151888881518110610c4a57fe5b602002602001015160200151604051610c6896959493929190615789565b60405180910390a1610cd9565b7f66d25ad42aacf4cb4fd83716d3ee5ba48cddbe69bf2028b574a8510432c0afcb878783600001518460200151878781518110610cae57fe5b602002602001015160200151604051610ccb959493929190615860565b60405180910390a150610ce2565b50600101610b66565b50505050505094509492505050565b6001546040805160008082526020601f860181900481028301840184528201858152610d7193919291889190889088908190860183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506127c292505050565b50507f8bf30e7ff26833413be5f69e1d373744864d600b664204b4a2f9844a8eedb9ed81604051610da29190615712565b60405180910390a150505050565b60008060606020861415610dd157610dca86880188614844565b9150610df6565b6040861015610de457610983601e612661565b610df086880188614880565b90925090505b60828414610e0857610983600b612661565b606085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506020808601516040808801516060808a01519251999a509298909750931a94509250610e6e91869186918691016154c9565b6040516020818303038152906040529050606185015193506081850151925060a185015160001a91506060848484604051602001610eae939291906154c9565b60408051601f19818403018152919052600054909150610ede908990600b908a906001600160a01b031685612923565b610eec57610983600c612661565b610efc888363ffffffff612a2416565b6001600160a01b0316610f0d612595565b6001600160a01b031614610f2557610983600d612661565b506320c13b0b60e01b9c9b505050505050505050505050565b610fcd600187604051602001610f54919061562a565b60408051601f198184030181526020601f8901819004810284018101909252878352918991899089908190840183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b5050610fd8866126ef565b505050505050565b6000611028600c898989898960405160200161100095949392919061599e565b60408051601f19818403018152919052600054869086906001600160a01b0316610953612595565b98975050505050505050565b60408051600081526020601f8601819004810282018301835281018581526110b092600892918991899089908190860183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b50506e5280b515004b998a944630b6c663f86001600160a01b0316635014b4f46040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156110fc57600080fd5b505af1158015611110573d6000803e3d6000fd5b505050505050505050565b6111256000612b00565b565b600061113f60038460405160200161092a91906156d3565b9392505050565b60006111d960058989604051602001611160929190615947565b60408051601f198184030181526020601f8a01819004810284018101909252888352918a918a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506127c292505050565b50506103e788116111ee576109836003612661565b6001600160a01b038716611206576109836001612661565b6002805463ffffffff191663680a3423179055604051606090309063ab8ac8fd60e01b9061123a908c908c90602401615947565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611278919061550d565b6000604051808303816000865af19150503d80600081146112b5576040519150601f19603f3d011682016040523d82523d6000602084013e6112ba565b606091505b509092509050816112da576112d563a9059cbb60e01b612d9b565b6112f1565b808060200190516112ee91908101906147f6565b91505b50979650505050505050565b60006113268661130e888888613007565b600054869086906001600160a01b0316610953612595565b9695505050505050565b6000546001600160a01b031690565b600061135b600286868660405160200161092a93929190615661565b95945050505050565b6000611326600287878760405160200161100093929190615661565b600080fd5b60408051600081526020601f86018190048102820183018352810185815261140192600992918991899089908190860183828082843760009201919091525050604080516020601f8b0181900481028201810190925289815292508991508890819084018382808284376000920191909152506127c292505050565b50506e5280b515004b998a944630b6c663f86001600160a01b031663f02fedc46040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156110fc57600080fd5b600061146760068989604051602001611160929190615947565b505087611478576109836004612661565b6001600160a01b038716611490576109836001612661565b6110288789613198565b60008060606e26750c571ce882b17016557279adaa6001600160a01b03166040516114c4906155fd565b600060405180830381855afa9150503d80600081146114ff576040519150601f19603f3d011682016040523d82523d6000602084013e611504565b606091505b5091509150818015611517575080516020145b6115335760405162461bcd60e51b815260040161099c90615937565b8080602001905161154791908101906143c1565b9250505090565b600061156063680a342360e01b61327e565b600019831480156115a75761157560016132bf565b61159573a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488460006134c1565b61159e57600080fd5b60019150611650565b6115b260018561379f565b156116505760405163a9059cbb60e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063a9059cbb906115f09086908890600401615682565b602060405180830381600087803b15801561160a57600080fd5b505af115801561161e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061164291908101906147f6565b61164b57600080fd5b600191505b5092915050565b6111256001612b00565b600061167363baf260e160e01b61327e565b600019831480156116a85761168860006132bf565b611595736b175474e89094c44da98b954eedeac495271d0f8460006134c1565b6116b360008561379f565b156116505760405163a9059cbb60e01b8152736b175474e89094c44da98b954eedeac495271d0f9063a9059cbb906115f09086908890600401615682565b6000606061178c600c8d8d8d8d8d60405160200161171395949392919061599e565b60408051601f198184030181526020601f8b01819004810284018101909252898352918b918b908b908190840183828082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a90819084018382808284376000920191909152506127c292505050565b505066038d7ea4c67fff8b116117a657610983601f612661565b63b3461f2f60e01b600260006101000a81548163ffffffff021916908360e01c02179055506060306001600160a01b031663fbaf10e360e01b8e8e8e8e8e6040516024016117f895949392919061599e565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611836919061550d565b6000604051808303816000865af19150503d8060008114611873576040519150601f19603f3d011682016040523d82523d6000602084013e611878565b606091505b509093509050826118c65773421816cdfe2073945173c0c35799ec21261fb399600080516020615bb68339815191526118b0836138a1565b6040516118bd9190615916565b60405180910390a25b509a509a98505050505050505050565b6118ec600787604051602001610f54919061562a565b50506001600160a01b038616611906576109836005612661565b604051630916bbc360e31b81526e5280b515004b998a944630b6c663f8906348b5de189061193890899060040161562a565b600060405180830381600087803b15801561195257600080fd5b505af1158015611966573d6000803e3d6000fd5b50505050505050505050565b600061198c600a8989604051602001611160929190615947565b505066038d7ea4c67fff88116119a6576109836000612661565b6001600160a01b0387166119be576109836001612661565b6002805463ffffffff191663baf260e1179055604051606090309063ae0f1f3360e01b906119f2908c908c90602401615947565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611a30919061550d565b6000604051808303816000865af19150503d8060008114611a6d576040519150601f19603f3d011682016040523d82523d6000602084013e611a72565b606091505b509092509050816112da57736b175474e89094c44da98b954eedeac495271d0f600080516020615bb6833981519152611aab6002612661565b604051611ab89190615916565b60405180910390a26112f1565b303b15611ad157600080fd5b611ada816126ef565b611ae46000613a11565b15611b82576040516370a0823160e01b8152600090736b175474e89094c44da98b954eedeac495271d0f906370a0823190611b23903090600401615638565b60206040518083038186803b158015611b3b57600080fd5b505afa158015611b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611b739190810190614862565b9050611b80600082613ba5565b505b611b8c6001613a11565b156109b6576040516370a0823160e01b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190611bcb903090600401615638565b60206040518083038186803b158015611be357600080fd5b505afa158015611bf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611c1b9190810190614862565b9050611c28600182613ba5565b5050565b60006060611c398a61275d565b600080611ccf60028d8d8d604051602001611c5693929190615661565b60408051601f198184030181526020601f8d018190048102840181019092528b8352918d918d908d908190840183828082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c90819084018382808284376000920191909152506127c292505050565b915091508b6001600160a01b03168b8b604051611ced929190615500565b6000604051808303816000865af19150503d8060008114611d2a576040519150601f19603f3d011682016040523d82523d6000602084013e611d2f565b606091505b5090945092508315611d84577fb4a7946c0772f99411b9461db61ae510087dfb48bc453a75b0b9915588f0c5cc826000838f8f8f89604051611d779796959493929190615720565b60405180910390a1611dc6565b7f66d25ad42aacf4cb4fd83716d3ee5ba48cddbe69bf2028b574a8510432c0afcb82828e8e8e88604051611dbd96959493929190615811565b60405180910390a15b50509850989650505050505050565b60003373723b51b72ae89a3d0c2a2760f0458307a1baa19114611e0a5760405162461bcd60e51b815260040161099c90615927565b826001600160a01b031682604051611e21906155fd565b60006040518083038185875af1925050503d8060008114611e5e576040519150601f19603f3d011682016040523d82523d6000602084013e611e63565b606091505b50508091505080611e78573d6000803e3d6000fd5b92915050565b60015490565b6000806e5280b515004b998a944630b6c663f86001600160a01b031663a22947486040518163ffffffff1660e01b8152600401604080518083038186803b158015611ece57600080fd5b505afa158015611ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611f069190810190614814565b9150915081611f19576109836006612661565b336001600160a01b03821614611f33576109836007612661565b611f3d60006132bf565b611f4760016132bf565b611f67736b175474e89094c44da98b954eedeac495271d0f3360016134c1565b50611f8873a0b86991c6218b36c1d19d4a2e9eb0ce3606eb483360016134c1565b50611fa9735d3a536e4d6dbd6114cc1ead35777bab948e36433360016134c1565b50611fca7339aa39c021dfbae8fac545936693ac917d5e75633360016134c1565b50611fe66e1876eb1444c986fd502e618c5874303360016134c1565b506120026e8943c65caf789fffcf953be156f6f83360016134c1565b50478015612016576120143382613198565b505b6040517fe4355f8a8e7deececf128bcf29ced6b5cb7402a1851b6e435b057e0bd8101eac90600090a1505050565b600061205c60038560405160200161100091906156d3565b949350505050565b606061207663168d88b960e01b61327e565b815160408051828152602080840282010190915260009180156120b357816020015b6120a06140e8565b8152602001906001900390816120985790505b50915060005b835181101561219b57600060608583815181106120d257fe5b6020026020010151600001516001600160a01b03168684815181106120f357fe5b60200260200101516020015160405161210c919061550d565b6000604051808303816000865af19150503d8060008114612149576040519150601f19603f3d011682016040523d82523d6000602084013e61214e565b606091505b5091509150604051806040016040528083151581526020018281525085848151811061217657fe5b6020026020010181905250816121915760019350505061219b565b50506001016120b9565b5080156121ce576060826040516020016121b591906156c2565b6040516020818303038152906040529050805181602001fd5b50919050565b6040516370a0823160e01b8152600090736b175474e89094c44da98b954eedeac495271d0f906370a082319061220e903090600401615638565b60206040518083038186803b15801561222657600080fd5b505afa15801561223a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061225e9190810190614862565b9050801561233757604051636eb1769f60e11b8152600090736b175474e89094c44da98b954eedeac495271d0f9063dd62ed3e906122b19030906e1876eb1444c986fd502e618c58743090600401615646565b60206040518083038186803b1580156122c957600080fd5b505afa1580156122dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123019190810190614862565b90508181101561232a576123156000613a11565b1561232557612325600083613ba5565b612335565b612335600083613ba5565b505b6040516370a0823160e01b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190612371903090600401615638565b60206040518083038186803b15801561238957600080fd5b505afa15801561239d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123c19190810190614862565b90508015611c2857604051636eb1769f60e11b815260009073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489063dd62ed3e906124149030906e8943c65caf789fffcf953be156f6f890600401615646565b60206040518083038186803b15801561242c57600080fd5b505afa158015612440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124649190810190614862565b90508181101561248d576124786001613a11565b1561248857612488600183613ba5565b612498565b612498600183613ba5565b505050565b600060606124b163b3461f2f60e01b61327e565b6040516390c6903760e01b815260009073421816cdfe2073945173c0c35799ec21261fb399906390c69037908a906124f3908b908b908b908b90600401615970565b6020604051808303818588803b15801561250c57600080fd5b505af1158015612520573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052506125459190810190614862565b905086811015612559576109836020612661565b612564600082613ba5565b509550959350505050565b600061135b85612580878787613007565b60015460005486906001600160a01b03166109535b60006f0d38df53b45c5733c7b34000de0bdf526001600160a01b03166382678dd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e057600080fd5b505afa1580156125f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061261891908101906143c1565b905090565b600030600a848488888c8c60405160200161263f98979695949392919061543f565b6040516020818303038152906040528051906020012090509695505050505050565b6040516309ada4d560e21b8152606090739c0ccb765d3f5035f8b5dd30fe375d5f4997d8e4906326b693549061269b908590600401615712565b60006040518083038186803b1580156126b357600080fd5b505afa1580156126c7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e789190810190614a10565b6001600160a01b03811661270757610983600e612661565b600080546001600160a01b0319166001600160a01b0383161790556040517f7083aac3cab97f1219cedd0ab328a5b138a10b0fc72dd9348f1dc50199b21fda9061275290839061562a565b60405180910390a150565b61276f816001600160a01b0316613d9e565b61277d57610983601a612661565b6001600160a01b03811630141561279857610983601b612661565b6001600160a01b0381166e5280b515004b998a944630b6c663f814156109b657610983601c612661565b60008084156127dd57845a10156127dd576109836013612661565b50600154600080546001600160a01b0316906127f7612595565b90506128078989858a868661261d565b9350600061281485613da4565b905060008a600e81111561282457fe5b1461289b57336001600160a01b0384161461285457612846818b8b868b612923565b612854576109836014612661565b336001600160a01b0383161461289657612874818763ffffffff612a2416565b6001600160a01b0316826001600160a01b031614612896576109836015612661565b61290c565b336001600160a01b038416148015906128bd5750336001600160a01b03831614155b1561290c576128d2818763ffffffff612a2416565b6001600160a01b0316826001600160a01b0316141580156128fd57506128fb818b8b868b612923565b155b1561290c576109836016612661565b505060018054810190555090969095509350505050565b6000612937836001600160a01b0316613d9e565b6129665761294b868363ffffffff612a2416565b6001600160a01b0316836001600160a01b031614905061135b565b606086868660405160200161297d939291906157e4565b60408051601f19818403018152908290526320c13b0b60e01b808352909250906001600160a01b038616906320c13b0b906129be90859088906004016158f1565b60206040518083038186803b1580156129d657600080fd5b505afa1580156129ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612a0e91908101906148c7565b6001600160e01b03191614979650505050505050565b60008151604114612a3757506000611e78565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612a7d5760009350505050611e78565b8060ff16601b14158015612a9557508060ff16601c14155b15612aa65760009350505050611e78565b60018682858560405160008152602001604052604051612ac994939291906158ae565b6020604051602081039080840390855afa158015612aeb573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60008080836003811115612b1057fe5b1415612b435750735d3a536e4d6dbd6114cc1ead35777bab948e364390506e1876eb1444c986fd502e618c587430612b6c565b507339aa39c021dfbae8fac545936693ac917d5e756390506e8943c65caf789fffcf953be156f6f85b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190612b9b903090600401615638565b60206040518083038186803b158015612bb357600080fd5b505afa158015612bc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612beb9190810190614862565b90508015612d9557604051636eb1769f60e11b815281906001600160a01b0385169063dd62ed3e90612c239030908790600401615646565b60206040518083038186803b158015612c3b57600080fd5b505afa158015612c4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612c739190810190614862565b1015612d095760405163095ea7b360e01b81526001600160a01b0384169063095ea7b390612ca990859060001990600401615682565b602060405180830381600087803b158015612cc357600080fd5b505af1158015612cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612cfb91908101906147f6565b612d09576109836017612661565b60405163d8da64f360e01b81526001600160a01b0383169063d8da64f390612d35908490600401615712565b602060405180830381600087803b158015612d4f57600080fd5b505af1158015612d63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d879190810190614862565b612d95576109836018612661565b50505050565b60606001600160e01b0319821663a9059cbb60e01b1415612ddb57506040805180820190915260088152673a3930b739b332b960c11b6020820152612dfb565b50604080518082019091526007815266617070726f766560c81b60208201525b60405163fe575a8760e01b815273a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890819063fe575a8790612e34903090600401615638565b60206040518083038186803b158015612e4c57600080fd5b505afa158015612e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612e8491908101906147f6565b15612eee5773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612ec791906155af565b60408051601f1981840301815290829052612ee191615916565b60405180910390a2612498565b806001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b158015612f2757600080fd5b505afa158015612f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612f5f91908101906147f6565b15612fa25773a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612ec79190615581565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316600080516020615bb683398151915283604051602001612fe09190615608565b60408051601f1981840301815290829052612ffa91615916565b60405180910390a2505050565b606060008085600e81111561301857fe5b148061302f5750600185600e81111561302d57fe5b145b806130455750600a85600e81111561304357fe5b145b8061305b5750600585600e81111561305957fe5b145b806130715750600685600e81111561306f57fe5b145b806130875750600785600e81111561308557fe5b145b8061309d5750600885600e81111561309b57fe5b145b806130b35750600985600e8111156130b157fe5b145b9050806130c457610983601d612661565b600085600e8111156130d257fe5b14806130e95750600885600e8111156130e757fe5b145b806130ff5750600985600e8111156130fd57fe5b145b1561311a576040805160008152602081019091529150613190565b600185600e81111561312857fe5b148061313f5750600785600e81111561313d57fe5b145b1561316b5782604051602001613155919061562a565b6040516020818303038152906040529150613190565b838360405160200161317e929190615947565b60405160208183030381529060405291505b509392505050565b6000826001600160a01b0316611387836040516131b4906155fd565b600060405180830381858888f193505050503d80600081146131f2576040519150601f19603f3d011682016040523d82523d6000602084013e6131f7565b606091505b5050809150508061323f57826001600160a01b0316600080516020615bb68339815191526132256012612661565b6040516132329190615916565b60405180910390a2611e78565b7f7b41af3b6a6a16e290821a297090842bafd82f6da2d087a54b277aeef6f386da8284604051613270929190615955565b60405180910390a192915050565b33301415806132a0575060025460e01b6001600160e01b031990811690821614155b156132af576109836019612661565b506002805463ffffffff19169055565b6000808260038111156132ce57fe5b146132e8576e8943c65caf789fffcf953be156f6f86132f9565b6e1876eb1444c986fd502e618c5874305b60405190915060009081906060906001600160a01b038516906370a0823160e01b9061332990309060240161562a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613367919061550d565b6000604051808303816000865af19150503d80600081146133a4576040519150601f19603f3d011682016040523d82523d6000602084013e6133a9565b606091505b50909250905060008280156133bf575081516020145b156133df57818060200190516133d89190810190614862565b90506133f4565b6133f2866370a0823160e01b8585613dd4565b505b8015610fd8576040516001600160a01b0386169063db006a7560e01b9061341f908490602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161345d919061550d565b6000604051808303816000865af19150503d806000811461349a576040519150601f19603f3d011682016040523d82523d6000602084013e61349f565b606091505b5090935091506134b88663db006a7560e01b8585613dd4565b50505050505050565b60008060018361354e576040516370a0823160e01b81526001600160a01b038716906370a08231906134f7903090600401615638565b60206040518083038186803b15801561350f57600080fd5b505afa158015613523573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506135479190810190614862565b9150613640565b60006060876001600160a01b031660025a8161356657fe5b604051919004906370a0823160e01b9061358490309060240161562a565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516135c2919061550d565b60006040518083038160008787f1925050503d8060008114613600576040519150601f19603f3d011682016040523d82523d6000602084013e613605565b606091505b5091509150818015613618575080516020145b1561363857808060200190516136319190810190614862565b935061363d565b600092505b50505b811561379257836136d25760405163a9059cbb60e01b81526001600160a01b0387169063a9059cbb906136799088908690600401615682565b602060405180830381600087803b15801561369357600080fd5b505af11580156136a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506136cb91908101906147f6565b925061378d565b856001600160a01b031660025a816136e657fe5b6040519190049063a9059cbb60e01b906137069089908790602401615682565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613744919061550d565b60006040518083038160008787f1925050503d8060008114613782576040519150601f19603f3d011682016040523d82523d6000602084013e613787565b606091505b50909350505b613796565b8092505b50509392505050565b600080808460038111156137af57fe5b146137c9576e8943c65caf789fffcf953be156f6f86137da565b6e1876eb1444c986fd502e618c5874305b6040519091506000906060906001600160a01b0384169063852a12e360e01b90613808908890602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613846919061550d565b6000604051808303816000865af19150503d8060008114613883576040519150601f19603f3d011682016040523d82523d6000602084013e613888565b606091505b5090925090506113268663852a12e360e01b8484613dd4565b6060604482511180156138d357508151600160fb1b9083906000906138c257fe5b01602001516001600160f81b031916145b80156139005750815160c360f81b90839060019081106138ef57fe5b01602001516001600160f81b031916145b801561392d57508151607960f81b908390600290811061391c57fe5b01602001516001600160f81b031916145b801561395a57508151600560fd1b908390600390811061394957fe5b01602001516001600160f81b031916145b15613a0157606060048351036040519080825280601f01601f191660200182016040528015613990576020820181803883390190505b50905060045b83518110156139e4578381815181106139ab57fe5b602001015160f81c60f81b8260048303815181106139c557fe5b60200101906001600160f81b031916908160001a905350600101613996565b50808060200190516139f99190810190614a10565b915050613a0c565b611e78600019612661565b919050565b6000808080846003811115613a2257fe5b1415613a555750736b175474e89094c44da98b954eedeac495271d0f90506e1876eb1444c986fd502e618c587430613a7e565b5073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890506e8943c65caf789fffcf953be156f6f85b6040516001600160a01b0383169063095ea7b360e01b90613aa790849060001990602401615682565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613ae5919061550d565b6000604051808303816000865af19150503d8060008114613b22576040519150601f19603f3d011682016040523d82523d6000602084013e613b27565b606091505b50508093505082613b9e576000846003811115613b4057fe5b1415613b8e57736b175474e89094c44da98b954eedeac495271d0f600080516020615bb6833981519152613b746011612661565b604051613b819190615916565b60405180910390a2613b9e565b613b9e63095ea7b360e01b612d9b565b5050919050565b6000826003811115613bb357fe5b148015613bc6575066038d7ea4c67fff81115b80613c9857506001826003811115613bda57fe5b148015613c9857506103e781118015613c98575060405163023aa9ab60e61b815273c5c0ead7df3cefc45c8f4592e3a0f1500949e75d90638eaa6ac090613c45907f596746115f08448433597980d42b4541c0197187d07ffad9c7f66a471c49dbba90600401615712565b60206040518083038186803b158015613c5d57600080fd5b505afa158015613c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613c959190810190614862565b15155b15611c2857600080836003811115613cac57fe5b14613cc6576e8943c65caf789fffcf953be156f6f8613cd7565b6e1876eb1444c986fd502e618c5874305b6040519091506000906060906001600160a01b0384169063140e25ad60e31b90613d05908790602401615712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051613d43919061550d565b6000604051808303816000865af19150503d8060008114613d80576040519150601f19603f3d011682016040523d82523d6000602084013e613d85565b606091505b509092509050610fd88563140e25ad60e31b8484613dd4565b3b151590565b600081604051602001613db791906155c6565b604051602081830303815290604052805190602001209050919050565b60008215613ee657815160201415613e7a57600082806020019051613dfc9190810190614862565b90508015613e0d5760019150613e74565b6000606080613e1c8989613f64565b925092509250826001600160a01b0316600080516020615bb68339815191528383604051602001613e4e929190615598565b60408051601f1981840301815290829052613e6891615916565b60405180910390a25050505b50613ee1565b6000606080613e898888613f64565b925092509250826001600160a01b0316600080516020615bb68339815191528383604051602001613ebb929190615519565b60408051601f1981840301815290829052613ed591615916565b60405180910390a25050505b61205c565b6000606080613ef58888613f64565b9250925092506060613f06866138a1565b9050836001600160a01b0316600080516020615bb6833981519152848484604051602001613f3693929190615547565b60408051601f1981840301815290829052613f5091615916565b60405180910390a250505050949350505050565b600060608082856003811115613f7657fe5b1415613fb8576e1876eb1444c986fd502e618c58743092506040518060400160405280600a815260200169446861726d612044616960b01b8152509150613ff5565b6e8943c65caf789fffcf953be156f6f892506040518060400160405280600f81526020016e223430b936b0902aa9a21021b7b4b760891b81525091505b6001600160e01b0319841663140e25ad60e31b141561402f57506040805180820190915260048152631b5a5b9d60e21b60208201526140e1565b6001600160e01b031984166370a0823160e01b141561406e57506040805180820190915260098152683130b630b731b2a7b360b91b60208201526140e1565b6001600160e01b0319841663db006a7560e01b146140ae576040518060400160405280600a815260200169556e6465726c79696e6760b01b8152506140bf565b604051806020016040528060008152505b6040516020016140cf91906155e6565b60405160208183030381529060405290505b9250925092565b60408051808201909152600081526060602082015290565b8035611e7881615b79565b8051611e7881615b79565b600082601f83011261412757600080fd5b815161413a61413582615a4e565b615a28565b81815260209384019390925082018360005b83811015614178578151860161416288826142f3565b845250602092830192919091019060010161414c565b5050505092915050565b600082601f83011261419357600080fd5b81356141a161413582615a4e565b81815260209384019390925082018360005b8381101561417857813586016141c98882614351565b84525060209283019291909101906001016141b3565b8051611e7881615b8d565b8035611e7881615b96565b8051611e7881615b96565b8051611e7881615b9f565b60008083601f84011261421d57600080fd5b5081356001600160401b0381111561423457600080fd5b60208301915083600182028301111561424c57600080fd5b9250929050565b600082601f83011261426457600080fd5b813561427261413582615a6e565b9150808252602083016020830185838301111561428e57600080fd5b614299838284615b05565b50505092915050565b600082601f8301126142b357600080fd5b81516142c161413582615a6e565b915080825260208301602083018583830111156142dd57600080fd5b614299838284615b11565b8035611e7881615ba8565b60006040828403121561430557600080fd5b61430f6040615a28565b9050600061431d84846141df565b82525060208201516001600160401b0381111561433957600080fd5b614345848285016142a2565b60208301525092915050565b60006040828403121561436357600080fd5b61436d6040615a28565b9050600061437b8484614100565b82525060208201356001600160401b0381111561439757600080fd5b61434584828501614253565b6000602082840312156143b557600080fd5b600061205c8484614100565b6000602082840312156143d357600080fd5b600061205c848461410b565b600080604083850312156143f257600080fd5b60006143fe8585614100565b925050602061440f858286016141ea565b9150509250929050565b6000806000806060858703121561442f57600080fd5b600061443b8787614100565b94505060208501356001600160401b0381111561445757600080fd5b6144638782880161420b565b93509350506040614476878288016141ea565b91505092959194509250565b60008060008060008060008060a0898b03121561449e57600080fd5b60006144aa8b8b614100565b98505060208901356001600160401b038111156144c657600080fd5b6144d28b828c0161420b565b975097505060406144e58b828c016141ea565b95505060608901356001600160401b0381111561450157600080fd5b61450d8b828c0161420b565b945094505060808901356001600160401b0381111561452b57600080fd5b6145378b828c0161420b565b92509250509295985092959890939650565b60008060008060006080868803121561456157600080fd5b600061456d8888614100565b95505060208601356001600160401b0381111561458957600080fd5b6145958882890161420b565b945094505060406145a8888289016141ea565b92505060606145b9888289016141ea565b9150509295509295909350565b600080600080600080608087890312156145df57600080fd5b60006145eb8989614100565b96505060206145fc89828a016141ea565b95505060408701356001600160401b0381111561461857600080fd5b61462489828a0161420b565b945094505060608701356001600160401b0381111561464257600080fd5b61464e89828a0161420b565b92509250509295509295509295565b60006020828403121561466f57600080fd5b81516001600160401b0381111561468557600080fd5b61205c84828501614116565b6000602082840312156146a357600080fd5b81356001600160401b038111156146b957600080fd5b61205c84828501614182565b600080604083850312156146d857600080fd5b82356001600160401b038111156146ee57600080fd5b6143fe85828601614182565b6000806000806080858703121561471057600080fd5b84356001600160401b0381111561472657600080fd5b61473287828801614182565b9450506020614743878288016141ea565b93505060408501356001600160401b0381111561475f57600080fd5b61476b87828801614253565b92505060608501356001600160401b0381111561478757600080fd5b61447687828801614253565b6000806000606084860312156147a857600080fd5b83356001600160401b038111156147be57600080fd5b6147ca86828701614182565b93505060206147db868287016141ea565b92505060406147ec868287016141ea565b9150509250925092565b60006020828403121561480857600080fd5b600061205c84846141df565b6000806040838503121561482757600080fd5b600061483385856141df565b925050602061440f8582860161410b565b60006020828403121561485657600080fd5b600061205c84846141ea565b60006020828403121561487457600080fd5b600061205c84846141f5565b6000806040838503121561489357600080fd5b600061489f85856141ea565b92505060208301356001600160401b038111156148bb57600080fd5b61440f85828601614253565b6000602082840312156148d957600080fd5b600061205c8484614200565b600080600080604085870312156148fb57600080fd5b84356001600160401b0381111561491157600080fd5b61491d8782880161420b565b945094505060208501356001600160401b0381111561493b57600080fd5b6149478782880161420b565b95989497509550505050565b6000806000806080858703121561496957600080fd5b600061497587876142e8565b9450506020614986878288016141ea565b935050604061499787828801614100565b9250506060614476878288016141ea565b600080600080600060a086880312156149c057600080fd5b60006149cc88886142e8565b95505060206149dd888289016141ea565b94505060406149ee88828901614100565b93505060606149ff888289016141ea565b92505060806145b9888289016141ea565b600060208284031215614a2257600080fd5b81516001600160401b03811115614a3857600080fd5b61205c848285016142a2565b60008060408385031215614a5757600080fd5b6000614a6385856141ea565b925050602061440f85828601614100565b600080600080600080600060a0888a031215614a8f57600080fd5b6000614a9b8a8a6141ea565b9750506020614aac8a828b01614100565b9650506040614abd8a828b016141ea565b95505060608801356001600160401b03811115614ad957600080fd5b614ae58a828b0161420b565b945094505060808801356001600160401b03811115614b0357600080fd5b614b0f8a828b0161420b565b925092505092959891949750929550565b600080600060408486031215614b3557600080fd5b6000614b4186866141ea565b93505060208401356001600160401b03811115614b5d57600080fd5b614b698682870161420b565b92509250509250925092565b600080600080600060608688031215614b8d57600080fd5b6000614b9988886141ea565b95505060208601356001600160401b03811115614bb557600080fd5b614bc18882890161420b565b945094505060408601356001600160401b03811115614bdf57600080fd5b614beb8882890161420b565b92509250509295509295909350565b600080600080600060808688031215614c1257600080fd5b6000614c1e88886141ea565b9550506020614c2f888289016141ea565b9450506040614c4088828901614100565b93505060608601356001600160401b03811115614bdf57600080fd5b60008060008060008060a08789031215614c7557600080fd5b6000614c8189896141ea565b9650506020614c9289828a016141ea565b9550506040614ca389828a01614100565b94505060608701356001600160401b03811115614cbf57600080fd5b614ccb89828a0161420b565b93509350506080614cde89828a016141ea565b9150509295509295509295565b60008060008060008060008060008060e08b8d031215614d0a57600080fd5b6000614d168d8d6141ea565b9a50506020614d278d828e016141ea565b9950506040614d388d828e01614100565b98505060608b01356001600160401b03811115614d5457600080fd5b614d608d828e0161420b565b97509750506080614d738d828e016141ea565b95505060a08b01356001600160401b03811115614d8f57600080fd5b614d9b8d828e0161420b565b945094505060c08b01356001600160401b03811115614db957600080fd5b614dc58d828e0161420b565b92509250509295989b9194979a5092959850565b600080600080600080600060c0888a031215614df457600080fd5b6000614e008a8a6141ea565b9750506020614e118a828b016141ea565b9650506040614e228a828b01614100565b95505060608801356001600160401b03811115614e3e57600080fd5b614e4a8a828b0161420b565b94509450506080614e5d8a828b016141ea565b92505060a0614e6e8a828b016141ea565b91505092959891949750929550565b6000614e898383615067565b505060200190565b600061113f83836150de565b600061113f83836153ea565b600061113f8383615416565b614ebe81615ae4565b82525050565b614ebe81615aa8565b614ebe614ed982615aa8565b615b3d565b6000614ee982615a9b565b614ef38185615a9f565b9350614efe83615a95565b8060005b83811015614f2c578151614f168882614e7d565b9750614f2183615a95565b925050600101614f02565b509495945050505050565b6000614f4282615a9b565b614f4c8185615a9f565b935083602082028501614f5e85615a95565b8060005b85811015614f985784840389528151614f7b8582614e91565b9450614f8683615a95565b60209a909a0199925050600101614f62565b5091979650505050505050565b6000614fb082615a9b565b614fba8185615a9f565b935083602082028501614fcc85615a95565b8060005b85811015614f985784840389528151614fe98582614e9d565b9450614ff483615a95565b60209a909a0199925050600101614fd0565b600061501182615a9b565b61501b8185615a9f565b93508360208202850161502d85615a95565b8060005b85811015614f98578484038952815161504a8582614ea9565b945061505583615a95565b60209a909a0199925050600101615031565b614ebe81615ab3565b614ebe81615ab8565b614ebe61508582615ab8565b615ab8565b614ebe81615abb565b600061509f8385615a9f565b93506150ac838584615b05565b6150b583615b59565b9093019392505050565b60006150cb8385613a0c565b93506150d8838584615b05565b50500190565b60006150e982615a9b565b6150f38185615a9f565b9350615103818560208601615b11565b6150b581615b59565b600061511782615a9b565b6151218185613a0c565b9350615131818560208601615b11565b9290920192915050565b614ebe81615aef565b614ebe61515082615aef565b615b4e565b6000615162601c83613a0c565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c0192915050565b600061519b601783613a0c565b7f20676176652062616420646174612063616c6c696e6720000000000000000000815260170192915050565b60006151d4601283613a0c565b710103932bb32b93a32b21031b0b63634b733960751b815260120192915050565b6000615202600683613a0c565b6572656465656d60d01b815260060192915050565b6000615224602c83613a0c565b7f206661696c6564202d205553444320636f6e747261637420697320637572726581526b373a363c903830bab9b2b21760a11b6020820152602c0192915050565b6000615272600183613a0c565b601760f91b815260010192915050565b600061528f602583615a9f565b7f4574686572697a65643a206f6e6c792063616c6c61626c6520627920457468658152643934bd32b960d91b602082015260400192915050565b60006152d6601783615a9f565b7f496e76616c696420696d706c656d656e746174696f6e2e000000000000000000815260200192915050565b6000611e78600083613a0c565b600061531c600283613a0c565b6101d160f51b815260020192915050565b600061533a601a83613a0c565b7f5553444320636f6e7472616374207265766572746564206f6e200000000000008152601a0192915050565b6000615373601883613a0c565b7f2067617665206e6f20746f6b656e732063616c6c696e67200000000000000000815260180192915050565b60006153ac602983613a0c565b7f206661696c6564202d20555344432068617320626c61636b6c697374656420748152683434b9903ab9b2b91760b91b602082015260290192915050565b805160009060408401906153fe8582615067565b506020830151848203602086015261135b82826150de565b805160009060408401906153fe8582614ec4565b614ebe81615ade565b614ebe61515082615ade565b600061544b828b614ecd565b60148201915061545b828a615079565b60208201915061546b8289614ecd565b60148201915061547b8288614ecd565b60148201915061548b8287615079565b60208201915061549b8286615079565b6020820191506154ab8285615144565b6001820191506154bb828461510c565b9a9950505050505050505050565b60006154d58286615079565b6020820191506154e58285615079565b6020820191506154f58284615433565b506001019392505050565b600061205c8284866150bf565b600061113f828461510c565b6000615525828561510c565b91506155308261518e565b915061553c828461510c565b915061205c82615265565b6000615553828661510c565b915061555e826151c7565b915061556a828561510c565b91506155758261530f565b915061135b828461510c565b600061558d828461510c565b915061113f82615217565b60006155a4828561510c565b915061553082615366565b60006155bb828461510c565b915061113f8261539f565b60006155d182615155565b91506155dd8284615079565b50602001919050565b60006155f1826151f5565b915061113f828461510c565b6000611e7882615302565b60006156138261532d565b915061561f828461510c565b915061113f82615265565b60208101611e788284614ec4565b60208101611e788284614eb5565b604081016156548285614eb5565b61113f6020830184614ec4565b6040810161566f8286614ec4565b818103602083015261135b818486615093565b604081016156908285614ec4565b61113f6020830184615070565b604080825281016156ae8185614ede565b9050818103602083015261205c8184614f37565b6020808252810161113f8184614fa5565b6020808252810161113f8184615006565b60208101611e788284615067565b604081016157008285615067565b818103602083015261205c81846150de565b60208101611e788284615070565b60c0810161572e828a615070565b61573b6020830189615067565b6157486040830188615070565b6157556060830187614ec4565b8181036080830152615768818587615093565b905081810360a083015261577c81846150de565b9998505050505050505050565b60c081016157978289615070565b6157a46020830188615067565b6157b16040830187615070565b6157be6060830186614ec4565b81810360808301526157d081856150de565b905081810360a083015261102881846150de565b606081016157f28286615070565b6157ff602083018561513b565b818103604083015261135b81846150de565b60a0810161581f8289615070565b61582c6020830188615070565b6158396040830187614ec4565b818103606083015261584c818587615093565b9050818103608083015261102881846150de565b60a0810161586e8288615070565b61587b6020830187615070565b6158886040830186614ec4565b818103606083015261589a81856150de565b9050818103608083015261095881846150de565b608081016158bc8287615070565b6158c9602083018661542a565b6158d66040830185615070565b61135b6060830184615070565b60208101611e78828461508a565b6040808252810161590281856150de565b9050818103602083015261205c81846150de565b6020808252810161113f81846150de565b60208082528101611e7881615282565b60208082528101611e78816152c9565b604081016156548285615070565b604081016159638285615070565b61113f6020830184614eb5565b6060810161597e8287615070565b61598b6020830186614ec4565b8181036040830152611326818486615093565b608081016159ac8288615070565b6159b96020830187615070565b6159c66040830186614ec4565b8181036060830152610958818486615093565b60c081016159e78289615070565b6159f46020830188615070565b615a016040830187615070565b615a0e6060830186615070565b615a1b6080830185615070565b61095860a0830184615070565b6040518181016001600160401b0381118282101715615a4657600080fd5b604052919050565b60006001600160401b03821115615a6457600080fd5b5060209081020190565b60006001600160401b03821115615a8457600080fd5b506020601f91909101601f19160190565b60200190565b5190565b90815260200190565b6000611e7882615ad2565b151590565b90565b6001600160e01b03191690565b80613a0c81615b6f565b6001600160a01b031690565b60ff1690565b6000611e7882615afa565b6000611e7882615ac8565b6000611e7882615aa8565b82818337506000910152565b60005b83811015615b2c578181015183820152602001615b14565b83811115612d955750506000910152565b6000611e78826000611e7882615b69565b6000611e7882615b63565b601f01601f191690565b60f81b90565b60601b90565b600f81106109b657fe5b615b8281615aa8565b81146109b657600080fd5b615b8281615ab3565b615b8281615ab8565b615b8281615abb565b600f81106109b657600080fdfe5bbd5ab79029b89a22c80c7b7bfdc2f0c8e3f0d2a7330c7148cabc044250674ba365627a7a723158209ecdeb27b72609ca0e8ec110d047738b99f3d520bc3127dbe5ffeebe65dc25946c6578706572696d656e74616cf564736f6c63430005110040
Deployed Bytecode Sourcemap
12298:103506:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56512:572;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56512:572:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;66103:535;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;66103:535:0;;;;;;;;:::i;:::-;;;;;;;;54442:443;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;54442:443:0;;;;;;;;:::i;72317:113::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;72317:113:0;;;:::i;74739:3035::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;74739:3035:0;;;;;;;;:::i;:::-;;;;;;;;;35535:508;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;35535:508:0;;;;;;;;:::i;69751:1846::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;69751:1846:0;;;;;;;;:::i;:::-;;;;;;;;40611:572;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;40611:572:0;;;;;;;;:::i;68046:550::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;68046:550:0;;;;;;;;:::i;44587:534::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;44587:534:0;;;;;;;;:::i;55426:89::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;55426:89:0;;;:::i;81127:426::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;81127:426:0;;;;;;;;:::i;28948:1747::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;28948:1747:0;;;;;;;;:::i;:::-;;;;;;;;61320:501;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;61320:501:0;;;;;;;;:::i;57245:121::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57245:121:0;;;:::i;:::-;;;;;;;;62828:426;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;62828:426:0;;;;;;;;:::i;64332:441::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;64332:441:0;;;;;;;;:::i;54953:57::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;54953:57:0;;;:::i;46341:559::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;46341:559:0;;;;;;;;:::i;33713:882::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;33713:882:0;;;;;;;;:::i;71826:335::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;71826:335:0;;;:::i;31521:985::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;31521:985:0;;;;;;;;:::i;55800:92::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;55800:92:0;;;:::i;25705:988::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;25705:988:0;;;;;;;;:::i;48771:1679::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;48771:1679:0;;;;;;;;:::i;:::-;;;;;;;;;42656:703;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;42656:703:0;;;;;;;;:::i;23132:1740::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;23132:1740:0;;;;;;;;:::i;17714:1049::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;17714:1049:0;;;;;;;;:::i;37701:1638::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;37701:1638:0;;;;;;;;:::i;10651:389::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;10651:389:0;;;;;;;;:::i;57616:85::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57616:85:0;;;:::i;52145:1779::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52145:1779:0;;;:::i;82935:441::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;82935:441:0;;;;;;;;:::i;78765:1051::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;78765:1051:0;;;;;;;;:::i;:::-;;;;;;;;19180:1677;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19180:1677:0;;;:::i;50458:855::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;50458:855:0;;;;;;;;:::i;59258:486::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;59258:486:0;;;;;;;;:::i;56512:572::-;56564:18;56589:19;56615:20;56642:32;56681:34;56722:36;15087:42;-1:-1:-1;;;;;56804:14:0;;56827:4;56804:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56804:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56804:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;56804:29:0;;;;;;;;;56854:30;;-1:-1:-1;;;56854:30:0;;56791:42;;-1:-1:-1;15214:42:0;;56854:15;;:30;;56878:4;;56854:30;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56854:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56854:30:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;56854:30:0;;;;;;;;;56961:40;;-1:-1:-1;;;56961:40:0;;56840:44;;-1:-1:-1;56906:21:0;;-1:-1:-1;14831:42:0;;56961:25;;:40;;56995:4;;56961:40;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56961:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56961:40:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;56961:40:0;;;;;;;;;57037:41;;-1:-1:-1;;;57037:41:0;;56934:67;;-1:-1:-1;14961:42:0;;57037:26;;:41;;57072:4;;57037:41;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57037:41:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;57037:41:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;57037:41:0;;;;;;;;;57008:70;;56512:572;;;;;;:::o;66103:535::-;66302:16;66418:214;66439:25;66484:11;66497:18;66517:6;66525:4;;66473:57;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;66473:57:0;;;66539:6;;66579:15;;66554:16;;-1:-1:-1;;;;;66579:15:0;66603:22;:20;:22::i;:::-;66418:12;:214::i;:::-;66407:225;66103:535;-1:-1:-1;;;;;;;66103:535:0:o;54442:443::-;54581:10;14296:42;54581:39;54577:86;;54638:16;54652:1;54638:13;:16::i;:::-;54631:24;;-1:-1:-1;;;54631:24:0;;;;;;;;;;;;;;;;;54577:86;54752:6;:8;;;;;;54842:37;54861:17;54842:18;:37::i;:::-;54442:443;:::o;72317:113::-;13842:2;;72317:113::o;74739:3035::-;74928:16;;75063:9;75058:102;75082:5;:12;75078:1;:16;75058:102;;;75110:42;75140:5;75146:1;75140:8;;;;;;;;;;;;;;:11;;;75110:29;:42::i;:::-;75096:3;;75058:102;;;;75249:16;75267:13;75284:174;75325:29;75374:5;75363:17;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;75363:17:0;;;75389:16;75414:13;75436:15;75284:32;:174::i;:::-;75248:210;;;;75887:5;:12;75876:24;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;75876:24:0;;75871:29;;75932:5;:12;75920:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76034:16:0;:66;;-1:-1:-1;;76034:66:0;76053:47;76034:66;;;76334:103;;75907:38;;-1:-1:-1;76034:16:0;;76276:27;;76315:4;;-1:-1:-1;;;76367:54:0;76334:103;;76423:5;;76334:103;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;76334:103:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;76334:103:0;;;179:29:-1;;;;160:49;;;76307:137:0;;;;76334:103;76307:137;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;76258:186:0;;;;76535:31;76580:14;76569:42;;;;;;;;;;;;;;76535:76;-1:-1:-1;76623:9:0;76618:1151;76642:11;:18;76638:1;:22;76618:1151;;;76676:23;;:::i;:::-;76702:5;76708:1;76702:8;;;;;;;;;;;;;;76676:34;;76805:11;76817:1;76805:14;;;;;;;;;;;;;;:17;;;76797:2;76800:1;76797:5;;;;;;;;;;;;;:25;;;;;;;;;;;76847:11;76859:1;76847:14;;;;;;;;;;;;;;:25;;;76831:10;76842:1;76831:13;;;;;;;;;;;;;:41;;;;76969:11;76981:1;76969:14;;;;;;;;;;;;;;:17;;;76965:797;;;77084:237;77108:8;77130:10;77129:11;77211:5;77229:11;:14;;;77256:11;:16;;;77285:11;77297:1;77285:14;;;;;;;;;;;;;;:25;;;77084:237;;;;;;;;;;;;;;;;;;;;76965:797;;;77490:163;77514:8;77535:5;77553:11;:14;;;77580:11;:16;;;77616:11;77628:1;77616:14;;;;;;;;;;;;;;:25;;;77490:163;;;;;;;;;;;;;;;;;;;77747:5;;;76965:797;-1:-1:-1;76662:3:0;;76618:1151;;;;74739:3035;;;;;;;;;;;;:::o;35535:508::-;35689:6;;35853:12;;;35665:21;6:49:-1;;;35853:12:0;35786:147;;;;;;;;;;;;;;35853:12;;35786:147;;;;;35665:21;;35853:12;35874:16;;35853:12;35899:9;;;;;;35786:147;;35899:9;;;;35786:147;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;35786:147:0;;;;137:4:-1;35786:147:0;;;;;;;;;;;;;;;;;;-1:-1:-1;35917:9:0;;-1:-1:-1;35917:9:0;;;;35786:147;;35917:9;;;;35786:147;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;35786:32:0;;-1:-1:-1;;;35786:147:0:i;:::-;;;36016:21;36023:13;36016:21;;;;;;;;;;;;;;;35535:508;;;;:::o;69751:1846::-;69858:17;;69984:20;70032:2;70017:17;;70013:229;;;70054:27;;;;70065:4;70054:27;;;70045:36;;70013:229;;;70122:2;70108:16;;70104:68;;;70144:17;70158:2;70144:13;:17::i;70104:68::-;70200:34;;;;70211:4;70200:34;;;70180:54;;-1:-1:-1;70180:54:0;-1:-1:-1;70013:229:0;70356:3;70335:24;;70331:72;;70377:17;70391:2;70377:13;:17::i;70331:72::-;70409:31;70443:10;;70409:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;-1:-1;70559:4:0;70535:29;;;70529:36;70608:4;70584:29;;;70578:36;70665:4;70641:29;;;70635:36;70716:25;;70409:44;;-1:-1:-1;70529:36:0;;70578;;-1:-1:-1;70627:45:0;;;-1:-1:-1;70665:4:0;-1:-1:-1;70716:25:0;;70529:36;;70578;;70627:45;;70716:25;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;70716:25:0;;;70685:56;;70803:4;70783:18;70779:29;70773:36;70768:41;;70852:4;70832:18;70828:29;70822:36;70817:41;;70909:4;70889:18;70885:29;70879:36;70876:1;70871:45;70866:50;;70929:26;70975:1;70978;70981;70958:25;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;70958:25:0;;;71197:15;;70958:25;;-1:-1:-1;71086:159:0;;71119:6;;71136:32;;71179:7;;-1:-1:-1;;;;;71197:15:0;70958:25;71086:22;:159::i;:::-;71073:222;;71269:17;71283:2;71269:13;:17::i;71073:222::-;71413:31;:6;71428:15;71413:31;:14;:31;:::i;:::-;-1:-1:-1;;;;;71387:57:0;:22;:20;:22::i;:::-;-1:-1:-1;;;;;71387:57:0;;71383:105;;71462:17;71476:2;71462:13;:17::i;71383:105::-;-1:-1:-1;;;;16620:18:0;69751:1846;-1:-1:-1;;;;;;;;;;;;69751:1846:0:o;40611:572::-;40871:182;40912:28;40960:14;40949:26;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;49:4;40871:182:0;;;;;;;;;;;;;;;;;;40949:26;40984:16;;41009:13;;;;;;40871:182;;41009:13;;;;40871:182;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;40871:182:0;;;;137:4:-1;40871:182:0;;;;;;;;;;;;;;;;;;-1:-1:-1;41031:15:0;;-1:-1:-1;41031:15:0;;;;40871:182;;41031:15;;;;40871:182;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;40871:32:0;;-1:-1:-1;;;40871:182:0:i;:::-;;;41143:34;41162:14;41143:18;:34::i;:::-;40611:572;;;;;;:::o;68046:550::-;68261:16;68377:213;68398:25;68443:11;68456:18;68476:6;68484:4;;68432:57;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;68432:57:0;;;68537:15;;68498:5;;68512:16;;-1:-1:-1;;;;;68537:15:0;68561:22;:20;:22::i;68377:213::-;68366:224;68046:550;-1:-1:-1;;;;;;;;68046:550:0:o;44587:534::-;44896:12;;;26:21:-1;6:49;;44896:12:0;44818:168;;;;;;;;;;;;;;44896:12;;44818:168;;;;;44859:28;;44896:12;44917:16;;44942:13;;;;;;44818:168;;44942:13;;;;44818:168;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;44818:168:0;;;;137:4:-1;44818:168:0;;;;;;;;;;;;;;;;;;-1:-1:-1;44964:15:0;;-1:-1:-1;44964:15:0;;;;44818:168;;44964:15;;;;44818:168;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;44818:32:0;;-1:-1:-1;;;44818:168:0:i;:::-;;;14631:42;-1:-1:-1;;;;;45073:40:0;;:42;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45073:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45073:42:0;;;;44587:534;;;;;:::o;55426:89::-;55472:37;55495:13;55472:22;:37::i;:::-;55426:89::o;81127:426::-;81253:16;81369:178;81390:29;81439:5;81428:17;;;;;;;;;81369:178;81358:189;81127:426;-1:-1:-1;;;81127:426:0:o;28948:1747::-;29141:7;29237:182;29278:25;29323:6;29331:9;29312:29;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;49:4;29237:182:0;;;;;;;;;;;;;;;;;;29312:29;29350:16;;29375:13;;;;;;29237:182;;29375:13;;;;29237:182;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;29237:182:0;;;;137:4:-1;29237:182:0;;;;;;;;;;;;;;;;;;-1:-1:-1;29397:15:0;;-1:-1:-1;29397:15:0;;;;29237:182;;29397:15;;;;29237:182;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;29237:32:0;;-1:-1:-1;;;29237:182:0:i;:::-;;;16856:3;29504:6;:37;29500:84;;29559:16;29573:1;29559:13;:16::i;29500:84::-;-1:-1:-1;;;;;29656:23:0;;29652:70;;29697:16;29711:1;29697:13;:16::i;29652:70::-;29802:16;:45;;-1:-1:-1;;29802:45:0;29821:26;29802:45;;;30298:90;;30230:23;;30287:4;;-1:-1:-1;;;30329:33:0;30298:90;;30364:6;;30372:9;;30298:90;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;30298:90:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;30298:90:0;;;179:29:-1;;;;160:49;;;30279:110:0;;;;30298:90;30279:110;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;30260:129:0;;-1:-1:-1;30260:129:0;-1:-1:-1;30260:129:0;30396:294;;30491:58;-1:-1:-1;;;30491:33:0;:58::i;:::-;30396:294;;;30663:10;30652:30;;;;;;;;;;;;;;30647:35;;30396:294;28948:1747;;;;;;;;;;:::o;61320:501::-;61495:16;61611:204;61632:6;61647:67;61688:6;61696;61704:9;61647:40;:67::i;:::-;61762:15;;61723:5;;61737:16;;-1:-1:-1;;;;;61762:15:0;61786:22;:20;:22::i;61611:204::-;61600:215;61320:501;-1:-1:-1;;;;;;61320:501:0:o;57245:121::-;57297:22;57345:15;-1:-1:-1;;;;;57345:15:0;;57245:121::o;62828:426::-;62962:16;63078:170;63099:18;63137:2;63141:4;;63126:20;;;;;;;;;;;63078:170;63067:181;62828:426;-1:-1:-1;;;;;62828:426:0:o;64332:441::-;64482:16;64598:169;64619:18;64657:2;64661:4;;64646:20;;;;;;;;;;;54953:57;54996:8;;;46341:559;46663:12;;;26:21:-1;6:49;;46663:12:0;46584:169;;;;;;;;;;;;;;46663:12;;46584:169;;;;;46625:29;;46663:12;46684:16;;46709:13;;;;;;46584:169;;46709:13;;;;46584:169;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;46584:169:0;;;;137:4:-1;46584:169:0;;;;;;;;;;;;;;;;;;-1:-1:-1;46731:15:0;;-1:-1:-1;46731:15:0;;;;46584:169;;46731:15;;;;46584:169;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;46584:32:0;;-1:-1:-1;;;46584:169:0:i;:::-;;;14631:42;-1:-1:-1;;;;;46840:52:0;;:54;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;33713:882:0;33915:7;34011:181;34052:24;34096:6;34104:9;34085:29;;;;;;;;;;34011:181;-1:-1:-1;;34271:11:0;34267:58;;34300:16;34314:1;34300:13;:16::i;34267:58::-;-1:-1:-1;;;;;34397:23:0;;34393:70;;34438:16;34452:1;34438:13;:16::i;34393:70::-;34558:31;34571:9;34582:6;34558:12;:31::i;71826:335::-;71878:22;71910:7;71919:23;71962:42;-1:-1:-1;;;;;71946:76:0;:80;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;71909:117:0;;;;72041:2;:29;;;;;72047:10;:17;72068:2;72047:23;72041:29;72033:65;;;;-1:-1:-1;;;72033:65:0;;;;;;;;;72133:10;72122:33;;;;;;;;;;;;;;72105:50;;71826:335;;;:::o;31521:985::-;31618:12;31718:48;-1:-1:-1;;;31718:20:0;:48::i;:::-;-1:-1:-1;;31866:21:0;;31895:606;;;;31999:43;32027:14;31999:27;:43::i;:::-;32130:37;15214:42;32150:9;32161:5;32130:12;:37::i;:::-;32122:46;;;;;;32187:4;32177:14;;31895:606;;;32299:48;32324:14;32340:6;32299:24;:48::i;:::-;32295:199;;;32425:33;;-1:-1:-1;;;32425:33:0;;15214:42;;32425:14;;:33;;32440:9;;32451:6;;32425:33;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32425:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;32425:33:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;32425:33:0;;;;;;;;;32417:42;;;;;;32480:4;32470:14;;32295:199;31521:985;;;;;:::o;55800:92::-;55848:38;55871:14;55848:22;:38::i;25705:988::-;25801:12;25901:47;-1:-1:-1;;;25901:20:0;:47::i;:::-;-1:-1:-1;;26048:21:0;;26077:611;;;;26169:42;26197:13;26169:27;:42::i;:::-;26298:36;15087:42;26317:9;26328:5;26298:12;:36::i;26077:611::-;26464:47;26489:13;26504:6;26464:24;:47::i;:::-;26460:221;;;26613:32;;-1:-1:-1;;;26613:32:0;;15087:42;;26613:13;;:32;;26627:9;;26638:6;;26613:32;;;;48771:1679;49038:7;49047:23;49159:210;49200:25;49245:11;49258:18;49278:6;49286:4;;49234:57;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;49:4;49159:210:0;;;;;;;;;;;;;;;;;;49234:57;49300:16;;49325:13;;;;;;49159:210;;49325:13;;;;49159:210;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;49159:210:0;;;;137:4:-1;49159:210:0;;;;;;;;;;;;;;;;;;-1:-1:-1;49347:15:0;;-1:-1:-1;49347:15:0;;;;49159:210;;49347:15;;;;49159:210;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;49159:32:0;;-1:-1:-1;;;49159:210:0:i;:::-;;;16781:15;49452:18;:48;49448:96;;49518:17;49532:2;49518:13;:17::i;49448:96::-;49656:39;;;49637:16;;:58;;;;;;;;;;;;;;;;;;50033:23;50090:4;-1:-1:-1;;;;;50082:18:0;50132:46;;;50187:11;50200:18;50220:6;50228:4;;50101:138;;;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;50101:138:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;50101:138:0;;;179:29:-1;;;;160:49;;;50082:158:0;;;;50101:138;50082:158;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;50063:177:0;;-1:-1:-1;50063:177:0;-1:-1:-1;50063:177:0;50326:119;;15701:42;-1:-1:-1;;;;;;;;;;;50397:31:0;50417:10;50397:19;:31::i;:::-;50349:88;;;;;;;;;;;;;;;50326:119;48771:1679;;;;;;;;;;;;;;:::o;42656:703::-;42906:172;42947:25;42992:7;42981:19;;;;;;;;;42906:172;-1:-1:-1;;;;;;;43154:21:0;;43150:68;;43193:16;43207:1;43193:13;:16::i;43150:68::-;43307:46;;-1:-1:-1;;;43307:46:0;;14631:42;;43307:37;;:46;;43345:7;;43307:46;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;43307:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;43307:46:0;;;;42656:703;;;;;;:::o;23132:1740::-;23324:7;23420:181;23461:24;23505:6;23513:9;23494:29;;;;;;;;;;23420:181;;;16781:15;23685:6;:36;23681:83;;23739:16;23753:1;23739:13;:16::i;23681:83::-;-1:-1:-1;;;;;23836:23:0;;23832:70;;23877:16;23891:1;23877:13;:16::i;23832:70::-;23981:16;:44;;-1:-1:-1;;23981:44:0;24000:25;23981:44;;;24478:89;;24410:23;;24467:4;;-1:-1:-1;;;24509:32:0;24478:89;;24543:6;;24551:9;;24478:89;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;24478:89:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;24478:89:0;;;179:29:-1;;;;160:49;;;24459:109:0;;;;24478:89;24459:109;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;24440:128:0;;-1:-1:-1;24440:128:0;-1:-1:-1;24440:128:0;24657:210;;15087:42;-1:-1:-1;;;;;;;;;;;24709:16:0;24723:1;24709:13;:16::i;:::-;24680:46;;;;;;;;;;;;;;;24657:210;;17714:1049;17881:7;17869:20;17866:2;;;17902:1;17899;17892:12;17866:2;17986:34;18005:14;17986:18;:34::i;:::-;18111:31;18128:13;18111:16;:31::i;:::-;18107:278;;;18230:29;;-1:-1:-1;;;18230:29:0;;18209:18;;15087:42;;18230:14;;:29;;18253:4;;18230:29;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;18230:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18230:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;18230:29:0;;;;;;;;;18209:50;;18331:46;18351:13;18366:10;18331:19;:46::i;:::-;18107:278;;18477:32;18494:14;18477:16;:32::i;:::-;18473:285;;;18599:30;;-1:-1:-1;;;18599:30:0;;18577:19;;15214:42;;18599:15;;:30;;18623:4;;18599:30;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;18599:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;18599:30:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;18599:30:0;;;;;;;;;18577:52;;18702:48;18722:14;18738:11;18702:19;:48::i;:::-;18473:285;17714:1049;:::o;37701:1638::-;37893:7;37902:23;38011:33;38041:2;38011:29;:33::i;:::-;38134:16;38152:13;38169:166;38210:18;38248:2;38252:4;;38237:20;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;49:4;38169:166:0;;;;;;;;;;;;;;;;;;38237:20;38266:16;;38291:13;;;;;;38169:166;;38291:13;;;;38169:166;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;38169:166:0;;;;137:4:-1;38169:166:0;;;;;;;;;;;;;;;;;;-1:-1:-1;38313:15:0;;-1:-1:-1;38313:15:0;;;;38169:166;;38313:15;;;;38169:166;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;38169:32:0;;-1:-1:-1;;;38169:166:0:i;:::-;38133:202;;;;38766:2;-1:-1:-1;;;;;38766:7:0;38774:4;;38766:13;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;38747:32:0;;-1:-1:-1;38747:32:0;-1:-1:-1;38870:464:0;;;;39050:57;39062:8;39072:5;39079;39086:2;39090:4;;39096:10;39050:57;;;;;;;;;;;;;;;;;;;;;38870:464;;;39268:58;39280:8;39290:5;39297:2;39301:4;;39314:10;39268:58;;;;;;;;;;;;;;;;;;;;38870:464;37701:1638;;;;;;;;;;;;;:::o;10651:389::-;10749:12;10778:10;10594:42;10778:24;10770:74;;;;-1:-1:-1;;;10770:74:0;;;;;;;;;10865:6;-1:-1:-1;;;;;10865:11:0;10883:6;10865:29;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;10851:43:0;;;;;10906:7;10901:134;;10965:16;10962:1;10959;10944:38;11002:16;10999:1;10992:27;10933:95;10651:389;;;;:::o;57616:85::-;57689:6;;;57616:85::o;52145:1779::-;52251:11;52264:19;14631:42;-1:-1:-1;;;;;52287:37:0;;:39;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52287:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;52287:39:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;52287:39:0;;;;;;;;;52250:76;;;;52416:6;52411:54;;52440:16;52454:1;52440:13;:16::i;52411:54::-;52537:10;-1:-1:-1;;;;;52537:25:0;;;52533:72;;52580:16;52594:1;52580:13;:16::i;52533:72::-;52671:42;52699:13;52671:27;:42::i;:::-;52783:43;52811:14;52783:27;:43::i;:::-;52900:36;15087:42;52919:10;52931:4;52900:12;:36::i;:::-;;53011:37;15214:42;53031:10;53043:4;53011:12;:37::i;:::-;;53118:62;15343:42;53163:10;53175:4;53118:12;:62::i;:::-;;53251:63;15473:42;53297:10;53309:4;53251:12;:63::i;:::-;;53384:62;14831:42;53429:10;53441:4;53384:12;:62::i;:::-;;53517:63;14961:42;53563:10;53575:4;53517:12;:63::i;:::-;-1:-1:-1;53687:21:0;53719:11;;53715:148;;53822:33;53835:10;53847:7;53822:12;:33::i;:::-;;53715:148;53909:9;;;;;;;52145:1779;;;:::o;82935:441::-;83077:16;83193:177;83214:29;83263:5;83252:17;;;;;;;;;83193:177;83182:188;82935:441;-1:-1:-1;;;;82935:441:0:o;78765:1051::-;78862:31;78981:69;-1:-1:-1;;;78981:20:0;:69::i;:::-;79118:12;;79101:30;;;;;;;;;;;;;;;;79059:13;;79101:30;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;79087:44:0;-1:-1:-1;79145:9:0;79140:417;79164:5;:12;79160:1;:16;79140:417;;;79262:7;79271:23;79298:5;79304:1;79298:8;;;;;;;;;;;;;;:11;;;-1:-1:-1;;;;;79298:16:0;79315:5;79321:1;79315:8;;;;;;;;;;;;;;:13;;;79298:31;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;79261:68:0;;;;79355:44;;;;;;;;79371:2;79355:44;;;;;;79387:10;79355:44;;;79338:11;79350:1;79338:14;;;;;;;;;;;;;:61;;;;79413:2;79408:142;;79520:4;79509:15;;79535:5;;;;79408:142;-1:-1:-1;;79178:3:0;;79140:417;;;;79569:8;79565:246;;;79669:29;79712:11;79701:23;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;79701:23:0;;;79669:55;;79784:16;79778:23;79759:16;79755:2;79751:25;79744:58;79742:62;78765:1051;;;;:::o;19180:1677::-;19298:29;;-1:-1:-1;;;19298:29:0;;19277:18;;15087:42;;19298:14;;:29;;19321:4;;19298:29;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19298:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19298:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;19298:29:0;;;;;;;;;19277:50;-1:-1:-1;19415:14:0;;19411:612;;19463:45;;-1:-1:-1;;;19463:45:0;;19440:20;;15087:42;;19463:14;;:45;;19486:4;;14831:42;;19463:45;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19463:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;19463:45:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;19463:45:0;;;;;;;;;19440:68;;19609:10;19594:12;:25;19590:426;;;19636:31;19653:13;19636:16;:31::i;:::-;19632:176;;;19750:46;19770:13;19785:10;19750:19;:46::i;:::-;19590:426;;;19960:46;19980:13;19995:10;19960:19;:46::i;:::-;19411:612;;20108:30;;-1:-1:-1;;;20108:30:0;;20086:19;;15214:42;;20108:15;;:30;;20132:4;;20108:30;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20108:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;20108:30:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;20108:30:0;;;;;;;;;20086:52;-1:-1:-1;20228:15:0;;20224:628;;20278:47;;-1:-1:-1;;;20278:47:0;;20254:21;;15214:42;;20278:15;;:47;;20302:4;;14961:42;;20278:47;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20278:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;20278:47:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;20278:47:0;;;;;;;;;20254:71;;20427:11;20411:13;:27;20407:438;;;20455:32;20472:14;20455:16;:32::i;:::-;20451:181;;;20572:48;20592:14;20608:11;20572:19;:48::i;:::-;20407:438;;;20787:48;20807:14;20823:11;20787:19;:48::i;:::-;20224:628;19180:1677;;:::o;50458:855::-;50629:7;50638:23;50749:61;-1:-1:-1;;;50749:20:0;:61::i;:::-;50921:95;;-1:-1:-1;;;50921:95:0;;50899:19;;15701:42;;50921:28;;50956:11;;50921:95;;50977:18;;50997:6;;51005:4;;;;50921:95;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;50921:95:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;50921:95:0;;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;50921:95:0;;;;;;;;;50899:117;;51121:18;51107:11;:32;51103:80;;;51157:17;51171:2;51157:13;:17::i;51103:80::-;51260:47;51280:13;51295:11;51260:19;:47::i;:::-;50458:855;;;;;;;;;:::o;59258:486::-;59417:16;59533:205;59554:6;59569:67;59610:6;59618;59626:9;59569:40;:67::i;:::-;59645:6;;59685:15;;59660:16;;-1:-1:-1;;;;;59685:15:0;59709:22;107234:152;107295:24;14031:42;-1:-1:-1;;;;;107351:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;107351:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;107351:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;107351:29:0;;;;;;;;;107332:48;;107234:152;:::o;108868:579::-;109082:16;109249:4;13842:2;109304:14;109329:16;109356:5;109372:16;109399:6;109416:9;109214:220;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;109214:220:0;;;109196:245;;;;;;109185:256;;108868:579;;;;;;;;:::o;115653:148::-;115761:34;;-1:-1:-1;;;115761:34:0;;115723:20;;15941:42;;115761:28;;:34;;115790:4;;115761:34;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;115761:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;115761:34:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;115761:34:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;115761:34:0;;;;;;;;83717:303;-1:-1:-1;;;;;83857:28:0;;83853:76;;83903:17;83917:2;83903:13;:17::i;83853:76::-;83937:15;:32;;-1:-1:-1;;;;;;83937:32:0;-1:-1:-1;;;;;83937:32:0;;;;;83981:33;;;;;;83937:32;;83981:33;;;;;;;;;;83717:303;:::o;111348:313::-;111425:15;:2;-1:-1:-1;;;;;111425:13:0;;:15::i;:::-;111420:64;;111458:17;111472:2;111458:13;:17::i;111420:64::-;-1:-1:-1;;;;;111500:19:0;;111514:4;111500:19;111496:67;;;111537:17;111551:2;111537:13;:17::i;111496:67::-;-1:-1:-1;;;;;111575:37:0;;14631:42;111575:37;111571:85;;;111630:17;111644:2;111630:13;:17::i;95561:2850::-;95778:16;;96297:21;;96293:123;;96345:16;96333:9;:28;96329:80;;;96381:17;96395:2;96381:13;:17::i;96329:80::-;-1:-1:-1;96500:6:0;;96593:22;96618:15;;-1:-1:-1;;;;;96618:15:0;;96749:22;:20;:22::i;:::-;96722:49;;96859:145;96880:6;96895:9;96913:11;96933:16;96958:14;96981:16;96859:12;:145::i;:::-;96848:156;;97093:19;97115:33;:8;:31;:33::i;:::-;97093:55;-1:-1:-1;97253:17:0;97243:6;:27;;;;;;;;;97239:1070;;97358:10;-1:-1:-1;;;;;97358:28:0;;;97354:244;;97416:111;97453:11;97466:6;97474:9;97485:14;97501:13;97416:22;:111::i;:::-;97399:190;;97559:17;97573:2;97559:13;:17::i;97399:190::-;97687:10;-1:-1:-1;;;;;97687:30:0;;;97683:168;;97754:36;:11;97774:15;97754:36;:19;:36;:::i;:::-;-1:-1:-1;;;;;97734:56:0;:16;-1:-1:-1;;;;;97734:56:0;;97730:112;;97812:17;97826:2;97812:13;:17::i;97730:112::-;97239:1070;;;97957:10;-1:-1:-1;;;;;97957:28:0;;;;;;:62;;-1:-1:-1;97989:10:0;-1:-1:-1;;;;;97989:30:0;;;;97957:62;97953:349;;;98068:36;:11;98088:15;98068:36;:19;:36;:::i;:::-;-1:-1:-1;;;;;98048:56:0;:16;-1:-1:-1;;;;;98048:56:0;;;:183;;;;;98120:111;98157:11;98170:6;98178:9;98189:14;98205:13;98120:22;:111::i;:::-;98119:112;98048:183;98032:261;;;98263:17;98277:2;98263:13;:17::i;98032:261::-;-1:-1:-1;;98397:6:0;:8;;;;;;-1:-1:-1;95561:2850:0;;;;-1:-1:-1;95561:2850:0;-1:-1:-1;;;;95561:2850:0:o;106286:575::-;106487:10;106511:27;:14;-1:-1:-1;;;;;106511:25:0;;:27::i;:::-;106506:350;;106575:34;:11;106595:13;106575:34;:19;:34;:::i;:::-;-1:-1:-1;;;;;106557:52:0;:14;-1:-1:-1;;;;;106557:52:0;;106549:60;;106506:350;;;106632:17;106663:11;106676:6;106684:9;106652:42;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;106652:42:0;;;;-1:-1:-1;;;106722:92:0;;;106652:42;;-1:-1:-1;16620:18:0;-1:-1:-1;;;;;106722:49:0;;;16627:10;;106722:92;;106652:42;;106790:13;;106722:92;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;106722:92:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;106722:92:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;106722:92:0;;;;;;;;;-1:-1:-1;;;;;;106722:117:0;;;106286:575;-1:-1:-1;;;;;;;106286:575:0:o;9706:608::-;9794:7;9814:9;:16;9834:2;9814:22;9810:64;;-1:-1:-1;9863:1:0;9847:19;;9810:64;9974:4;9959:20;;9953:27;10014:4;9999:20;;9993:27;10062:4;10047:20;;10041:27;9882:9;10033:36;10101:66;10088:79;;10084:119;;;10193:1;10178:17;;;;;;;10084:119;10215:1;:7;;10220:2;10215:7;;:18;;;;;10226:1;:7;;10231:2;10226:7;;10215:18;10211:58;;;10259:1;10244:17;;;;;;;10211:58;10284:24;10294:4;10300:1;10303;10306;10284:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;10284:24:0;;-1:-1:-1;;10284:24:0;;;9706:608;-1:-1:-1;;;;;;;9706:608:0:o;98699:914::-;98764:22;;;98828:5;:22;;;;;;;;;98824:144;;;-1:-1:-1;15343:42:0;;-1:-1:-1;14831:42:0;98824:144;;;-1:-1:-1;15473:42:0;;-1:-1:-1;14961:42:0;98824:144;99051:31;;-1:-1:-1;;;99051:31:0;;99033:15;;-1:-1:-1;;;;;99051:16:0;;;;;:31;;99076:4;;99051:31;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;99051:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;99051:31:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;99051:31:0;;;;;;;;;99033:49;-1:-1:-1;99163:11:0;;99159:449;;99263:48;;-1:-1:-1;;;99263:48:0;;99314:7;;-1:-1:-1;;;;;99263:16:0;;;;;:48;;99288:4;;99303:6;;99263:48;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;99263:48:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;99263:48:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;99263:48:0;;;;;;;;;:58;99259:185;;;99339:44;;-1:-1:-1;;;99339:44:0;;-1:-1:-1;;;;;99339:14:0;;;;;:44;;99362:6;;-1:-1:-1;;99379:2:0;99339:44;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;99339:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;99339:44:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;99339:44:0;;;;;;;;;99334:101;;99405:17;99419:2;99405:13;:17::i;99334:101::-;99519:29;;-1:-1:-1;;;99519:29:0;;-1:-1:-1;;;;;99519:20:0;;;;;:29;;99540:7;;99519:29;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;99519:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;99519:29:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;99519:29:0;;;;;;;;;99515:86;;99573:17;99587:2;99573:13;:17::i;99515:86::-;98699:914;;;;:::o;102877:1286::-;103029:26;-1:-1:-1;;;;;;103066:43:0;;-1:-1:-1;;;103066:43:0;103062:138;;;-1:-1:-1;103120:25:0;;;;;;;;;;;;-1:-1:-1;;;103120:25:0;;;;103062:138;;;-1:-1:-1;103168:24:0;;;;;;;;;;;;-1:-1:-1;;;103168:24:0;;;;103062:138;103364:40;;-1:-1:-1;;;103364:40:0;;15214:42;;;;103364:25;;:40;;103398:4;;103364:40;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;103364:40:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;103364:40:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;103364:40:0;;;;;;;;;103360:798;;;15214:42;-1:-1:-1;;;;;103420:189:0;-1:-1:-1;;;;;;;;;;;103519:12:0;103488:101;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;103488:101:0;;;;103420:189;;;;;;;;;;;;103360:798;;;103672:11;-1:-1:-1;;;;;103672:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;103672:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;103672:20:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;103672:20:0;;;;;;;;;103668:483;;;15214:42;-1:-1:-1;;;;;103710:206:0;-1:-1:-1;;;;;;;;;;;103817:12:0;103784:108;;;;;;;;;103668:483;15214:42;-1:-1:-1;;;;;103948:193:0;-1:-1:-1;;;;;;;;;;;104085:12:0;104022:95;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;104022:95:0;;;;103948:193;;;;;;;;;;;;102877:1286;;;:::o;112691:1433::-;112828:22;112926:20;;112958:6;:27;;;;;;;;;:76;;;-1:-1:-1;113006:28:0;112996:6;:38;;;;;;;;;112958:76;:121;;;-1:-1:-1;113055:24:0;113045:6;:34;;;;;;;;;112958:121;:167;;;-1:-1:-1;113100:25:0;113090:6;:35;;;;;;;;;112958:167;:212;;;-1:-1:-1;113146:24:0;113136:6;:34;;;;;;;;;112958:212;:258;;;-1:-1:-1;113191:25:0;113181:6;:35;;;;;;;;;112958:258;:307;;;-1:-1:-1;113237:28:0;113227:6;:38;;;;;;;;;112958:307;:357;;;-1:-1:-1;113286:29:0;113276:6;:39;;;;;;;;;112958:357;112926:396;;113334:15;113329:64;;113367:17;113381:2;113367:13;:17::i;113329:64::-;113505:17;113495:6;:27;;;;;;;;;:76;;;-1:-1:-1;113543:28:0;113533:6;:38;;;;;;;;;113495:76;:126;;;-1:-1:-1;113592:29:0;113582:6;:39;;;;;;;;;113495:126;113483:636;;;113732:12;;;26:21:-1;6:49;;113732:12:0;;;;;;;-1:-1:-1;113483:636:0;;;113780:28;113770:6;:38;;;;;;;;;:84;;;-1:-1:-1;113829:25:0;113819:6;:35;;;;;;;;;113770:84;113758:361;;;113965:9;113954:21;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;113954:21:0;;;113942:33;;113758:361;;;114093:6;114101:9;114082:29;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;114082:29:0;;;114070:41;;113758:361;112691:1433;;;;;;:::o;93203:413::-;93296:12;93410:9;-1:-1:-1;;;;;93410:14:0;16982:4;93454:6;93410:55;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;93396:69:0;;;;;93477:7;93472:139;;93514:9;-1:-1:-1;;;;;93500:43:0;-1:-1:-1;;;;;;;;;;;93525:17:0;93539:2;93525:13;:17::i;:::-;93500:43;;;;;;;;;;;;;;;93472:139;;;93571:32;93585:6;93593:9;93571:32;;;;;;;;;;;;;;;;93203:413;;;;:::o;104678:337::-;104831:10;104853:4;104831:27;;;:66;;-1:-1:-1;104862:16:0;;;;-1:-1:-1;;;;;;104862:35:0;;;;;;;;104831:66;104827:114;;;104915:17;104929:2;104915:13;:17::i;104827:114::-;-1:-1:-1;104993:16:0;104986:23;;-1:-1:-1;;104986:23:0;;;104678:337::o;88993:1378::-;89145:14;;89162:5;:22;;;;;;;;;:57;;14961:42;89162:57;;;14831:42;89162:57;89375:85;;89145:74;;-1:-1:-1;89297:28:0;;;;89342:17;;-1:-1:-1;;;;;89363:11:0;;;-1:-1:-1;;;89406:32:0;89375:85;;89448:4;;89375:85;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;89375:85:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;89375:85:0;;;179:29:-1;;;;160:49;;;89363:98:0;;;;89375:85;89363:98;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;89332:129:0;;-1:-1:-1;89332:129:0;-1:-1:-1;89470:20:0;89332:129;89505:23;;;;;89511:4;:11;89526:2;89511:17;89505:23;89501:301;;;89565:4;89554:27;;;;;;;;;;;;;;89539:42;;89501:301;;;89682:112;89736:5;-1:-1:-1;;;89777:2:0;89781:4;89682:43;:112::i;:::-;;89501:301;89886:16;;89882:484;;90015:156;;-1:-1:-1;;;;;90003:11:0;;;-1:-1:-1;;;90127:21:0;90015:156;;90150:12;;90015:156;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;90015:156:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;90015:156:0;;;179:29:-1;;;;160:49;;;90003:169:0;;;;90015:156;90003:169;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;89990:182:0;;-1:-1:-1;89990:182:0;-1:-1:-1;90257:101:0;90311:5;-1:-1:-1;;;89990:182:0;;90257:43;:101::i;:::-;;88993:1378;;;;;;:::o;91222:1489::-;91334:12;;91489:4;91505:14;91500:539;;91540:30;;-1:-1:-1;;;91540:30:0;;-1:-1:-1;;;;;91540:15:0;;;;;:30;;91564:4;;91540:30;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;91540:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;91540:30:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;91540:30:0;;;;;;;;;91530:40;;91500:539;;;91673:7;91682:17;91711:5;-1:-1:-1;;;;;91703:19:0;91739:1;91727:9;:13;;;;;91752:63;;91727:13;;;;-1:-1:-1;;;91775:24:0;91752:63;;91809:4;;91752:63;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;91752:63:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;91752:63:0;;;179:29:-1;;;;160:49;;;91703:121:0;;;;91752:63;91703:121;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;91672:152:0;;;;91839:2;:23;;;;;91845:4;:11;91860:2;91845:17;91839:23;91835:197;;;91896:4;91885:27;;;;;;;;;;;;;;91875:37;;91835:197;;;92017:5;91996:26;;91835:197;91500:539;;;92125:11;;92121:585;;92152:14;92147:420;;92271:34;;-1:-1:-1;;;92271:34:0;;-1:-1:-1;;;;;92271:14:0;;;;;:34;;92286:9;;92297:7;;92271:34;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;92271:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;92271:34:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;92271:34:0;;;;;;;;;92261:44;;92147:420;;;92436:5;-1:-1:-1;;;;;92428:19:0;92464:1;92452:9;:13;;;;;92479:67;;92452:13;;;;-1:-1:-1;;;92502:23:0;92479:67;;92527:9;;92538:7;;92479:67;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;92479:67:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;92479:67:0;;;179:29:-1;;;;160:49;;;92428:129:0;;;;92479:67;92428:129;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;92414:143:0;;-1:-1:-1;;92147:420:0;92121:585;;;92680:18;92670:28;;92121:585;91222:1489;;;;;;;:::o;87888:765::-;87984:12;;;88104:5;:22;;;;;;;;;:57;;14961:42;88104:57;;;14831:42;88104:57;88288:160;;88087:74;;-1:-1:-1;88246:7:0;;88255:17;;-1:-1:-1;;;;;88276:11:0;;;-1:-1:-1;;;88401:31:0;88288:160;;88434:7;;88288:160;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;88288:160:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;88288:160:0;;;179:29:-1;;;;160:49;;;88276:173:0;;;;88288:160;88276:173;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;88245:204:0;;-1:-1:-1;88245:204:0;-1:-1:-1;88540:107:0;88592:5;-1:-1:-1;;;88245:204:0;;88540:43;:107::i;114417:966::-;114504:26;114653:2;114633:10;:17;:22;:104;;;;-1:-1:-1;114710:13:0;;-1:-1:-1;;;114727:10:0;114710;;114721:1;;114710:13;;;;;;;;-1:-1:-1;;;;;;114710:13:0;:27;114633:104;:142;;;;-1:-1:-1;114748:13:0;;-1:-1:-1;;;114765:10:0;114748;;114759:1;;114748:13;;;;;;;;;;-1:-1:-1;;;;;;114748:13:0;:27;114633:142;:180;;;;-1:-1:-1;114786:13:0;;-1:-1:-1;;;114803:10:0;114786;;114797:1;;114786:13;;;;;;;;;;-1:-1:-1;;;;;;114786:13:0;:27;114633:180;:218;;;;-1:-1:-1;114824:13:0;;-1:-1:-1;;;114841:10:0;114824;;114835:1;;114824:13;;;;;;;;;;-1:-1:-1;;;;;;114824:13:0;:27;114633:218;114621:757;;;114941:30;115004:1;114984:10;:17;:21;114974:32;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;104:10;114974:32:0;87:34:-1;135:17;;-1:-1;114974:32:0;-1:-1:-1;114941:65:0;-1:-1:-1;115032:1:0;115015:109;115039:10;:17;115035:1;:21;115015:109;;;115101:10;115112:1;115101:13;;;;;;;;;;;;;;;;115074:17;115096:1;115092;:5;115074:24;;;;;;;;;;;:40;-1:-1:-1;;;;;115074:40:0;;;;;;;;-1:-1:-1;115058:3:0;;115015:109;;;;115218:17;115207:39;;;;;;;;;;;;;;115192:54;;114621:757;;;;115344:26;-1:-1:-1;;115344:13:0;:26::i;114621:757::-;114417:966;;;:::o;84391:1012::-;84452:7;;;;84592:5;:22;;;;;;;;;84588:176;;;-1:-1:-1;15087:42:0;;-1:-1:-1;14831:42:0;84588:176;;;-1:-1:-1;15214:42:0;;-1:-1:-1;14961:42:0;84588:176;84882:155;;-1:-1:-1;;;;;84862:19:0;;;-1:-1:-1;;;84988:21:0;84882:155;;85011:6;;-1:-1:-1;;85027:2:0;84882:155;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;84882:155:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;84882:155:0;;;179:29:-1;;;;160:49;;;84862:176:0;;;;84882:155;84862:176;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;84853:185:0;;;;;85111:2;85106:292;;85137:13;85128:5;:22;;;;;;;;;85124:267;;;15087:42;-1:-1:-1;;;;;;;;;;;85197:17:0;85211:2;85197:13;:17::i;:::-;85168:47;;;;;;;;;;;;;;;85124:267;;;85324:57;-1:-1:-1;;;85324:33:0;:57::i;:::-;84391:1012;;;;;:::o;86116:1000::-;86292:13;86283:5;:22;;;;;;;;;:62;;;;;16781:15;86309:7;:36;86283:62;:230;;;-1:-1:-1;86365:14:0;86356:5;:23;;;;;;;;;:157;;;;;16856:3;86394:7;:37;:110;;;;-1:-1:-1;86452:46:0;;-1:-1:-1;;;86452:46:0;;16104:42;;86452:20;;:46;;16228:66;;86452:46;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;86452:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;86452:46:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;86452:46:0;;;;;;;;;86444:60;;86394:110;86271:840;;;86579:14;;86596:5;:22;;;;;;;;;:57;;14961:42;86596:57;;;14831:42;86596:57;86769:149;;86579:74;;-1:-1:-1;86727:7:0;;86736:17;;-1:-1:-1;;;;;86757:11:0;;;-1:-1:-1;;;86881:19:0;86769:149;;86902:7;;86769:149;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;86769:149:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;86769:149:0;;;179:29:-1;;;;160:49;;;86757:162:0;;;;86769:149;86757:162;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;86726:193:0;;-1:-1:-1;86726:193:0;-1:-1:-1;87004:99:0;87058:5;-1:-1:-1;;;86726:193:0;;87004:43;:99::i;9518:160::-;9629:20;9664:8;;;9518:160::o;10320:167::-;10389:7;10475:4;10422:58;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;10422:58:0;;;10412:69;;;;;;10405:76;;10320:167;;;:::o;100378:2109::-;100544:12;100641:2;100637:1845;;;100658:4;:11;100673:2;100658:17;100654:1195;;;100688:14;100716:4;100705:27;;;;;;;;;;;;;;100688:44;-1:-1:-1;100747:10:0;;100743:593;;100782:4;100772:14;;100743:593;;;100898:15;100915:18;100935:26;100980:47;101003:5;101010:16;100980:22;:47::i;:::-;100897:143;;;;;;101088:7;-1:-1:-1;;;;;101060:255:0;-1:-1:-1;;;;;;;;;;;101168:4:0;101236:12;101133:154;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;101133:154:0;;;;101060:255;;;;;;;;;;;;100743:593;;;;100654:1195;;;;101441:15;101458:18;101478:26;101521:47;101544:5;101551:16;101521:22;:47::i;:::-;101440:139;;;;;;101623:7;-1:-1:-1;;;;;101597:234:0;-1:-1:-1;;;;;;;;;;;101697:4:0;101760:12;101664:143;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;101664:143:0;;;;101597:234;;;;;;;;;;;;100654:1195;;;;100637:1845;;;101956:15;101973:18;101993:26;102034:47;102057:5;102064:16;102034:22;:47::i;:::-;101955:135;;;;;;102167:26;102196:25;102216:4;102196:19;:25::i;:::-;102167:54;;102261:7;-1:-1:-1;;;;;102237:237:0;-1:-1:-1;;;;;;;;;;;102329:4:0;102383:12;102429;102298:156;;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;102298:156:0;;;;102237:237;;;;;;;;;;;;100637:1845;;;;100378:2109;;;;;;:::o;109982:862::-;110100:15;110122:18;;110100:15;110190:5;:22;;;;;;;;;110186:178;;;14831:42;110223:24;;110256:19;;;;;;;;;;;;;-1:-1:-1;;;110256:19:0;;;;;110186:178;;;14961:42;110298:25;;110332:24;;;;;;;;;;;;;-1:-1:-1;;;110332:24:0;;;;;110186:178;-1:-1:-1;;;;;;110451:39:0;;-1:-1:-1;;;110451:39:0;110447:392;;;-1:-1:-1;110501:21:0;;;;;;;;;;;;-1:-1:-1;;;110501:21:0;;;;110447:392;;;-1:-1:-1;;;;;;110549:62:0;;-1:-1:-1;;;110549:62:0;110545:287;;;-1:-1:-1;110624:26:0;;;;;;;;;;;;-1:-1:-1;;;110624:26:0;;;;110545:287;;;-1:-1:-1;;;;;;110749:41:0;;-1:-1:-1;;;110749:41:0;:61;;;;;;;;;;;;;;;-1:-1:-1;;;110749:61:0;;;;;;;;;;;;;;;;;;;110699:122;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;110699:122:0;;;110677:145;;110545:287;109982:862;;;;;:::o;12298:103506::-;;;;;;;;;;-1:-1:-1;12298:103506:0;;;;;;;;:::o;5:130:-1:-;72:20;;97:33;72:20;97:33;;142:134;220:13;;238:33;220:13;238:33;;664:744;;810:3;803:4;795:6;791:17;787:27;777:2;;828:1;825;818:12;777:2;858:6;852:13;880:98;895:82;970:6;895:82;;;880:98;;;1006:21;;;1050:4;1038:17;;;;871:107;;-1:-1;1063:14;;1038:17;1158:1;1143:259;1168:6;1165:1;1162:13;1143:259;;;1244:3;1238:10;1230:6;1226:23;1268:70;1334:3;1322:10;1268:70;;;1256:83;;-1:-1;1362:4;1353:14;;;;1381;;;;;1190:1;1183:9;1143:259;;;1147:14;770:638;;;;;;;;1481:726;;1614:3;1607:4;1599:6;1595:17;1591:27;1581:2;;1632:1;1629;1622:12;1581:2;1669:6;1656:20;1691:96;1706:80;1779:6;1706:80;;1691:96;1815:21;;;1859:4;1847:17;;;;1682:105;;-1:-1;1872:14;;1847:17;1967:1;1952:249;1977:6;1974:1;1971:13;1952:249;;;2060:3;2047:17;2039:6;2035:30;2084:53;2133:3;2121:10;2084:53;;;2072:66;;-1:-1;2161:4;2152:14;;;;2180;;;;;1999:1;1992:9;1952:249;;2215:128;2290:13;;2308:30;2290:13;2308:30;;2350:130;2417:20;;2442:33;2417:20;2442:33;;2487:134;2565:13;;2583:33;2565:13;2583:33;;2628:132;2705:13;;2723:32;2705:13;2723:32;;2781:336;;;2895:3;2888:4;2880:6;2876:17;2872:27;2862:2;;2913:1;2910;2903:12;2862:2;-1:-1;2933:20;;-1:-1;;;;;2962:30;;2959:2;;;3005:1;3002;2995:12;2959:2;3039:4;3031:6;3027:17;3015:29;;3090:3;3082:4;3074:6;3070:17;3060:8;3056:32;3053:41;3050:2;;;3107:1;3104;3097:12;3050:2;2855:262;;;;;;3126:432;;3223:3;3216:4;3208:6;3204:17;3200:27;3190:2;;3241:1;3238;3231:12;3190:2;3278:6;3265:20;3300:60;3315:44;3352:6;3315:44;;3300:60;3291:69;;3380:6;3373:5;3366:21;3416:4;3408:6;3404:17;3449:4;3442:5;3438:16;3484:3;3475:6;3470:3;3466:16;3463:25;3460:2;;;3501:1;3498;3491:12;3460:2;3511:41;3545:6;3540:3;3535;3511:41;;;3183:375;;;;;;;;3567:434;;3675:3;3668:4;3660:6;3656:17;3652:27;3642:2;;3693:1;3690;3683:12;3642:2;3723:6;3717:13;3745:60;3760:44;3797:6;3760:44;;3745:60;3736:69;;3825:6;3818:5;3811:21;3861:4;3853:6;3849:17;3894:4;3887:5;3883:16;3929:3;3920:6;3915:3;3911:16;3908:25;3905:2;;;3946:1;3943;3936:12;3905:2;3956:39;3988:6;3983:3;3978;3956:39;;4458:158;4539:20;;4564:47;4539:20;4564:47;;5588:582;;5710:4;5698:9;5693:3;5689:19;5685:30;5682:2;;;5728:1;5725;5718:12;5682:2;5746:20;5761:4;5746:20;;;5737:29;-1:-1;5814:1;5846:57;5899:3;5879:9;5846:57;;;5821:83;;-1:-1;5992:2;5977:18;;5971:25;-1:-1;;;;;6005:30;;6002:2;;;6048:1;6045;6038:12;6002:2;6083:65;6144:3;6135:6;6124:9;6120:22;6083:65;;;6076:4;6069:5;6065:16;6058:91;5925:235;5676:494;;;;;6238:547;;6343:4;6331:9;6326:3;6322:19;6318:30;6315:2;;;6361:1;6358;6351:12;6315:2;6379:20;6394:4;6379:20;;;6370:29;-1:-1;6447:1;6479:49;6524:3;6504:9;6479:49;;;6454:75;;-1:-1;6618:2;6603:18;;6590:32;-1:-1;;;;;6631:30;;6628:2;;;6674:1;6671;6664:12;6628:2;6709:54;6759:3;6750:6;6739:9;6735:22;6709:54;;7070:241;;7174:2;7162:9;7153:7;7149:23;7145:32;7142:2;;;7190:1;7187;7180:12;7142:2;7225:1;7242:53;7287:7;7267:9;7242:53;;7318:263;;7433:2;7421:9;7412:7;7408:23;7404:32;7401:2;;;7449:1;7446;7439:12;7401:2;7484:1;7501:64;7557:7;7537:9;7501:64;;7874:382;;;8003:2;7991:9;7982:7;7978:23;7974:32;7971:2;;;8019:1;8016;8009:12;7971:2;8054:1;8071:61;8124:7;8104:9;8071:61;;;8061:71;;8033:105;8169:2;8187:53;8232:7;8223:6;8212:9;8208:22;8187:53;;;8177:63;;8148:98;7965:291;;;;;;8263:615;;;;;8420:2;8408:9;8399:7;8395:23;8391:32;8388:2;;;8436:1;8433;8426:12;8388:2;8471:1;8488:53;8533:7;8513:9;8488:53;;;8478:63;;8450:97;8606:2;8595:9;8591:18;8578:32;-1:-1;;;;;8622:6;8619:30;8616:2;;;8662:1;8659;8652:12;8616:2;8690:64;8746:7;8737:6;8726:9;8722:22;8690:64;;;8680:74;;;;8557:203;8791:2;8809:53;8854:7;8845:6;8834:9;8830:22;8809:53;;;8799:63;;8770:98;8382:496;;;;;;;;8885:1115;;;;;;;;;9114:3;9102:9;9093:7;9089:23;9085:33;9082:2;;;9131:1;9128;9121:12;9082:2;9166:1;9183:53;9228:7;9208:9;9183:53;;;9173:63;;9145:97;9301:2;9290:9;9286:18;9273:32;-1:-1;;;;;9317:6;9314:30;9311:2;;;9357:1;9354;9347:12;9311:2;9385:64;9441:7;9432:6;9421:9;9417:22;9385:64;;;9375:74;;;;9252:203;9486:2;9504:53;9549:7;9540:6;9529:9;9525:22;9504:53;;;9494:63;;9465:98;9622:2;9611:9;9607:18;9594:32;-1:-1;;;;;9638:6;9635:30;9632:2;;;9678:1;9675;9668:12;9632:2;9706:64;9762:7;9753:6;9742:9;9738:22;9706:64;;;9696:74;;;;9573:203;9835:3;9824:9;9820:19;9807:33;-1:-1;;;;;9852:6;9849:30;9846:2;;;9892:1;9889;9882:12;9846:2;9920:64;9976:7;9967:6;9956:9;9952:22;9920:64;;;9910:74;;;;9786:204;9076:924;;;;;;;;;;;;10007:741;;;;;;10181:3;10169:9;10160:7;10156:23;10152:33;10149:2;;;10198:1;10195;10188:12;10149:2;10233:1;10250:53;10295:7;10275:9;10250:53;;;10240:63;;10212:97;10368:2;10357:9;10353:18;10340:32;-1:-1;;;;;10384:6;10381:30;10378:2;;;10424:1;10421;10414:12;10378:2;10452:64;10508:7;10499:6;10488:9;10484:22;10452:64;;;10442:74;;;;10319:203;10553:2;10571:53;10616:7;10607:6;10596:9;10592:22;10571:53;;;10561:63;;10532:98;10661:2;10679:53;10724:7;10715:6;10704:9;10700:22;10679:53;;;10669:63;;10640:98;10143:605;;;;;;;;;10755:865;;;;;;;10948:3;10936:9;10927:7;10923:23;10919:33;10916:2;;;10965:1;10962;10955:12;10916:2;11000:1;11017:53;11062:7;11042:9;11017:53;;;11007:63;;10979:97;11107:2;11125:53;11170:7;11161:6;11150:9;11146:22;11125:53;;;11115:63;;11086:98;11243:2;11232:9;11228:18;11215:32;-1:-1;;;;;11259:6;11256:30;11253:2;;;11299:1;11296;11289:12;11253:2;11327:64;11383:7;11374:6;11363:9;11359:22;11327:64;;;11317:74;;;;11194:203;11456:2;11445:9;11441:18;11428:32;-1:-1;;;;;11472:6;11469:30;11466:2;;;11512:1;11509;11502:12;11466:2;11540:64;11596:7;11587:6;11576:9;11572:22;11540:64;;;11530:74;;;;11407:203;10910:710;;;;;;;;;11627:428;;11785:2;11773:9;11764:7;11760:23;11756:32;11753:2;;;11801:1;11798;11791:12;11753:2;11836:24;;-1:-1;;;;;11869:30;;11866:2;;;11912:1;11909;11902:12;11866:2;11932:107;12031:7;12022:6;12011:9;12007:22;11932:107;;12062:409;;12207:2;12195:9;12186:7;12182:23;12178:32;12175:2;;;12223:1;12220;12213:12;12175:2;12258:31;;-1:-1;;;;;12298:30;;12295:2;;;12341:1;12338;12331:12;12295:2;12361:94;12447:7;12438:6;12427:9;12423:22;12361:94;;12478:534;;;12640:2;12628:9;12619:7;12615:23;12611:32;12608:2;;;12656:1;12653;12646:12;12608:2;12691:31;;-1:-1;;;;;12731:30;;12728:2;;;12774:1;12771;12764:12;12728:2;12794:94;12880:7;12871:6;12860:9;12856:22;12794:94;;13019:993;;;;;13233:3;13221:9;13212:7;13208:23;13204:33;13201:2;;;13250:1;13247;13240:12;13201:2;13285:31;;-1:-1;;;;;13325:30;;13322:2;;;13368:1;13365;13358:12;13322:2;13388:94;13474:7;13465:6;13454:9;13450:22;13388:94;;;13378:104;;13264:224;13519:2;13537:53;13582:7;13573:6;13562:9;13558:22;13537:53;;;13527:63;;13498:98;13655:2;13644:9;13640:18;13627:32;-1:-1;;;;;13671:6;13668:30;13665:2;;;13711:1;13708;13701:12;13665:2;13731:62;13785:7;13776:6;13765:9;13761:22;13731:62;;;13721:72;;13606:193;13858:2;13847:9;13843:18;13830:32;-1:-1;;;;;13874:6;13871:30;13868:2;;;13914:1;13911;13904:12;13868:2;13934:62;13988:7;13979:6;13968:9;13964:22;13934:62;;14019:659;;;;14198:2;14186:9;14177:7;14173:23;14169:32;14166:2;;;14214:1;14211;14204:12;14166:2;14249:31;;-1:-1;;;;;14289:30;;14286:2;;;14332:1;14329;14322:12;14286:2;14352:94;14438:7;14429:6;14418:9;14414:22;14352:94;;;14342:104;;14228:224;14483:2;14501:53;14546:7;14537:6;14526:9;14522:22;14501:53;;;14491:63;;14462:98;14591:2;14609:53;14654:7;14645:6;14634:9;14630:22;14609:53;;;14599:63;;14570:98;14160:518;;;;;;14685:257;;14797:2;14785:9;14776:7;14772:23;14768:32;14765:2;;;14813:1;14810;14803:12;14765:2;14848:1;14865:61;14918:7;14898:9;14865:61;;14949:393;;;15078:2;15066:9;15057:7;15053:23;15049:32;15046:2;;;15094:1;15091;15084:12;15046:2;15129:1;15146:61;15199:7;15179:9;15146:61;;;15136:71;;15108:105;15244:2;15262:64;15318:7;15309:6;15298:9;15294:22;15262:64;;15349:241;;15453:2;15441:9;15432:7;15428:23;15424:32;15421:2;;;15469:1;15466;15459:12;15421:2;15504:1;15521:53;15566:7;15546:9;15521:53;;15597:263;;15712:2;15700:9;15691:7;15687:23;15683:32;15680:2;;;15728:1;15725;15718:12;15680:2;15763:1;15780:64;15836:7;15816:9;15780:64;;15867:462;;;15993:2;15981:9;15972:7;15968:23;15964:32;15961:2;;;16009:1;16006;15999:12;15961:2;16044:1;16061:53;16106:7;16086:9;16061:53;;;16051:63;;16023:97;16179:2;16168:9;16164:18;16151:32;-1:-1;;;;;16195:6;16192:30;16189:2;;;16235:1;16232;16225:12;16189:2;16255:58;16305:7;16296:6;16285:9;16281:22;16255:58;;16336:261;;16450:2;16438:9;16429:7;16425:23;16421:32;16418:2;;;16466:1;16463;16456:12;16418:2;16501:1;16518:63;16573:7;16553:9;16518:63;;16604:614;;;;;16763:2;16751:9;16742:7;16738:23;16734:32;16731:2;;;16779:1;16776;16769:12;16731:2;16814:31;;-1:-1;;;;;16854:30;;16851:2;;;16897:1;16894;16887:12;16851:2;16925:64;16981:7;16972:6;16961:9;16957:22;16925:64;;;16915:74;;;;16793:202;17054:2;17043:9;17039:18;17026:32;-1:-1;;;;;17070:6;17067:30;17064:2;;;17110:1;17107;17100:12;17064:2;17138:64;17194:7;17185:6;17174:9;17170:22;17138:64;;;16725:493;;;;-1:-1;17128:74;-1:-1;;;;16725:493;17225:645;;;;;17394:3;17382:9;17373:7;17369:23;17365:33;17362:2;;;17411:1;17408;17401:12;17362:2;17446:1;17463:67;17522:7;17502:9;17463:67;;;17453:77;;17425:111;17567:2;17585:53;17630:7;17621:6;17610:9;17606:22;17585:53;;;17575:63;;17546:98;17675:2;17693:53;17738:7;17729:6;17718:9;17714:22;17693:53;;;17683:63;;17654:98;17783:2;17801:53;17846:7;17837:6;17826:9;17822:22;17801:53;;17877:771;;;;;;18063:3;18051:9;18042:7;18038:23;18034:33;18031:2;;;18080:1;18077;18070:12;18031:2;18115:1;18132:67;18191:7;18171:9;18132:67;;;18122:77;;18094:111;18236:2;18254:53;18299:7;18290:6;18279:9;18275:22;18254:53;;;18244:63;;18215:98;18344:2;18362:53;18407:7;18398:6;18387:9;18383:22;18362:53;;;18352:63;;18323:98;18452:2;18470:53;18515:7;18506:6;18495:9;18491:22;18470:53;;;18460:63;;18431:98;18560:3;18579:53;18624:7;18615:6;18604:9;18600:22;18579:53;;18655:354;;18776:2;18764:9;18755:7;18751:23;18747:32;18744:2;;;18792:1;18789;18782:12;18744:2;18827:24;;-1:-1;;;;;18860:30;;18857:2;;;18903:1;18900;18893:12;18857:2;18923:70;18985:7;18976:6;18965:9;18961:22;18923:70;;19655:366;;;19776:2;19764:9;19755:7;19751:23;19747:32;19744:2;;;19792:1;19789;19782:12;19744:2;19827:1;19844:53;19889:7;19869:9;19844:53;;;19834:63;;19806:97;19934:2;19952:53;19997:7;19988:6;19977:9;19973:22;19952:53;;20028:1007;;;;;;;;20246:3;20234:9;20225:7;20221:23;20217:33;20214:2;;;20263:1;20260;20253:12;20214:2;20298:1;20315:53;20360:7;20340:9;20315:53;;;20305:63;;20277:97;20405:2;20423:61;20476:7;20467:6;20456:9;20452:22;20423:61;;;20413:71;;20384:106;20521:2;20539:53;20584:7;20575:6;20564:9;20560:22;20539:53;;;20529:63;;20500:98;20657:2;20646:9;20642:18;20629:32;-1:-1;;;;;20673:6;20670:30;20667:2;;;20713:1;20710;20703:12;20667:2;20741:64;20797:7;20788:6;20777:9;20773:22;20741:64;;;20731:74;;;;20608:203;20870:3;20859:9;20855:19;20842:33;-1:-1;;;;;20887:6;20884:30;20881:2;;;20927:1;20924;20917:12;20881:2;20955:64;21011:7;21002:6;20991:9;20987:22;20955:64;;;20945:74;;;;20821:204;20208:827;;;;;;;;;;;22040:490;;;;22180:2;22168:9;22159:7;22155:23;22151:32;22148:2;;;22196:1;22193;22186:12;22148:2;22231:1;22248:53;22293:7;22273:9;22248:53;;;22238:63;;22210:97;22366:2;22355:9;22351:18;22338:32;-1:-1;;;;;22382:6;22379:30;22376:2;;;22422:1;22419;22412:12;22376:2;22450:64;22506:7;22497:6;22486:9;22482:22;22450:64;;;22440:74;;;;22317:203;22142:388;;;;;;22537:739;;;;;;22713:2;22701:9;22692:7;22688:23;22684:32;22681:2;;;22729:1;22726;22719:12;22681:2;22764:1;22781:53;22826:7;22806:9;22781:53;;;22771:63;;22743:97;22899:2;22888:9;22884:18;22871:32;-1:-1;;;;;22915:6;22912:30;22909:2;;;22955:1;22952;22945:12;22909:2;22983:64;23039:7;23030:6;23019:9;23015:22;22983:64;;;22973:74;;;;22850:203;23112:2;23101:9;23097:18;23084:32;-1:-1;;;;;23128:6;23125:30;23122:2;;;23168:1;23165;23158:12;23122:2;23196:64;23252:7;23243:6;23232:9;23228:22;23196:64;;;23186:74;;;;23063:203;22675:601;;;;;;;;;23283:741;;;;;;23457:3;23445:9;23436:7;23432:23;23428:33;23425:2;;;23474:1;23471;23464:12;23425:2;23509:1;23526:53;23571:7;23551:9;23526:53;;;23516:63;;23488:97;23616:2;23634:53;23679:7;23670:6;23659:9;23655:22;23634:53;;;23624:63;;23595:98;23724:2;23742:53;23787:7;23778:6;23767:9;23763:22;23742:53;;;23732:63;;23703:98;23860:2;23849:9;23845:18;23832:32;-1:-1;;;;;23876:6;23873:30;23870:2;;;23916:1;23913;23906:12;24031:867;;;;;;;24222:3;24210:9;24201:7;24197:23;24193:33;24190:2;;;24239:1;24236;24229:12;24190:2;24274:1;24291:53;24336:7;24316:9;24291:53;;;24281:63;;24253:97;24381:2;24399:53;24444:7;24435:6;24424:9;24420:22;24399:53;;;24389:63;;24360:98;24489:2;24507:53;24552:7;24543:6;24532:9;24528:22;24507:53;;;24497:63;;24468:98;24625:2;24614:9;24610:18;24597:32;-1:-1;;;;;24641:6;24638:30;24635:2;;;24681:1;24678;24671:12;24635:2;24709:64;24765:7;24756:6;24745:9;24741:22;24709:64;;;24699:74;;;;24576:203;24810:3;24829:53;24874:7;24865:6;24854:9;24850:22;24829:53;;;24819:63;;24789:99;24184:714;;;;;;;;;24905:1367;;;;;;;;;;;25168:3;25156:9;25147:7;25143:23;25139:33;25136:2;;;25185:1;25182;25175:12;25136:2;25220:1;25237:53;25282:7;25262:9;25237:53;;;25227:63;;25199:97;25327:2;25345:53;25390:7;25381:6;25370:9;25366:22;25345:53;;;25335:63;;25306:98;25435:2;25453:53;25498:7;25489:6;25478:9;25474:22;25453:53;;;25443:63;;25414:98;25571:2;25560:9;25556:18;25543:32;-1:-1;;;;;25587:6;25584:30;25581:2;;;25627:1;25624;25617:12;25581:2;25655:64;25711:7;25702:6;25691:9;25687:22;25655:64;;;25645:74;;;;25522:203;25756:3;25775:53;25820:7;25811:6;25800:9;25796:22;25775:53;;;25765:63;;25735:99;25893:3;25882:9;25878:19;25865:33;-1:-1;;;;;25910:6;25907:30;25904:2;;;25950:1;25947;25940:12;25904:2;25978:64;26034:7;26025:6;26014:9;26010:22;25978:64;;;25968:74;;;;25844:204;26107:3;26096:9;26092:19;26079:33;-1:-1;;;;;26124:6;26121:30;26118:2;;;26164:1;26161;26154:12;26118:2;26192:64;26248:7;26239:6;26228:9;26224:22;26192:64;;;26182:74;;;;26058:204;25130:1142;;;;;;;;;;;;;;26279:993;;;;;;;;26487:3;26475:9;26466:7;26462:23;26458:33;26455:2;;;26504:1;26501;26494:12;26455:2;26539:1;26556:53;26601:7;26581:9;26556:53;;;26546:63;;26518:97;26646:2;26664:53;26709:7;26700:6;26689:9;26685:22;26664:53;;;26654:63;;26625:98;26754:2;26772:53;26817:7;26808:6;26797:9;26793:22;26772:53;;;26762:63;;26733:98;26890:2;26879:9;26875:18;26862:32;-1:-1;;;;;26906:6;26903:30;26900:2;;;26946:1;26943;26936:12;26900:2;26974:64;27030:7;27021:6;27010:9;27006:22;26974:64;;;26964:74;;;;26841:203;27075:3;27094:53;27139:7;27130:6;27119:9;27115:22;27094:53;;;27084:63;;27054:99;27184:3;27203:53;27248:7;27239:6;27228:9;27224:22;27203:53;;;27193:63;;27163:99;26449:823;;;;;;;;;;;27280:161;;27361:40;27397:3;27389:6;27361:40;;;-1:-1;;27430:4;27421:14;;27354:87;27450:177;;27561:60;27617:3;27609:6;27561:60;;27636:245;;27781:94;27871:3;27863:6;27781:94;;27890:221;;28023:82;28101:3;28093:6;28023:82;;28119:142;28210:45;28249:5;28210:45;;;28205:3;28198:58;28192:69;;;28268:137;28367:32;28393:5;28367:32;;28412:184;28529:61;28557:32;28583:5;28557:32;;;28529:61;;29017:666;;29156:51;29201:5;29156:51;;;29220:83;29296:6;29291:3;29220:83;;;29213:90;;29324:53;29371:5;29324:53;;;29397:7;29425:1;29410:251;29435:6;29432:1;29429:13;29410:251;;;29502:6;29496:13;29523:57;29576:3;29561:13;29523:57;;;29516:64;;29597:57;29647:6;29597:57;;;29587:67;-1:-1;;29457:1;29450:9;29410:251;;;-1:-1;29674:3;;29135:548;-1:-1;;;;;29135:548;29718:888;;29873:59;29926:5;29873:59;;;29945:91;30029:6;30024:3;29945:91;;;29938:98;;30059:3;30101:4;30093:6;30089:17;30084:3;30080:27;30128:61;30183:5;30128:61;;;30209:7;30237:1;30222:345;30247:6;30244:1;30241:13;30222:345;;;30309:9;30303:4;30299:20;30294:3;30287:33;30354:6;30348:13;30376:74;30445:4;30430:13;30376:74;;;30368:82;;30467:65;30525:6;30467:65;;;30555:4;30546:14;;;;;30457:75;-1:-1;;30269:1;30262:9;30222:345;;;-1:-1;30580:4;;29852:754;-1:-1;;;;;;;29852:754;30751:1024;;30940:76;31010:5;30940:76;;;31029:108;31130:6;31125:3;31029:108;;;31022:115;;31160:3;31202:4;31194:6;31190:17;31185:3;31181:27;31229:78;31301:5;31229:78;;;31327:7;31355:1;31340:396;31365:6;31362:1;31359:13;31340:396;;;31427:9;31421:4;31417:20;31412:3;31405:33;31472:6;31466:13;31494:108;31597:4;31582:13;31494:108;;;31486:116;;31619:82;31694:6;31619:82;;;31724:4;31715:14;;;;;31609:92;-1:-1;;31387:1;31380:9;31340:396;;31908:976;;32085:70;32149:5;32085:70;;;32168:102;32263:6;32258:3;32168:102;;;32161:109;;32293:3;32335:4;32327:6;32323:17;32318:3;32314:27;32362:72;32428:5;32362:72;;;32454:7;32482:1;32467:378;32492:6;32489:1;32486:13;32467:378;;;32554:9;32548:4;32544:20;32539:3;32532:33;32599:6;32593:13;32621:96;32712:4;32697:13;32621:96;;;32613:104;;32734:76;32803:6;32734:76;;;32833:4;32824:14;;;;;32724:86;-1:-1;;32514:1;32507:9;32467:378;;32892:94;32959:21;32974:5;32959:21;;33104:113;33187:24;33205:5;33187:24;;33224:152;33325:45;33345:24;33363:5;33345:24;;;33325:45;;33383:110;33464:23;33481:5;33464:23;;33523:297;;33637:70;33700:6;33695:3;33637:70;;;33630:77;;33719:43;33755:6;33750:3;33743:5;33719:43;;;33784:29;33806:6;33784:29;;;33775:39;;;;33623:197;-1:-1;;;33623:197;33851:310;;33983:88;34064:6;34059:3;33983:88;;;33976:95;;34083:43;34119:6;34114:3;34107:5;34083:43;;;-1:-1;;34139:16;;33969:192;34169:343;;34279:38;34311:5;34279:38;;;34329:70;34392:6;34387:3;34329:70;;;34322:77;;34404:52;34449:6;34444:3;34437:4;34430:5;34426:16;34404:52;;;34477:29;34499:6;34477:29;;34519:356;;34647:38;34679:5;34647:38;;;34697:88;34778:6;34773:3;34697:88;;;34690:95;;34790:52;34835:6;34830:3;34823:4;34816:5;34812:16;34790:52;;;34854:16;;;;;34627:248;-1:-1;;34627:248;35901:150;35996:49;36039:5;35996:49;;36058:187;36171:68;36189:49;36232:5;36189:49;;;36171:68;;36974:400;;37152:85;37234:2;37229:3;37152:85;;;37270:66;37250:87;;37365:2;37356:12;;37138:236;-1:-1;;37138:236;37383:359;;37561:85;37643:2;37638:3;37561:85;;;37679:25;37659:46;;37733:2;37724:12;;37547:195;-1:-1;;37547:195;37751:354;;37929:85;38011:2;38006:3;37929:85;;;-1:-1;;;38027:41;;38096:2;38087:12;;37915:190;-1:-1;;37915:190;38114:340;;38292:84;38374:1;38369:3;38292:84;;;-1:-1;;;38389:29;;38446:1;38437:11;;38278:176;-1:-1;;38278:176;38463:417;;38641:85;38723:2;38718:3;38641:85;;;38759:34;38739:55;;-1:-1;;;38823:2;38814:12;;38807:36;38871:2;38862:12;;38627:253;-1:-1;;38627:253;38889:335;;39067:84;39149:1;39144:3;39067:84;;;-1:-1;;;39164:24;;39216:1;39207:11;;39053:171;-1:-1;;39053:171;39233:374;;39393:67;39457:2;39452:3;39393:67;;;39493:34;39473:55;;-1:-1;;;39557:2;39548:12;;39541:29;39598:2;39589:12;;39379:228;-1:-1;;39379:228;39616:323;;39776:67;39840:2;39835:3;39776:67;;;39876:25;39856:46;;39930:2;39921:12;;39762:177;-1:-1;;39762:177;39948:296;;40125:83;40206:1;40201:3;40125:83;;40253:336;;40431:84;40513:1;40508:3;40431:84;;;-1:-1;;;40528:25;;40581:1;40572:11;;40417:172;-1:-1;;40417:172;40598:362;;40776:85;40858:2;40853:3;40776:85;;;40894:28;40874:49;;40951:2;40942:12;;40762:198;-1:-1;;40762:198;40969:360;;41147:85;41229:2;41224:3;41147:85;;;41265:26;41245:47;;41320:2;41311:12;;41133:196;-1:-1;;41133:196;41338:414;;41516:85;41598:2;41593:3;41516:85;;;41634:34;41614:55;;-1:-1;;;41698:2;41689:12;;41682:33;41743:2;41734:12;;41502:250;-1:-1;;41502:250;41891:551;42094:23;;41891:551;;42030:4;42021:14;;;42123:57;42025:3;42094:23;42123:57;;;42050:136;42265:4;42258:5;42254:16;42248:23;42317:3;42311:4;42307:14;42300:4;42295:3;42291:14;42284:38;42337:67;42399:4;42385:12;42337:67;;42568:539;42759:23;;42568:539;;42695:4;42686:14;;;42788:63;42690:3;42759:23;42788:63;;43393:107;43472:22;43488:5;43472:22;;43507:144;43604:41;43622:22;43638:5;43622:22;;43658:1290;;44019:91;44106:3;44097:6;44019:91;;;44132:2;44127:3;44123:12;44116:19;;44146:75;44217:3;44208:6;44146:75;;;44243:2;44238:3;44234:12;44227:19;;44257:75;44328:3;44319:6;44257:75;;;44354:2;44349:3;44345:12;44338:19;;44368:75;44439:3;44430:6;44368:75;;;44465:2;44460:3;44456:12;44449:19;;44479:75;44550:3;44541:6;44479:75;;;44576:2;44571:3;44567:12;44560:19;;44590:75;44661:3;44652:6;44590:75;;;44687:2;44682:3;44678:12;44671:19;;44701:87;44784:3;44775:6;44701:87;;;44810:1;44805:3;44801:11;44794:18;;44830:93;44919:3;44910:6;44830:93;;;44823:100;44007:941;-1:-1;;;;;;;;;;44007:941;44955:513;;45126:75;45197:3;45188:6;45126:75;;;45223:2;45218:3;45214:12;45207:19;;45237:75;45308:3;45299:6;45237:75;;;45334:2;45329:3;45325:12;45318:19;;45348:71;45415:3;45406:6;45348:71;;;-1:-1;45441:1;45432:11;;45114:354;-1:-1;;;45114:354;45475:282;;45629:103;45728:3;45719:6;45711;45629:103;;45764:254;;45904:89;45989:3;45980:6;45904:89;;46294:961;;46690:95;46781:3;46772:6;46690:95;;;46683:102;;46803:148;46947:3;46803:148;;;46796:155;;46969:95;47060:3;47051:6;46969:95;;;46962:102;;47082:148;47226:3;47082:148;;47262:1122;;47706:95;47797:3;47788:6;47706:95;;;47699:102;;47819:148;47963:3;47819:148;;;47812:155;;47985:95;48076:3;48067:6;47985:95;;;47978:102;;48098:148;48242:3;48098:148;;;48091:155;;48264:95;48355:3;48346:6;48264:95;;48391:533;;48638:95;48729:3;48720:6;48638:95;;;48631:102;;48751:148;48895:3;48751:148;;48931:961;;49327:95;49418:3;49409:6;49327:95;;;49320:102;;49440:148;49584:3;49440:148;;49899:533;;50146:95;50237:3;50228:6;50146:95;;;50139:102;;50259:148;50403:3;50259:148;;50439:511;;50666:148;50810:3;50666:148;;;50659:155;;50825:75;50896:3;50887:6;50825:75;;;-1:-1;50922:2;50913:12;;50647:303;-1:-1;50647:303;50957:533;;51204:148;51348:3;51204:148;;;51197:155;;51370:95;51461:3;51452:6;51370:95;;51497:370;;51695:147;51838:3;51695:147;;51874:800;;52222:148;52366:3;52222:148;;;52215:155;;52388:95;52479:3;52470:6;52388:95;;;52381:102;;52501:148;52645:3;52501:148;;52681:213;52799:2;52784:18;;52813:71;52788:9;52857:6;52813:71;;52901:229;53027:2;53012:18;;53041:79;53016:9;53093:6;53041:79;;53389:340;53543:2;53528:18;;53557:79;53532:9;53609:6;53557:79;;;53647:72;53715:2;53704:9;53700:18;53691:6;53647:72;;53736:428;53910:2;53895:18;;53924:71;53899:9;53968:6;53924:71;;;54043:9;54037:4;54033:20;54028:2;54017:9;54013:18;54006:48;54068:86;54149:4;54140:6;54132;54068:86;;54171:324;54317:2;54302:18;;54331:71;54306:9;54375:6;54331:71;;;54413:72;54481:2;54470:9;54466:18;54457:6;54413:72;;54502:628;54752:2;54766:47;;;54737:18;;54827:102;54737:18;54915:6;54827:102;;;54819:110;;54977:9;54971:4;54967:20;54962:2;54951:9;54947:18;54940:48;55002:118;55115:4;55106:6;55002:118;;55137:449;55349:2;55363:47;;;55334:18;;55424:152;55334:18;55562:6;55424:152;;55593:425;55793:2;55807:47;;;55778:18;;55868:140;55778:18;55994:6;55868:140;;56025:201;56137:2;56122:18;;56151:65;56126:9;56189:6;56151:65;;56233:396;56391:2;56376:18;;56405:65;56380:9;56443:6;56405:65;;;56518:9;56512:4;56508:20;56503:2;56492:9;56488:18;56481:48;56543:76;56614:4;56605:6;56543:76;;56636:213;56754:2;56739:18;;56768:71;56743:9;56812:6;56768:71;;56856:947;57154:3;57139:19;;57169:71;57143:9;57213:6;57169:71;;;57251:66;57313:2;57302:9;57298:18;57289:6;57251:66;;;57328:72;57396:2;57385:9;57381:18;57372:6;57328:72;;;57411;57479:2;57468:9;57464:18;57455:6;57411:72;;;57532:9;57526:4;57522:20;57516:3;57505:9;57501:19;57494:49;57557:86;57638:4;57629:6;57621;57557:86;;;57549:94;;57692:9;57686:4;57682:20;57676:3;57665:9;57661:19;57654:49;57717:76;57788:4;57779:6;57717:76;;;57709:84;57125:678;-1:-1;;;;;;;;;57125:678;57810:911;58090:3;58075:19;;58105:71;58079:9;58149:6;58105:71;;;58187:66;58249:2;58238:9;58234:18;58225:6;58187:66;;;58264:72;58332:2;58321:9;58317:18;58308:6;58264:72;;;58347;58415:2;58404:9;58400:18;58391:6;58347:72;;;58468:9;58462:4;58458:20;58452:3;58441:9;58437:19;58430:49;58493:72;58560:4;58551:6;58493:72;;;58485:80;;58614:9;58608:4;58604:20;58598:3;58587:9;58583:19;58576:49;58639:72;58706:4;58697:6;58639:72;;58728:543;58932:2;58917:18;;58946:71;58921:9;58990:6;58946:71;;;59028:84;59108:2;59097:9;59093:18;59084:6;59028:84;;;59160:9;59154:4;59150:20;59145:2;59134:9;59130:18;59123:48;59185:76;59256:4;59247:6;59185:76;;59278:851;59556:3;59541:19;;59571:71;59545:9;59615:6;59571:71;;;59653:72;59721:2;59710:9;59706:18;59697:6;59653:72;;;59736;59804:2;59793:9;59789:18;59780:6;59736:72;;;59856:9;59850:4;59846:20;59841:2;59830:9;59826:18;59819:48;59881:86;59962:4;59953:6;59945;59881:86;;;59873:94;;60016:9;60010:4;60006:20;60000:3;59989:9;59985:19;59978:49;60041:78;60114:4;60105:6;60041:78;;60136:823;60400:3;60385:19;;60415:71;60389:9;60459:6;60415:71;;;60497:72;60565:2;60554:9;60550:18;60541:6;60497:72;;;60580;60648:2;60637:9;60633:18;60624:6;60580:72;;;60700:9;60694:4;60690:20;60685:2;60674:9;60670:18;60663:48;60725:72;60792:4;60783:6;60725:72;;;60717:80;;60846:9;60840:4;60836:20;60830:3;60819:9;60815:19;60808:49;60871:78;60944:4;60935:6;60871:78;;60966:539;61164:3;61149:19;;61179:71;61153:9;61223:6;61179:71;;;61261:68;61325:2;61314:9;61310:18;61301:6;61261:68;;;61340:72;61408:2;61397:9;61393:18;61384:6;61340:72;;;61423;61491:2;61480:9;61476:18;61467:6;61423:72;;61512:209;61628:2;61613:18;;61642:69;61617:9;61684:6;61642:69;;61728:492;61910:2;61924:47;;;61895:18;;61985:76;61895:18;62047:6;61985:76;;;61977:84;;62109:9;62103:4;62099:20;62094:2;62083:9;62079:18;62072:48;62134:76;62205:4;62196:6;62134:76;;62227:301;62365:2;62379:47;;;62350:18;;62440:78;62350:18;62504:6;62440:78;;62535:407;62726:2;62740:47;;;62711:18;;62801:131;62711:18;62801:131;;62949:407;63140:2;63154:47;;;63125:18;;63215:131;63125:18;63215:131;;63583:324;63729:2;63714:18;;63743:71;63718:9;63787:6;63743:71;;63914:340;64068:2;64053:18;;64082:71;64057:9;64126:6;64082:71;;;64164:80;64240:2;64229:9;64225:18;64216:6;64164:80;;64624:539;64826:2;64811:18;;64840:71;64815:9;64884:6;64840:71;;;64922:72;64990:2;64979:9;64975:18;64966:6;64922:72;;;65042:9;65036:4;65032:20;65027:2;65016:9;65012:18;65005:48;65067:86;65148:4;65139:6;65131;65067:86;;65170:651;65400:3;65385:19;;65415:71;65389:9;65459:6;65415:71;;;65497:72;65565:2;65554:9;65550:18;65541:6;65497:72;;;65580;65648:2;65637:9;65633:18;65624:6;65580:72;;;65700:9;65694:4;65690:20;65685:2;65674:9;65670:18;65663:48;65725:86;65806:4;65797:6;65789;65725:86;;65828:771;66086:3;66071:19;;66101:71;66075:9;66145:6;66101:71;;;66183:72;66251:2;66240:9;66236:18;66227:6;66183:72;;;66266;66334:2;66323:9;66319:18;66310:6;66266:72;;;66349;66417:2;66406:9;66402:18;66393:6;66349:72;;;66432:73;66500:3;66489:9;66485:19;66476:6;66432:73;;;66516;66584:3;66573:9;66569:19;66560:6;66516:73;;66606:256;66668:2;66662:9;66694:17;;;-1:-1;;;;;66754:34;;66790:22;;;66751:62;66748:2;;;66826:1;66823;66816:12;66748:2;66842;66835:22;66646:216;;-1:-1;66646:216;66869:322;;-1:-1;;;;;67038:6;67035:30;67032:2;;;67078:1;67075;67068:12;67032:2;-1:-1;67113:4;67101:17;;;67166:15;;66969:222;67525:317;;-1:-1;;;;;67656:6;67653:30;67650:2;;;67696:1;67693;67686:12;67650:2;-1:-1;67827:4;67763;67740:17;;;;-1:-1;;67736:33;67817:15;;67587:255;68831:148;68952:4;68943:14;;68900:79;69503:134;69603:12;;69574:63;71001:175;71116:19;;;71165:4;71156:14;;71109:67;72599:91;;72661:24;72679:5;72661:24;;72803:85;72869:13;72862:21;;72845:43;72895:72;72957:5;72940:27;72974:144;-1:-1;;;;;;73035:78;;73018:100;73125:134;73201:5;73207:47;73201:5;73207:47;;73266:121;-1:-1;;;;;73328:54;;73311:76;73473:81;73544:4;73533:16;;73516:38;73561:129;;73648:37;73679:5;73648:37;;73697:134;;73788:38;73820:5;73788:38;;73838:121;;73917:37;73948:5;73917:37;;74082:145;74163:6;74158:3;74153;74140:30;-1:-1;74219:1;74201:16;;74194:27;74133:94;74236:268;74301:1;74308:101;74322:6;74319:1;74316:13;74308:101;;;74389:11;;;74383:18;74370:11;;;74363:39;74344:2;74337:10;74308:101;;;74424:6;74421:1;74418:13;74415:2;;;-1:-1;;74489:1;74471:16;;74464:27;74285:219;74512:95;;74576:26;74596:5;74805:89;74869:20;74883:5;74869:20;;74982:88;;75044:21;75059:5;75044:21;;75077:97;75165:2;75145:14;-1:-1;;75141:28;;75125:49;75182:96;75257:3;75253:15;;75225:53;75286:94;75360:2;75356:14;;75328:52;75388:106;75471:2;75464:5;75461:13;75451:2;;75478:9;75501:117;75570:24;75588:5;75570:24;;;75563:5;75560:35;75550:2;;75609:1;75606;75599:12;75765:111;75831:21;75846:5;75831:21;;75883:117;75952:24;75970:5;75952:24;;76007:115;76075:23;76092:5;76075:23;;76129:109;76212:2;76205:5;76202:13;76192:2;;76229:1;76226;76219:12
Swarm Source
bzzr://9ecdeb27b72609ca0e8ec110d047738b99f3d520bc3127dbe5ffeebe65dc2594
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.