diff --git a/packages/contracts-bedrock/scripts/L2Genesis.s.sol b/packages/contracts-bedrock/scripts/L2Genesis.s.sol index e1e43efebc8c7..9eed38747e319 100644 --- a/packages/contracts-bedrock/scripts/L2Genesis.s.sol +++ b/packages/contracts-bedrock/scripts/L2Genesis.s.sol @@ -245,6 +245,8 @@ contract L2Genesis is Deployer { if (cfg.useInterop()) { setCrossL2Inbox(); // 22 setL2ToL2CrossDomainMessenger(); // 23 + setSuperchainWETH(); // 24 + setETHLiquidity(); // 25 } } @@ -475,6 +477,19 @@ contract L2Genesis is Deployer { _setImplementationCode(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); } + /// @notice This predeploy is following the saftey invariant #1. + /// This contract has no initializer. + function setETHLiquidity() internal { + _setImplementationCode(Predeploys.ETH_LIQUIDITY); + vm.deal(Predeploys.ETH_LIQUIDITY, type(uint248).max); + } + + /// @notice This predeploy is following the saftey invariant #1. + /// This contract has no initializer. + function setSuperchainWETH() internal { + _setImplementationCode(Predeploys.SUPERCHAIN_WETH); + } + /// @notice Sets all the preinstalls. /// Warning: the creator-accounts of the preinstall contracts have 0 nonce values. /// When performing a regular user-initiated contract-creation of a preinstall, diff --git a/packages/contracts-bedrock/snapshots/abi/ETHLiquidity.json b/packages/contracts-bedrock/snapshots/abi/ETHLiquidity.json new file mode 100644 index 0000000000000..5fd386c52e5ae --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/ETHLiquidity.json @@ -0,0 +1,83 @@ +[ + { + "inputs": [], + "name": "burn", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "LiquidityBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "LiquidityMinted", + "type": "event" + }, + { + "inputs": [], + "name": "NotCustomGasToken", + "type": "error" + }, + { + "inputs": [], + "name": "Unauthorized", + "type": "error" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json b/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json new file mode 100644 index 0000000000000..dcb423522b215 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/SuperchainWETH.json @@ -0,0 +1,372 @@ +[ + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "finalizeSendERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "sendERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "sendERC20To", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + }, + { + "inputs": [], + "name": "NotCustomGasToken", + "type": "error" + }, + { + "inputs": [], + "name": "Unauthorized", + "type": "error" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/ETHLiquidity.json b/packages/contracts-bedrock/snapshots/storageLayout/ETHLiquidity.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/ETHLiquidity.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/SuperchainWETH.json b/packages/contracts-bedrock/snapshots/storageLayout/SuperchainWETH.json new file mode 100644 index 0000000000000..ac5f38a75a045 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/SuperchainWETH.json @@ -0,0 +1,16 @@ +[ + { + "bytes": "32", + "label": "balanceOf", + "offset": 0, + "slot": "0", + "type": "mapping(address => uint256)" + }, + { + "bytes": "32", + "label": "allowance", + "offset": 0, + "slot": "1", + "type": "mapping(address => mapping(address => uint256))" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L2/ETHLiquidity.sol b/packages/contracts-bedrock/src/L2/ETHLiquidity.sol new file mode 100644 index 0000000000000..90a80b2e011cf --- /dev/null +++ b/packages/contracts-bedrock/src/L2/ETHLiquidity.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { WETH98 } from "src/dispute/weth/WETH98.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { L1Block } from "src/L2/L1Block.sol"; +import { SafeSend } from "src/universal/SafeSend.sol"; +import { ISemver } from "src/universal/ISemver.sol"; + +import "src/libraries/errors/CommonErrors.sol"; + +/// @title ETHLiquidity +/// @notice The ETHLiquidity contract allows other contracts to access ETH liquidity without +/// needing to modify the EVM to generate new ETH. +contract ETHLiquidity { + /// @notice Emitted when an address burns ETH liquidity. + event LiquidityBurned(address indexed caller, uint256 value); + + /// @notice Emitted when an address mints ETH liquidity. + event LiquidityMinted(address indexed caller, uint256 value); + + /// @notice Semantic version. + /// @custom:semver 1.0.0 + string public constant version = "1.0.0-beta.1"; + + /// @notice Throws if the caller is not authorized. + modifier onlyAuthorized() { + // Only the SuperchainWETH contract is authorized to call this contract for now. Other + // contracts may be allowed to call this contract in the future so we're using a generic + // name for the modifier. + if (msg.sender != Predeploys.SUPERCHAIN_WETH) revert Unauthorized(); + _; + } + + /// @notice Throws this chain is using a custom gas token. + modifier notCustomGasToken() { + if (L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); + _; + } + + /// @notice Allows an address to lock ETH liquidity into this contract. + function burn() external payable onlyAuthorized notCustomGasToken { + emit LiquidityBurned(msg.sender, msg.value); + } + + /// @notice Allows an address to unlock ETH liquidity from this contract. + /// @param _amount The amount of liquidity to unlock. + function mint(uint256 _amount) external onlyAuthorized notCustomGasToken { + new SafeSend{ value: _amount }(payable(msg.sender)); + emit LiquidityMinted(msg.sender, _amount); + } +} diff --git a/packages/contracts-bedrock/src/L2/SuperchainWETH.sol b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol new file mode 100644 index 0000000000000..8c40fd1598ddf --- /dev/null +++ b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { WETH98 } from "src/dispute/weth/WETH98.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { L1Block } from "src/L2/L1Block.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; +import { ETHLiquidity } from "src/L2/ETHLiquidity.sol"; +import { ISemver } from "src/universal/ISemver.sol"; + +import "src/libraries/errors/CommonErrors.sol"; + +/// @title SuperchainWETH +/// @notice SuperchainWETH is a version of WETH that can be freely transfered between chains within +/// the superchain. SuperchainWETH can be converted into native ETH on chains that do not +// use a custom gas token. +contract SuperchainWETH is WETH98, ISemver { + /// @notice Semantic version. + /// @custom:semver 1.0.0 + string public constant version = "1.0.0-beta.1"; + + /// @notice Throws this chain is using a custom gas token. + modifier notCustomGasToken() { + if (L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); + _; + } + + /// @inheritdoc WETH98 + function deposit() public payable override notCustomGasToken { + super.deposit(); + } + + /// @inheritdoc WETH98 + function withdraw(uint256 wad) public override notCustomGasToken { + super.withdraw(wad); + } + + /// TODO: .inheritdoc ISuperchainERC20 + function sendERC20(uint256 wad, uint256 chainId) external { + sendERC20To(msg.sender, wad, chainId); + } + + /// TODO: .inheritdoc ISuperchainERC20 + function sendERC20To(address dst, uint256 wad, uint256 chainId) public { + // Burn from user's balance. + _burn(msg.sender, wad); + + // Burn to ETHLiquidity contract. + if (!L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { + ETHLiquidity(Predeploys.ETH_LIQUIDITY).burn{ value: wad }(); + } + + // Send message to other chain. + IL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER).sendMessage({ + _destination: chainId, + _target: address(this), + _message: abi.encodeCall(this.finalizeSendERC20, (dst, wad)) + }); + } + + /// TODO: .inheritdoc ISuperchainERC20 + function finalizeSendERC20(address dst, uint256 wad) external { + // Receive message from other chain. + IL2ToL2CrossDomainMessenger messenger = IL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + if (msg.sender != address(messenger)) revert Unauthorized(); + if (messenger.crossDomainMessageSender() != address(this)) revert Unauthorized(); + + // Mint from ETHLiquidity contract. + if (!L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { + ETHLiquidity(Predeploys.ETH_LIQUIDITY).mint(wad); + } + + // Mint to user's balance. + _mint(dst, wad); + } + + /// @notice Mints WETH to an address. + /// @param guy The address to mint WETH to. + /// @param wad The amount of WETH to mint. + function _mint(address guy, uint256 wad) internal { + balanceOf[guy] += wad; + emit Transfer(address(0), guy, wad); + } + + /// @notice Burns WETH from an address. + /// @param guy The address to burn WETH from. + /// @param wad The amount of WETH to burn. + function _burn(address guy, uint256 wad) internal { + require(balanceOf[guy] >= wad); + balanceOf[guy] -= wad; + emit Transfer(guy, address(0), wad); + } +} diff --git a/packages/contracts-bedrock/src/dispute/weth/WETH98.sol b/packages/contracts-bedrock/src/dispute/weth/WETH98.sol index f95699a3bf931..2b054c7048ebf 100644 --- a/packages/contracts-bedrock/src/dispute/weth/WETH98.sol +++ b/packages/contracts-bedrock/src/dispute/weth/WETH98.sol @@ -50,7 +50,7 @@ contract WETH98 is IWETH { } /// @inheritdoc IWETH - function deposit() public payable { + function deposit() public payable virtual { balanceOf[msg.sender] += msg.value; emit Deposit(msg.sender, msg.value); } diff --git a/packages/contracts-bedrock/src/libraries/Predeploys.sol b/packages/contracts-bedrock/src/libraries/Predeploys.sol index d37dbca6af111..5b2b9fc6baee5 100644 --- a/packages/contracts-bedrock/src/libraries/Predeploys.sol +++ b/packages/contracts-bedrock/src/libraries/Predeploys.sol @@ -89,6 +89,12 @@ library Predeploys { /// @notice Address of the L2ToL2CrossDomainMessenger predeploy. address internal constant L2_TO_L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000023; + /// @notice Address of the SuperchainWETH predeploy. + address internal constant SUPERCHAIN_WETH = 0x4200000000000000000000000000000000000024; + + /// @notice Address of the ETHLiquidty predeploy. + address internal constant ETH_LIQUIDITY = 0x4200000000000000000000000000000000000025; + /// @notice Returns the name of the predeploy at the given address. function getName(address _addr) internal pure returns (string memory out_) { require(isPredeployNamespace(_addr), "Predeploys: address must be a predeploy"); @@ -115,6 +121,8 @@ library Predeploys { if (_addr == LEGACY_ERC20_ETH) return "LegacyERC20ETH"; if (_addr == CROSS_L2_INBOX) return "CrossL2Inbox"; if (_addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER) return "L2ToL2CrossDomainMessenger"; + if (_addr == SUPERCHAIN_WETH) return "SuperchainWETH"; + if (_addr == ETH_LIQUIDITY) return "ETHLiquidity"; revert("Predeploys: unnamed predeploy"); } @@ -131,7 +139,8 @@ library Predeploys { || _addr == L2_ERC721_BRIDGE || _addr == L1_BLOCK_ATTRIBUTES || _addr == L2_TO_L1_MESSAGE_PASSER || _addr == OPTIMISM_MINTABLE_ERC721_FACTORY || _addr == PROXY_ADMIN || _addr == BASE_FEE_VAULT || _addr == L1_FEE_VAULT || _addr == SCHEMA_REGISTRY || _addr == EAS || _addr == GOVERNANCE_TOKEN - || (_useInterop && _addr == CROSS_L2_INBOX) || (_useInterop && _addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER); + || (_useInterop && _addr == CROSS_L2_INBOX) || (_useInterop && _addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER) + || (_useInterop && _addr == SUPERCHAIN_WETH) || (_useInterop && _addr == ETH_LIQUIDITY); } function isPredeployNamespace(address _addr) internal pure returns (bool) { diff --git a/packages/contracts-bedrock/src/libraries/errors/CommonErrors.sol b/packages/contracts-bedrock/src/libraries/errors/CommonErrors.sol new file mode 100644 index 0000000000000..eee6cc699489e --- /dev/null +++ b/packages/contracts-bedrock/src/libraries/errors/CommonErrors.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice Error for an unauthorized CALLER. +error Unauthorized(); + +/// @notice Error for when a method is called that only works when using a custom gas token. +error OnlyCustomGasToken(); + +/// @notice Error for when a method is called that only works when NOT using a custom gas token. +error NotCustomGasToken(); + +/// @notice Error for when a transfer via call fails. +error TransferFailed(); diff --git a/packages/contracts-bedrock/src/periphery/faucet/Faucet.sol b/packages/contracts-bedrock/src/periphery/faucet/Faucet.sol index 9266d00ed0f03..cce6a83b3e131 100644 --- a/packages/contracts-bedrock/src/periphery/faucet/Faucet.sol +++ b/packages/contracts-bedrock/src/periphery/faucet/Faucet.sol @@ -1,17 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { IFaucetAuthModule } from "./authmodules/IFaucetAuthModule.sol"; -import { SafeCall } from "../../libraries/SafeCall.sol"; - -/// @title SafeSend -/// @notice Sends ETH to a recipient account without triggering any code. -contract SafeSend { - /// @param _recipient Account to send ETH to. - constructor(address payable _recipient) payable { - selfdestruct(_recipient); - } -} +import { IFaucetAuthModule } from "src/periphery/faucet/authmodules/IFaucetAuthModule.sol"; +import { SafeCall } from "src/libraries/SafeCall.sol"; +import { SafeSend } from "src/universal/SafeSend.sol"; /// @title Faucet /// @notice Faucet contract that drips ETH to users. diff --git a/packages/contracts-bedrock/src/universal/SafeSend.sol b/packages/contracts-bedrock/src/universal/SafeSend.sol new file mode 100644 index 0000000000000..4e99c6678d85f --- /dev/null +++ b/packages/contracts-bedrock/src/universal/SafeSend.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title SafeSend +/// @notice Sends ETH to a recipient account without triggering any code. +contract SafeSend { + /// @param _recipient Account to send ETH to. + constructor(address payable _recipient) payable { + selfdestruct(_recipient); + } +} diff --git a/packages/contracts-bedrock/test/L2/ETHLiquidity.t.sol b/packages/contracts-bedrock/test/L2/ETHLiquidity.t.sol new file mode 100644 index 0000000000000..cd526290f387f --- /dev/null +++ b/packages/contracts-bedrock/test/L2/ETHLiquidity.t.sol @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +// Testing utilities +import { CommonTest } from "test/setup/CommonTest.sol"; + +// Error imports +import "src/libraries/errors/CommonErrors.sol"; + +/// @title ETHLiquidity_Test +/// @notice Contract for testing the ETHLiquidity contract. +contract ETHLiquidity_Test is CommonTest { + /// @notice Emitted when an address burns ETH liquidity. + event LiquidityBurned(address indexed caller, uint256 value); + + /// @notice Emitted when an address mints ETH liquidity. + event LiquidityMinted(address indexed caller, uint256 value); + + /// @notice The starting balance of the ETHLiquidity contract. + uint256 public constant STARTING_LIQUIDITY_BALANCE = type(uint248).max; + + /// @notice Test setup. + function setUp() public virtual override { + super.enableInterop(); + super.setUp(); + } + + /// @notice Tests that the burn function can be called by an authorized caller. + function test_burn_fromAuthorizedCaller_succeeds() public { + // Arrange + uint256 amount = 1000; + vm.deal(address(superchainWeth), amount); + + // Act + vm.expectEmit(address(ethLiquidity)); + emit LiquidityBurned(address(superchainWeth), amount); + vm.prank(address(superchainWeth)); + ethLiquidity.burn{ value: amount }(); + + // Assert + assertEq(address(superchainWeth).balance, 0); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE + amount); + } + + /// @notice Tests that the burn function reverts when called by an unauthorized caller. + function test_burn_fromUnauthorizedCaller_fails() public { + // Arrange + uint256 amount = 1000; + vm.deal(address(superchainWeth), amount); + + // Act + vm.expectRevert(Unauthorized.selector); + ethLiquidity.burn{ value: amount }(); + + // Assert + assertEq(address(superchainWeth).balance, amount); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE); + } + + /// @notice Tests that the burn function reverts when called on a custom gas token chain. + function test_burn_fromCustomGasTokenChain_fails() public { + // Arrange + uint256 amount = 1000; + vm.deal(address(superchainWeth), amount); + vm.mockCall(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); + + // Act + vm.prank(address(superchainWeth)); + vm.expectRevert(NotCustomGasToken.selector); + ethLiquidity.burn{ value: amount }(); + + // Assert + assertEq(address(superchainWeth).balance, amount); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE); + } + + /// @notice Tests that the burn function can always be called by an authorized caller. + /// @param _amount Amount of ETH (in wei) to call the burn function with. + function testFuzz_burn_fromAuthorizedCaller_succeeds(uint256 _amount) public { + // Assume + vm.assume(_amount < type(uint248).max); + + // Arrange + vm.deal(address(superchainWeth), _amount); + + // Act + vm.expectEmit(address(ethLiquidity)); + emit LiquidityBurned(address(superchainWeth), _amount); + vm.prank(address(superchainWeth)); + ethLiquidity.burn{ value: _amount }(); + + // Assert + assertEq(address(superchainWeth).balance, 0); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE + _amount); + } + + /// @notice Tests that the burn function always reverts when called by an unauthorized caller. + /// @param _amount Amount of ETH (in wei) to call the burn function with. + /// @param _caller Address of the caller to call the burn function with. + function testFuzz_burn_fromUnauthorizedCaller_fails(uint256 _amount, address _caller) public { + // Assume + vm.assume(_amount < type(uint248).max); + vm.assume(_caller != address(superchainWeth)); + + // Arrange + vm.deal(_caller, _amount); + + // Act + vm.prank(_caller); + vm.expectRevert(Unauthorized.selector); + ethLiquidity.burn{ value: _amount }(); + + // Assert + assertEq(_caller.balance, _amount); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE); + } + + /// @notice Tests that the mint function can be called by an authorized caller. + function test_mint_fromAuthorizedCaller_succeeds() public { + // Arrange + uint256 amount = 1000; + + // Act + vm.expectEmit(address(ethLiquidity)); + emit LiquidityMinted(address(superchainWeth), amount); + vm.prank(address(superchainWeth)); + ethLiquidity.mint(amount); + + // Assert + assertEq(address(superchainWeth).balance, amount); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE - amount); + assertEq(superchainWeth.balanceOf(address(ethLiquidity)), 0); + } + + /// @notice Tests that the mint function reverts when called by an unauthorized caller. + function test_mint_fromUnauthorizedCaller_fails() public { + // Arrange + uint256 amount = 1000; + + // Act + vm.expectRevert(Unauthorized.selector); + ethLiquidity.mint(amount); + + // Assert + assertEq(address(superchainWeth).balance, 0); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE); + assertEq(superchainWeth.balanceOf(address(ethLiquidity)), 0); + } + + /// @notice Tests that the mint function reverts when called on a custom gas token chain. + function test_mint_fromCustomGasTokenChain_fails() public { + // Arrange + uint256 amount = 1000; + vm.mockCall(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); + + // Act + vm.prank(address(superchainWeth)); + vm.expectRevert(NotCustomGasToken.selector); + ethLiquidity.mint(amount); + + // Assert + assertEq(address(superchainWeth).balance, 0); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE); + assertEq(superchainWeth.balanceOf(address(ethLiquidity)), 0); + } + + /// @notice Tests that the mint function fails when the amount requested is greater than the + /// available balance. In practice this should never happen because the starting + /// balance is expected to be uint248 wei, the total ETH supply is far less than that + /// amount, and the only contract that pulls from here is the SuperchainWETH contract + /// which will always burn ETH somewhere before minting it somewhere else. It needs to + /// be a system-wide invariant that this condition is never triggered in the first + /// place but it is the behavior we expect if it does happen. + function test_mint_moreThanAvailableBalance_fails() public { + // Arrange + uint256 amount = STARTING_LIQUIDITY_BALANCE + 1; + + // Act + vm.expectRevert(); + ethLiquidity.mint(amount); + + // Assert + assertEq(address(superchainWeth).balance, 0); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE); + assertEq(superchainWeth.balanceOf(address(ethLiquidity)), 0); + } + + /// @notice Tests that the mint function can always be called by an authorized caller. + /// @param _amount Amount of ETH (in wei) to call the mint function with. + function testFuzz_mint_fromAuthorizedCaller_succeeds(uint256 _amount) public { + // Assume + vm.assume(_amount < type(uint248).max); + + // Arrange + // Nothing to arrange. + + // Act + vm.expectEmit(address(ethLiquidity)); + emit LiquidityMinted(address(superchainWeth), _amount); + vm.prank(address(superchainWeth)); + ethLiquidity.mint(_amount); + + // Assert + assertEq(address(superchainWeth).balance, _amount); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE - _amount); + assertEq(superchainWeth.balanceOf(address(ethLiquidity)), 0); + } + + /// @notice Tests that the mint function always reverts when called by an unauthorized caller. + /// @param _amount Amount of ETH (in wei) to call the mint function with. + /// @param _caller Address of the caller to call the mint function with. + function testFuzz_mint_fromUnauthorizedCaller_fails(uint256 _amount, address _caller) public { + // Assume + vm.assume(_amount < type(uint248).max); + vm.assume(_caller != address(superchainWeth)); + vm.assume(address(_caller).balance == 0); + + // Arrange + // Nothing to arrange. + + // Act + vm.prank(_caller); + vm.expectRevert(Unauthorized.selector); + ethLiquidity.mint(_amount); + + // Assert + assertEq(_caller.balance, 0); + assertEq(address(ethLiquidity).balance, STARTING_LIQUIDITY_BALANCE); + assertEq(superchainWeth.balanceOf(address(ethLiquidity)), 0); + } +} diff --git a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol new file mode 100644 index 0000000000000..87b70963ebd75 --- /dev/null +++ b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol @@ -0,0 +1,435 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +// Testing utilities +import { CommonTest } from "test/setup/CommonTest.sol"; + +// Contract imports +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; +import { ETHLiquidity } from "src/L2/ETHLiquidity.sol"; + +// Error imports +import "src/libraries/errors/CommonErrors.sol"; + +/// @title SuperchainWETH_Test +/// @notice Contract for testing the SuperchainWETH contract. +contract SuperchainWETH_Test is CommonTest { + /// @notice Emitted when a transfer is made. + event Transfer(address indexed src, address indexed dst, uint256 wad); + + /// @notice Emitted when a deposit is made. + event Deposit(address indexed dst, uint256 wad); + + /// @notice Emitted when a withdrawal is made. + event Withdrawal(address indexed src, uint256 wad); + + /// @notice Test setup. + function setUp() public virtual override { + super.enableInterop(); + super.setUp(); + } + + /// @notice Tests that the deposit function can be called on a non-custom gas token chain. + function test_deposit_fromNonCustomGasTokenChain_succeeds() public { + // Arrange + uint256 amount = 1000; + vm.deal(alice, amount); + + // Act + vm.expectEmit(address(superchainWeth)); + emit Deposit(alice, amount); + vm.prank(alice); + superchainWeth.deposit{ value: amount }(); + + // Assert + assertEq(alice.balance, 0); + assertEq(superchainWeth.balanceOf(alice), amount); + } + + /// @notice Tests that the deposit function reverts when called on a custom gas token chain. + function test_deposit_fromCustomGasTokenChain_fails() public { + // Arrange + uint256 amount = 1000; + vm.deal(address(alice), amount); + vm.mockCall(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); + + // Act + vm.prank(alice); + vm.expectRevert(NotCustomGasToken.selector); + superchainWeth.deposit{ value: amount }(); + + // Assert + assertEq(alice.balance, amount); + assertEq(superchainWeth.balanceOf(alice), 0); + } + + /// @notice Tests that the withdraw function can be called on a non-custom gas token chain. + function test_withdraw_fromNonCustomGasTokenChain_succeeds() public { + // Arrange + uint256 amount = 1000; + vm.deal(alice, amount); + vm.prank(alice); + superchainWeth.deposit{ value: amount }(); + + // Act + vm.expectEmit(address(superchainWeth)); + emit Withdrawal(alice, amount); + vm.prank(alice); + superchainWeth.withdraw(amount); + + // Assert + assertEq(alice.balance, amount); + assertEq(superchainWeth.balanceOf(alice), 0); + } + + /// @notice Tests that the withdraw function reverts when called on a custom gas token chain. + function test_withdraw_fromCustomGasTokenChain_fails() public { + // Arrange + uint256 amount = 1000; + vm.deal(alice, amount); + vm.prank(alice); + superchainWeth.deposit{ value: amount }(); + vm.mockCall(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); + + // Act + vm.prank(alice); + vm.expectRevert(NotCustomGasToken.selector); + superchainWeth.withdraw(amount); + + // Assert + assertEq(alice.balance, 0); + assertEq(superchainWeth.balanceOf(alice), amount); + } + + /// @notice Tests that the sendERC20 function can be called with a sufficient balance on a + /// non-custom gas token chain. Also tests that the proper calls are made, ETH is + /// burned, and the proper events are emitted. + function test_sendERC20_sufficientBalance_succeeds() public { + // Arrange + uint256 amount = 1000; + uint256 chainId = 1; + vm.deal(alice, amount); + vm.prank(alice); + superchainWeth.deposit{ value: amount }(); + + // Act + vm.expectEmit(address(superchainWeth)); + emit Transfer(alice, address(0), amount); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.burn, ()), 1); + vm.expectCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall( + IL2ToL2CrossDomainMessenger.sendMessage, + ( + chainId, + address(superchainWeth), + abi.encodeWithSelector(superchainWeth.finalizeSendERC20.selector, alice, amount) + ) + ), + 1 + ); + vm.prank(alice); + superchainWeth.sendERC20(amount, chainId); + + // Assert + assertEq(alice.balance, 0); + assertEq(superchainWeth.balanceOf(alice), 0); + } + + /// @notice Tests that the sendERC20 function can be called with a sufficient balance on a + /// custom gas token chain. Also tests that the proper calls are made and the proper + /// events are emitted but ETH is not burned via the ETHLiquidity contract. + function test_sendERC20_sufficientFromCustomGasTokenChain_succeeds() public { + // Arrange + uint256 amount = 1000; + uint256 chainId = 1; + vm.deal(alice, amount); + vm.prank(alice); + superchainWeth.deposit{ value: amount }(); + vm.mockCall(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); + + // Act + vm.expectEmit(address(superchainWeth)); + emit Transfer(alice, address(0), amount); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.burn, ()), 0); + vm.expectCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall( + IL2ToL2CrossDomainMessenger.sendMessage, + ( + chainId, + address(superchainWeth), + abi.encodeWithSelector(superchainWeth.finalizeSendERC20.selector, alice, amount) + ) + ), + 1 + ); + vm.prank(alice); + superchainWeth.sendERC20(amount, chainId); + + // Assert + assertEq(alice.balance, 0); + assertEq(superchainWeth.balanceOf(alice), 0); + } + + /// @notice Tests that the sendERC20 function reverts when called with insufficient balance. + function test_sendERC20_insufficientBalance_fails() public { + // Arrange + uint256 amount = 1000; + uint256 chainId = 1; + vm.deal(alice, amount); + vm.prank(alice); + superchainWeth.deposit{ value: amount }(); + + // Act + vm.expectRevert(); + superchainWeth.sendERC20(amount + 1, chainId); + + // Assert + assertEq(alice.balance, 0); + assertEq(superchainWeth.balanceOf(alice), amount); + } + + /// @notice Tests that the sendERC20 function always succeeds when called with a sufficient + /// balance no matter the sender, amount, or chain ID. + /// @param _amount The amount of WETH to send. + /// @param _caller The address of the caller. + /// @param _chainId The chain ID to send the WETH to. + function testFuzz_sendERC20_sufficientBalance_succeeds(uint256 _amount, address _caller, uint256 _chainId) public { + // Arrange + vm.deal(_caller, _amount); + vm.prank(_caller); + superchainWeth.deposit{ value: _amount }(); + + // Act + vm.expectEmit(address(superchainWeth)); + emit Transfer(_caller, address(0), _amount); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.burn, ()), 1); + vm.expectCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall( + IL2ToL2CrossDomainMessenger.sendMessage, + ( + _chainId, + address(superchainWeth), + abi.encodeCall(superchainWeth.finalizeSendERC20, (_caller, _amount)) + ) + ), + 1 + ); + vm.prank(_caller); + superchainWeth.sendERC20(_amount, _chainId); + + // Assert + assertEq(_caller.balance, 0); + assertEq(superchainWeth.balanceOf(_caller), 0); + } + + /// @notice Tests that the sendERC20To function can be called with a sufficient balance on a + /// non-custom gas token chain. Also tests that the proper calls are made, ETH is + /// burned, and the proper events are emitted. + function test_sendERC20To_sufficientBalance_succeeds() public { + // Arrange + uint256 amount = 1000; + uint256 chainId = 1; + vm.deal(alice, amount); + vm.prank(alice); + superchainWeth.deposit{ value: amount }(); + + // Act + vm.expectEmit(address(superchainWeth)); + emit Transfer(alice, address(0), amount); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.burn, ()), 1); + vm.expectCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall( + IL2ToL2CrossDomainMessenger.sendMessage, + (chainId, address(superchainWeth), abi.encodeCall(superchainWeth.finalizeSendERC20, (bob, amount))) + ), + 1 + ); + vm.prank(alice); + superchainWeth.sendERC20To(bob, amount, chainId); + + // Assert + assertEq(alice.balance, 0); + assertEq(superchainWeth.balanceOf(alice), 0); + } + + /// @notice Tests that the sendERC20To function can be called with a sufficient balance on a + /// custom gas token chain. Also tests that the proper calls are made and the proper + /// events are emitted but ETH is not burned via the ETHLiquidity contract. + function test_sendERC20To_sufficientFromCustomGasTokenChain_succeeds() public { + // Arrange + uint256 amount = 1000; + uint256 chainId = 1; + vm.deal(alice, amount); + vm.prank(alice); + superchainWeth.deposit{ value: amount }(); + vm.mockCall(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); + + // Act + vm.expectEmit(address(superchainWeth)); + emit Transfer(alice, address(0), amount); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.burn, ()), 0); + vm.expectCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall( + IL2ToL2CrossDomainMessenger.sendMessage, + (chainId, address(superchainWeth), abi.encodeCall(superchainWeth.finalizeSendERC20, (bob, amount))) + ), + 1 + ); + vm.prank(alice); + superchainWeth.sendERC20To(bob, amount, chainId); + + // Assert + assertEq(alice.balance, 0); + assertEq(superchainWeth.balanceOf(alice), 0); + } + + /// @notice Tests that the sendERC20To function reverts when called with insufficient balance. + function test_sendERC20To_insufficientBalance_fails() public { + // Arrange + uint256 amount = 1000; + uint256 chainId = 1; + vm.deal(alice, amount); + vm.prank(alice); + superchainWeth.deposit{ value: amount }(); + + // Act + vm.expectRevert(); + superchainWeth.sendERC20To(bob, amount + 1, chainId); + + // Assert + assertEq(alice.balance, 0); + assertEq(superchainWeth.balanceOf(alice), amount); + } + + /// @notice Tests that the sendERC20To function always succeeds when called with a sufficient + /// balance no matter the sender, amount, recipient, or chain ID. + /// @param _amount The amount of WETH to send. + /// @param _caller The address of the caller. + /// @param _recipient The address of the recipient. + /// @param _chainId The chain ID to send the WETH to. + function testFuzz_sendERC20To_sufficientBalance_succeeds( + uint256 _amount, + address _caller, + address _recipient, + uint256 _chainId + ) + public + { + // Arrange + vm.deal(_caller, _amount); + vm.prank(_caller); + superchainWeth.deposit{ value: _amount }(); + + // Act + vm.expectEmit(address(superchainWeth)); + emit Transfer(_caller, address(0), _amount); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.burn, ()), 1); + vm.expectCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall( + IL2ToL2CrossDomainMessenger.sendMessage, + ( + _chainId, + address(superchainWeth), + abi.encodeCall(superchainWeth.finalizeSendERC20, (_recipient, _amount)) + ) + ), + 1 + ); + vm.prank(_caller); + superchainWeth.sendERC20To(_recipient, _amount, _chainId); + + // Assert + assertEq(_caller.balance, 0); + assertEq(superchainWeth.balanceOf(_caller), 0); + } + + /// @notice Tests that the finalizeSendERC20 function can be called from the + /// L2ToL2CrossDomainMessenger as long as the crossDomainMessageSender is the + function test_finalizeSendERC20_fromMessenger_succeeds() public { + // Arrange + uint256 amount = 1000; + vm.mockCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall(IL2ToL2CrossDomainMessenger.crossDomainMessageSender, ()), + abi.encode(address(superchainWeth)) + ); + + // Act + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.mint, (amount)), 1); + vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + superchainWeth.finalizeSendERC20(bob, amount); + + // Assert + assertEq(address(superchainWeth).balance, amount); + assertEq(superchainWeth.balanceOf(bob), amount); + } + + /// @notice Tests that the finalizeSendERC20 function can be called from the + /// L2ToL2CrossDomainMessenger as long as the crossDomainMessageSender is the + /// SuperchainWETH contract, even when the chain is a custom gas token chain. Shows + /// that ETH is not minted in this case but the SuperchainWETH balance is updated. + function test_finalizeSendERC20_fromMessengerCustomGasTokenChain_succeeds() public { + // Arrange + uint256 amount = 1000; + vm.mockCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall(IL2ToL2CrossDomainMessenger.crossDomainMessageSender, ()), + abi.encode(address(superchainWeth)) + ); + vm.mockCall(address(l1Block), abi.encodeCall(l1Block.isCustomGasToken, ()), abi.encode(true)); + + // Act + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.mint, (amount)), 0); + vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + superchainWeth.finalizeSendERC20(bob, amount); + + // Assert + assertEq(address(superchainWeth).balance, 0); + assertEq(superchainWeth.balanceOf(bob), amount); + } + + /// @notice Tests that the finalizeSendERC20 function reverts when not called from the + /// L2ToL2CrossDomainMessenger. + function test_finalizeSendERC20_notFromMessenger_fails() public { + // Arrange + uint256 amount = 1000; + + // Act + vm.expectRevert(Unauthorized.selector); + vm.prank(alice); + superchainWeth.finalizeSendERC20(bob, amount); + + // Assert + assertEq(address(superchainWeth).balance, 0); + assertEq(superchainWeth.balanceOf(bob), 0); + } + + /// @notice Tests that the finalizeSendERC20 function reverts when called from the + /// L2ToL2CrossDomainMessenger but the crossDomainMessageSender is not the + /// SuperchainWETH contract. + function test_finalizeSendERC20_fromMessengerNotFromSuperchainWETH_fails() public { + // Arrange + uint256 amount = 1000; + vm.mockCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall(IL2ToL2CrossDomainMessenger.crossDomainMessageSender, ()), + abi.encode(address(alice)) + ); + + // Act + vm.expectRevert(Unauthorized.selector); + vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + superchainWeth.finalizeSendERC20(bob, amount); + + // Assert + assertEq(address(superchainWeth).balance, 0); + assertEq(superchainWeth.balanceOf(bob), 0); + } +} diff --git a/packages/contracts-bedrock/test/L2Genesis.t.sol b/packages/contracts-bedrock/test/L2Genesis.t.sol index 80d6656ac1d4b..2bb969546a52f 100644 --- a/packages/contracts-bedrock/test/L2Genesis.t.sol +++ b/packages/contracts-bedrock/test/L2Genesis.t.sol @@ -150,8 +150,8 @@ contract L2GenesisTest is Test { // 2 predeploys do not have proxies assertEq(getCodeCount(_path, "Proxy.sol:Proxy"), Predeploys.PREDEPLOY_COUNT - 2); - // 19 proxies have the implementation set if useInterop is true and 17 if useInterop is false - assertEq(getPredeployCountWithSlotSet(_path, Constants.PROXY_IMPLEMENTATION_ADDRESS), _useInterop ? 19 : 17); + // 21 proxies have the implementation set if useInterop is true and 17 if useInterop is false + assertEq(getPredeployCountWithSlotSet(_path, Constants.PROXY_IMPLEMENTATION_ADDRESS), _useInterop ? 21 : 17); // All proxies except 2 have the proxy 1967 admin slot set to the proxy admin assertEq( diff --git a/packages/contracts-bedrock/test/invariants/ETHLiquidity.t.sol b/packages/contracts-bedrock/test/invariants/ETHLiquidity.t.sol new file mode 100644 index 0000000000000..a7da876adb3be --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/ETHLiquidity.t.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { StdUtils } from "forge-std/Test.sol"; +import { Vm } from "forge-std/Vm.sol"; + +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { ETHLiquidity } from "src/L2/ETHLiquidity.sol"; + +import { CommonTest } from "test/setup/CommonTest.sol"; + +/// @title ETHLiquidity_User +/// @notice Actor contract that interacts with the ETHLiquidity contract. Always pretends to be the +/// SuperchainWETH contract since it's the only contract that can use ETHLiquidity. +contract ETHLiquidity_User is StdUtils { + /// @notice Flag to indicate if the test has failed. + bool public failed = false; + + /// @notice The Vm contract. + Vm internal vm; + + /// @notice The ETHLiquidity contract. + ETHLiquidity internal liquidity; + + /// @param _vm The Vm contract. + /// @param _liquidity The ETHLiquidity contract. + /// @param _balance The initial balance of the contract. + constructor(Vm _vm, ETHLiquidity _liquidity, uint256 _balance) { + vm = _vm; + liquidity = _liquidity; + vm.deal(Predeploys.SUPERCHAIN_WETH, _balance); + } + + /// @notice Mint ETH liquidity. + /// @param _amount The amount of ETH to mint. + function mint(uint256 _amount) public { + vm.prank(Predeploys.SUPERCHAIN_WETH); + liquidity.mint(_amount); + } + + /// @notice Burn ETH liquidity. + /// @param _amount The amount of ETH to burn. + function burn(uint256 _amount) public { + vm.prank(Predeploys.SUPERCHAIN_WETH); + liquidity.burn{ value: _amount }(); + } +} + +/// @title ETHLiquidity_MintBurn_Invariant +/// @notice Invariant that checks that minting/burning ETH liquidity does not cause the actor's +/// balance to magically increase beyond the starting balance. +contract ETHLiquidity_MintBurn_Invariant is CommonTest { + /// @notice Starting balance of the contract. + uint256 internal constant STARTING_BALANCE = type(uint248).max; + + /// @notice The ETHLiquidity_User actor. + ETHLiquidity_User internal actor; + + /// @notice Test setup. + function setUp() public override { + super.enableInterop(); + super.setUp(); + + // Create a new ETHLiquidity_User actor. + actor = new ETHLiquidity_User(vm, ethLiquidity, STARTING_BALANCE); + + // Set the target contract. + targetContract(address(actor)); + + // Set the target selectors. + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = actor.mint.selector; + selectors[1] = actor.burn.selector; + FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors }); + targetSelector(selector); + } + + /// @notice Invariant that checks that repeatedly minting/burning does not cause the actor's + /// balance to increase beyond the starting balance. + /// @custom:invariant Calls to mint/burn repeatedly should never cause the actor's balance to + /// increase beyond the starting balance. + function invariant_mintburn_maintainsBalance() public view { + // Assert that the actor's balance has not somehow increased. + assertLe(address(actor).balance, type(uint248).max); + } +} diff --git a/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol b/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol new file mode 100644 index 0000000000000..7b8601d38e466 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { StdUtils } from "forge-std/Test.sol"; +import { Vm } from "forge-std/Vm.sol"; + +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { SuperchainWETH } from "src/L2/SuperchainWETH.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; + +import { CommonTest } from "test/setup/CommonTest.sol"; + +/// @title SuperchainWETH_User +/// @notice Actor contract that interacts with the SuperchainWETH contract. +contract SuperchainWETH_User is StdUtils { + /// @notice Cross domain message data. + struct MessageData { + bytes32 id; + uint256 amount; + } + + /// @notice Flag to indicate if the test has failed. + bool public failed = false; + + /// @notice The Vm contract. + Vm internal vm; + + /// @notice The SuperchainWETH contract. + SuperchainWETH internal weth; + + /// @notice Mapping of sent messages. + mapping(bytes32 => bool) internal sent; + + /// @notice Array of unrelayed messages. + MessageData[] internal unrelayed; + + /// @param _vm The Vm contract. + /// @param _weth The SuperchainWETH contract. + /// @param _balance The initial balance of the contract. + constructor(Vm _vm, SuperchainWETH _weth, uint256 _balance) { + vm = _vm; + weth = _weth; + vm.deal(address(this), _balance); + } + + /// @notice Allow the contract to receive ETH. + receive() external payable { } + + /// @notice Deposit ETH into the contract. + /// @param _amount The amount of ETH to deposit. + function deposit(uint256 _amount) public { + // Bound deposit amount to our ETH balance. + _amount = bound(_amount, 0, address(this).balance); + + // Deposit the amount. + try weth.deposit{ value: _amount }() { + // Success. + } catch { + failed = true; + } + } + + /// @notice Withdraw ETH from the contract. + /// @param _amount The amount of ETH to withdraw. + function withdraw(uint256 _amount) public { + // Bound withdraw amount to our WETH balance. + _amount = bound(_amount, 0, weth.balanceOf(address(this))); + + // Withdraw the amount. + try weth.withdraw(_amount) { + // Success. + } catch { + failed = true; + } + } + + /// @notice Send ERC20 tokens to another chain. + /// @param _amount The amount of ERC20 tokens to send. + /// @param _chainId The chain ID to send the tokens to. + /// @param _messageId The message ID. + function sendERC20(uint256 _amount, uint256 _chainId, bytes32 _messageId) public { + // Make sure we aren't reusing a message ID. + if (sent[_messageId]) { + return; + } + + // Bound send amount to our WETH balance. + _amount = bound(_amount, 0, weth.balanceOf(address(this))); + + // Send the amount. + try weth.sendERC20(_amount, _chainId) { + // Success. + } catch { + failed = true; + } + + // Mark message as sent. + sent[_messageId] = true; + unrelayed.push(MessageData({ id: _messageId, amount: _amount })); + } + + /// @notice Relay a message from another chain. + function relayMessage() public { + // Make sure there are unrelayed messages. + if (unrelayed.length == 0) { + return; + } + + // Grab the latest unrelayed message. + MessageData memory message = unrelayed[unrelayed.length - 1]; + + // Simulate the cross-domain message. + // Make sure the cross-domain message sender is set to this contract. + vm.mockCall( + Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, + abi.encodeCall(IL2ToL2CrossDomainMessenger.crossDomainMessageSender, ()), + abi.encode(address(weth)) + ); + + // Prank the finalizeSendERC20 function. + // Balance will just go back to our own account. + vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + try weth.finalizeSendERC20(address(this), message.amount) { + // Success. + } catch { + failed = true; + } + + // Remove the message from the unrelayed list. + unrelayed.pop(); + } +} + +/// @title SuperchainWETH_SendSucceeds_Invariant +/// @notice Invariant test that checks that sending WETH always succeeds if the actor has a +/// sufficient balance to do so and that the actor's balance does not increase out of +/// nowhere. +contract SuperchainWETH_SendSucceeds_Invariant is CommonTest { + /// @notice Starting balance of the contract. + uint256 internal constant STARTING_BALANCE = type(uint248).max; + + /// @notice The SuperchainWETH_User actor. + SuperchainWETH_User internal actor; + + /// @notice Test setup. + function setUp() public override { + super.enableInterop(); + super.setUp(); + + // Create a new SuperchainWETH_User actor. + actor = new SuperchainWETH_User(vm, superchainWeth, STARTING_BALANCE); + + // Set the target contract. + targetContract(address(actor)); + + // Set the target selectors. + bytes4[] memory selectors = new bytes4[](4); + selectors[0] = actor.deposit.selector; + selectors[1] = actor.withdraw.selector; + selectors[2] = actor.sendERC20.selector; + selectors[3] = actor.relayMessage.selector; + FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors }); + targetSelector(selector); + } + + /// @notice Invariant that checks that sending WETH always succeeds. + /// @custom:invariant Calls to sendERC20 should always succeed as long as the actor has less + /// than uint248 wei which is much greater than the total ETH supply. Actor's + /// balance should also not increase out of nowhere. + function invariant_sendERC20_succeeds() public view { + // Assert that the actor has not failed to send WETH. + assertEq(actor.failed(), false); + + // Assert that the actor's balance has not somehow increased. + assertLe(address(actor).balance, STARTING_BALANCE); + } +} diff --git a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol index d8fbd28656a23..1de3787ccd349 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol +++ b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol @@ -13,26 +13,26 @@ contract DeploymentSummary is DeploymentSummaryCode { Vm private constant vm = Vm(VM_ADDRESS); address internal constant addressManagerAddress = 0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3; - address internal constant l1CrossDomainMessengerAddress = 0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b; + address internal constant l1CrossDomainMessengerAddress = 0x8e4E41289Bd71F4954b901297f0971bc2fDf6EFf; address internal constant l1CrossDomainMessengerProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; - address internal constant l1ERC721BridgeAddress = 0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804; + address internal constant l1ERC721BridgeAddress = 0x29Bd22555ae6b759E7E90A60467151FA2004fdA1; address internal constant l1ERC721BridgeProxyAddress = 0xDeF3bca8c80064589E6787477FFa7Dd616B5574F; - address internal constant l1StandardBridgeAddress = 0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b; + address internal constant l1StandardBridgeAddress = 0xA1A13a7477023c4986b9843D886D95cb82912F67; address internal constant l1StandardBridgeProxyAddress = 0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6; - address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60; + address internal constant l2OutputOracleAddress = 0xC978d1DbFc5AF83A464F1935B24125B67E357B37; address internal constant l2OutputOracleProxyAddress = 0x8B71b41D4dBEb2b6821d44692d3fACAAf77480Bb; - address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131; + address internal constant optimismPortalAddress = 0xb73936BFb438221eFCeeb028c0f4111bF50e8355; address internal constant optimismPortalProxyAddress = 0x978e3286EB805934215a88694d80b09aDed68D90; - address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F; + address internal constant protocolVersionsAddress = 0xF468a5acffa1DaB98A25FEB22BC3c88ab032e745; address internal constant protocolVersionsProxyAddress = 0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6; address internal constant proxyAdminAddress = 0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76; address internal constant safeProxyFactoryAddress = 0x34A1D3fff3958843C43aD80F30b94c510645C316; address internal constant safeSingletonAddress = 0x90193C961A926261B756D1E5bb255e67ff9498A1; - address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A; + address internal constant superchainConfigAddress = 0xf30A59E7073770D778f9b671606B879931a363E6; address internal constant superchainConfigProxyAddress = 0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809; - address internal constant systemConfigAddress = 0x67866A5052E5302aaD08e9f352331fd8622eB6DC; + address internal constant systemConfigAddress = 0xd0407445e7b421206245548905579a7bc540374D; address internal constant systemConfigProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4; - address internal constant systemOwnerSafeAddress = 0x7EA964E5D864b95f6D7d2BD04dA897F6e31084b3; + address internal constant systemOwnerSafeAddress = 0xB37e4E94E5A68B7233482C022663Fd8597dD3455; function recreateDeployment() public { bytes32 slot; @@ -73,7 +73,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3"; vm.store(proxyAdminAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; - value = hex"0000000000000000000000007ea964e5d864b95f6d7d2bd04da897f6e31084b3"; + value = hex"000000000000000000000000b37e4e94e5a68b7233482c022663fd8597dd3455"; vm.store(proxyAdminAddress, slot, value); vm.etch(superchainConfigProxyAddress, superchainConfigProxyCode); slot = hex"b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"; @@ -93,7 +93,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000001"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a"; + value = hex"000000000000000000000000f30a59e7073770d778f9b671606b879931a363e6"; vm.store(superchainConfigProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -131,7 +131,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000002"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f"; + value = hex"000000000000000000000000f468a5acffa1dab98a25feb22bc3c88ab032e745"; vm.store(protocolVersionsProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -284,7 +284,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000003"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc"; + value = hex"000000000000000000000000d0407445e7b421206245548905579a7bc540374d"; vm.store(systemConfigProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -347,7 +347,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000005"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b"; + value = hex"000000000000000000000000a1a13a7477023c4986b9843d886d95cb82912f67"; vm.store(l1StandardBridgeProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -374,7 +374,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000006"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804"; + value = hex"00000000000000000000000029bd22555ae6b759e7e90a60467151fa2004fda1"; vm.store(l1ERC721BridgeProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -410,7 +410,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000009"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e"; - value = hex"000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b"; + value = hex"0000000000000000000000008e4e41289bd71f4954b901297f0971bc2fdf6eff"; vm.store(addressManagerAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000010000000000000000000000000000000000000000"; @@ -440,7 +440,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"000000000000000000000000000000000000000000000000000000000000000a"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131"; + value = hex"000000000000000000000000b73936bfb438221efceeb028c0f4111bf50e8355"; vm.store(optimismPortalProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; diff --git a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol index d0e8be6b23150..4c1c2de73ec78 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol +++ b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol @@ -13,32 +13,32 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { Vm private constant vm = Vm(VM_ADDRESS); address internal constant addressManagerAddress = 0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3; - address internal constant anchorStateRegistryAddress = 0xF74482139D1564B826994875cF6632eB5b134b25; + address internal constant anchorStateRegistryAddress = 0x0D5b6d7D2Ccb1Dcf94216c5ab5444989A6C6B078; address internal constant anchorStateRegistryProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4; - address internal constant delayedWETHAddress = 0x49BBFf1629824A1e7993Ab5c17AFa45D24AB28c9; + address internal constant delayedWETHAddress = 0xa41ea060dcBc8A1ED75febd54BD18c9F17C54F0b; address internal constant delayedWETHProxyAddress = 0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6; - address internal constant disputeGameFactoryAddress = 0x20B168142354Cee65a32f6D8cf3033E592299765; + address internal constant disputeGameFactoryAddress = 0x08f7FeEC3720E46B19799455Ae3d57593cAC0a9d; address internal constant disputeGameFactoryProxyAddress = 0x8B71b41D4dBEb2b6821d44692d3fACAAf77480Bb; - address internal constant l1CrossDomainMessengerAddress = 0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b; + address internal constant l1CrossDomainMessengerAddress = 0x8e4E41289Bd71F4954b901297f0971bc2fDf6EFf; address internal constant l1CrossDomainMessengerProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB; - address internal constant l1ERC721BridgeAddress = 0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804; + address internal constant l1ERC721BridgeAddress = 0x29Bd22555ae6b759E7E90A60467151FA2004fdA1; address internal constant l1ERC721BridgeProxyAddress = 0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865; - address internal constant l1StandardBridgeAddress = 0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b; + address internal constant l1StandardBridgeAddress = 0xA1A13a7477023c4986b9843D886D95cb82912F67; address internal constant l1StandardBridgeProxyAddress = 0xDeF3bca8c80064589E6787477FFa7Dd616B5574F; - address internal constant mipsAddress = 0xcdAdd729ca2319E8955240bDb61A6A6A956A7664; - address internal constant optimismPortal2Address = 0xfcbb237388CaF5b08175C9927a37aB6450acd535; + address internal constant mipsAddress = 0x90Ed5f6E29A5cD042d7Bd6b1964B6156675Fa1Db; + address internal constant optimismPortal2Address = 0xfC84F146f0B4795109Dd03A52BF86E7FcDEDe517; address internal constant optimismPortalProxyAddress = 0x978e3286EB805934215a88694d80b09aDed68D90; - address internal constant preimageOracleAddress = 0x3bd7E801E51d48c5d94Ea68e8B801DFFC275De75; - address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F; + address internal constant preimageOracleAddress = 0xe4Fb287531f0b54DabA227c87C473787fF5a6b5D; + address internal constant protocolVersionsAddress = 0xF468a5acffa1DaB98A25FEB22BC3c88ab032e745; address internal constant protocolVersionsProxyAddress = 0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6; address internal constant proxyAdminAddress = 0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76; address internal constant safeProxyFactoryAddress = 0x34A1D3fff3958843C43aD80F30b94c510645C316; address internal constant safeSingletonAddress = 0x90193C961A926261B756D1E5bb255e67ff9498A1; - address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A; + address internal constant superchainConfigAddress = 0xf30A59E7073770D778f9b671606B879931a363E6; address internal constant superchainConfigProxyAddress = 0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809; - address internal constant systemConfigAddress = 0x67866A5052E5302aaD08e9f352331fd8622eB6DC; + address internal constant systemConfigAddress = 0xd0407445e7b421206245548905579a7bc540374D; address internal constant systemConfigProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; - address internal constant systemOwnerSafeAddress = 0x7EA964E5D864b95f6D7d2BD04dA897F6e31084b3; + address internal constant systemOwnerSafeAddress = 0xB37e4E94E5A68B7233482C022663Fd8597dD3455; address internal constant acc27Address = 0x12e721c390F5728200a26BBEf206A5F4F7E991f3; address internal constant acc28Address = 0x2abb7CBB720020ee3C9ecf3915D14B6d1886A577; @@ -81,7 +81,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3"; vm.store(proxyAdminAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; - value = hex"0000000000000000000000007ea964e5d864b95f6d7d2bd04da897f6e31084b3"; + value = hex"000000000000000000000000b37e4e94e5a68b7233482c022663fd8597dd3455"; vm.store(proxyAdminAddress, slot, value); vm.etch(superchainConfigProxyAddress, superchainConfigProxyCode); slot = hex"b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"; @@ -101,7 +101,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000001"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a"; + value = hex"000000000000000000000000f30a59e7073770d778f9b671606b879931a363e6"; vm.store(superchainConfigProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -139,7 +139,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000002"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f"; + value = hex"000000000000000000000000f468a5acffa1dab98a25feb22bc3c88ab032e745"; vm.store(protocolVersionsProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -376,7 +376,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000003"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc"; + value = hex"000000000000000000000000d0407445e7b421206245548905579a7bc540374d"; vm.store(systemConfigProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -442,7 +442,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000005"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b"; + value = hex"000000000000000000000000a1a13a7477023c4986b9843d886d95cb82912f67"; vm.store(l1StandardBridgeProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -469,7 +469,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000006"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804"; + value = hex"00000000000000000000000029bd22555ae6b759e7e90a60467151fa2004fda1"; vm.store(l1ERC721BridgeProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -505,7 +505,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000009"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e"; - value = hex"000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b"; + value = hex"0000000000000000000000008e4e41289bd71f4954b901297f0971bc2fdf6eff"; vm.store(addressManagerAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000010000000000000000000000000000000000000000"; @@ -535,7 +535,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000000000000000000000000000000000000000000a"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765"; + value = hex"00000000000000000000000008f7feec3720e46b19799455ae3d57593cac0a9d"; vm.store(disputeGameFactoryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -556,7 +556,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000000000000000000000000000000000000000000b"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000049bbff1629824a1e7993ab5c17afa45d24ab28c9"; + value = hex"000000000000000000000000a41ea060dcbc8a1ed75febd54bd18c9f17c54f0b"; vm.store(delayedWETHProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -580,7 +580,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000000000000000000000000000000000000000000c"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000f74482139d1564b826994875cf6632eb5b134b25"; + value = hex"0000000000000000000000000d5b6d7d2ccb1dcf94216c5ab5444989a6c6b078"; vm.store(anchorStateRegistryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -610,7 +610,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000000000000000000000000000000000000000000d"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000fcbb237388caf5b08175c9927a37ab6450acd535"; + value = hex"000000000000000000000000fc84f146f0b4795109dd03a52bf86e7fcdede517"; vm.store(optimismPortalProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; diff --git a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol index 880728ad1d2f8..aad1d11dd8af0 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol +++ b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol @@ -55,11 +55,11 @@ contract DeploymentSummaryFaultProofsCode { bytes internal constant preimageOracleCode = hex"6080604052600436106101cd5760003560e01c80638dc4be11116100f7578063dd24f9bf11610095578063ec5efcbc11610064578063ec5efcbc1461065f578063f3f480d91461067f578063faf37bc7146106b2578063fef2b4ed146106c557600080fd5b8063dd24f9bf1461059f578063ddcd58de146105d2578063e03110e11461060a578063e15926111461063f57600080fd5b8063b2e67ba8116100d1578063b2e67ba814610512578063b4801e611461054a578063d18534b51461056a578063da35c6641461058a57600080fd5b80638dc4be11146104835780639d53a648146104a35780639d7e8769146104f257600080fd5b806354fd4d501161016f5780637917de1d1161013e5780637917de1d146103bf5780637ac54767146103df5780638542cf50146103ff578063882856ef1461044a57600080fd5b806354fd4d50146102dd57806361238bde146103335780636551927b1461036b5780637051472e146103a357600080fd5b80632055b36b116101ab5780632055b36b146102735780633909af5c146102885780634d52b4c9146102a857806352f0f3ad146102bd57600080fd5b8063013cf08b146101d25780630359a5631461022357806304697c7814610251575b600080fd5b3480156101de57600080fd5b506101f26101ed366004612d2f565b6106f2565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561022f57600080fd5b5061024361023e366004612d71565b610737565b60405190815260200161021a565b34801561025d57600080fd5b5061027161026c366004612de4565b61086f565b005b34801561027f57600080fd5b50610243601081565b34801561029457600080fd5b506102716102a3366004613008565b6109a5565b3480156102b457600080fd5b50610243610bfc565b3480156102c957600080fd5b506102436102d83660046130f4565b610c17565b3480156102e957600080fd5b506103266040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161021a919061315b565b34801561033f57600080fd5b5061024361034e3660046131ac565b600160209081526000928352604080842090915290825290205481565b34801561037757600080fd5b50610243610386366004612d71565b601560209081526000928352604080842090915290825290205481565b3480156103af57600080fd5b506102436703782dace9d9000081565b3480156103cb57600080fd5b506102716103da3660046131ce565b610cec565b3480156103eb57600080fd5b506102436103fa366004612d2f565b6111ef565b34801561040b57600080fd5b5061043a61041a3660046131ac565b600260209081526000928352604080842090915290825290205460ff1681565b604051901515815260200161021a565b34801561045657600080fd5b5061046a61046536600461326a565b611206565b60405167ffffffffffffffff909116815260200161021a565b34801561048f57600080fd5b5061027161049e36600461329d565b611260565b3480156104af57600080fd5b506102436104be366004612d71565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104fe57600080fd5b5061027161050d3660046132e9565b61135b565b34801561051e57600080fd5b5061024361052d366004612d71565b601760209081526000928352604080842090915290825290205481565b34801561055657600080fd5b5061024361056536600461326a565b611512565b34801561057657600080fd5b50610271610585366004613008565b611544565b34801561059657600080fd5b50601354610243565b3480156105ab57600080fd5b507f0000000000000000000000000000000000000000000000000000000000002710610243565b3480156105de57600080fd5b506102436105ed366004612d71565b601660209081526000928352604080842090915290825290205481565b34801561061657600080fd5b5061062a6106253660046131ac565b611906565b6040805192835260208301919091520161021a565b34801561064b57600080fd5b5061027161065a36600461329d565b6119f7565b34801561066b57600080fd5b5061027161067a366004613375565b611aff565b34801561068b57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000078610243565b6102716106c036600461340e565b611c85565b3480156106d157600080fd5b506102436106e0366004612d2f565b60006020819052908152604090205481565b6013818154811061070257600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061077a9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610867578160011660010361080d5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107da576107da61344a565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925061084e565b82600382601081106108215761082161344a565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c908061085f816134a8565b915050610785565b505092915050565b600080600080608060146030823785878260140137601480870182207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06000000000000000000000000000000000000000000000000000000000000001794506000908190889084018b5afa94503d60010191506008820189106108fc5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e88017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208c8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209b83529a81528a82209290925593845283905296909120959095555050505050565b60006109b18a8a610737565b90506109d486868360208b01356109cf6109ca8d6134e0565b611ef0565b611f30565b80156109f257506109f283838360208801356109cf6109ca8a6134e0565b610a28576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b866040013588604051602001610a3e91906135af565b6040516020818303038152906040528051906020012014610a8b576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836020013587602001356001610aa191906135ed565b14610ad8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2088610ae68680613605565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f9192505050565b610b29886120ec565b836040013588604051602001610b3f91906135af565b6040516020818303038152906040528051906020012003610b8c576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610bf08a8a33612894565b50505050505050505050565b6001610c0a6010600261378c565b610c149190613798565b81565b6000610c23868661294d565b9050610c308360086135ed565b821180610c3d5750602083115b15610c74576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610d0557610cfe86866129fa565b9050610d3f565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610d6c57505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610ded8260601c63ffffffff1690565b63ffffffff169050333214610e2e576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e3e8260801c63ffffffff1690565b63ffffffff16600003610e7d576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e878260c01c90565b67ffffffffffffffff1615610ec8576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610f01576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f0e89898d8886612a73565b83516020850160888204881415608883061715610f33576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610fe3578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610fd8576001821615610fb85782818b0152610fd8565b8981015160009081526020938452604090209260019290921c9101610f9b565b505050608801610f40565b50505050600160106002610ff7919061378c565b6110019190613798565b81111561103a576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110af61104d8360401c63ffffffff1690565b61105d9063ffffffff168a6135ed565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b9150841561113c5777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791506110e98260801c63ffffffff1690565b63ffffffff166110ff8360401c63ffffffff1690565b63ffffffff161461113c576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061116290846010612ca5565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106111ff57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061122e57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061127e5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa9050806112ab57600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806113835763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa925082611405576309bde3396000526004601cfd5b6028861061141b5763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061153a57600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156115b7576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000786115e28260c01c90565b6115f69067ffffffffffffffff1642613798565b1161162d576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116398b8b610737565b905061165287878360208c01356109cf6109ca8e6134e0565b8015611670575061167084848360208901356109cf6109ca8b6134e0565b6116a6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016116bc91906135af565b6040516020818303038152906040528051906020012014611709576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161171f91906135ed565b141580611751575060016117398360601c63ffffffff1690565b61174391906137af565b63ffffffff16856020013514155b15611788576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61179689610ae68780613605565b61179f896120ec565b60006117aa8a612bc6565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f020000000000000000000000000000000000000000000000000000000000000017905060006118018460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d815260200190815260200160002054600160008481526020019081526020016000206000838152602001908152602001600020819055506118d38460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118f78d8d81612894565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff1661198f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546119ab8160086135ed565b6119b68560206135ed565b106119d457836119c78260086135ed565b6119d19190613798565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018610611a155763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000611b0b8686610737565b9050611b2483838360208801356109cf6109ca8a6134e0565b611b5a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611b96576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b9e612ce3565b611bac81610ae68780613605565b611bb5816120ec565b846040013581604051602001611bcb91906135af565b6040516020818303038152906040528051906020012003611c18576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611c7c878733612894565b50505050505050565b6703782dace9d90000341015611cc7576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d00576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d0b8160086137d4565b63ffffffff168263ffffffff1610611d4f576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611daf576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b949094179094558251808401845282815280850186815260138054600181018255908452915160029092027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffff000000000000000000000000000000000000000090941693909317909255517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015590815260168352818120938152929091529020349055565b6000816000015182602001518360400151604051602001611f13939291906137fc565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611f84578060051b880135600186831c1660018114611f695760008481526020839052604090209350611f7a565b600082815260208590526040902093505b5050600101611f36565b5090931495945050505050565b6088815114611f9f57600080fd5b6020810160208301612020565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b171717905061201a81612005868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b61202c60008383611fac565b61203860018383611fac565b61204460028383611fac565b61205060038383611fac565b61205c60048383611fac565b61206860058383611fac565b61207460068383611fac565b61208060078383611fac565b61208c60088383611fac565b61209860098383611fac565b6120a4600a8383611fac565b6120b0600b8383611fac565b6120bc600c8383611fac565b6120c8600d8383611fac565b6120d4600e8383611fac565b6120e0600f8383611fac565b61201a60108383611fac565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612774565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c61229f8660011b67ffffffffffffffff1690565b18188584603f1c6122ba8660011b67ffffffffffffffff1690565b18188584603f1c6122d58660011b67ffffffffffffffff1690565b181895508483603f1c6122f28560011b67ffffffffffffffff1690565b181894508387603f1c61230f8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611c7c565b61270e600082612687565b612719600582612687565b612724600a82612687565b61272f600f82612687565b61273a601482612687565b50565b612746816121e2565b61274f81612703565b600383901b820151815160c09190911c9061201a90821867ffffffffffffffff168352565b6127806000828461273d565b61278c6001828461273d565b6127986002828461273d565b6127a46003828461273d565b6127b06004828461273d565b6127bc6005828461273d565b6127c86006828461273d565b6127d46007828461273d565b6127e06008828461273d565b6127ec6009828461273d565b6127f8600a828461273d565b612804600b828461273d565b612810600c828461273d565b61281c600d828461273d565b612828600e828461273d565b612834600f828461273d565b6128406010828461273d565b61284c6011828461273d565b6128586012828461273d565b6128646013828461273d565b6128706014828461273d565b61287c6015828461273d565b6128886016828461273d565b61201a6017828461273d565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d806000811461290d576040519150601f19603f3d011682016040523d82523d6000602084013e612912565b606091505b5050905080612680576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316176129f3818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612a435760888290038501848101848103803687375060806001820353506001845160001a1784538652612a5a565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612a858260a01c63ffffffff1690565b67ffffffffffffffff1690506000612aa38360801c63ffffffff1690565b63ffffffff1690506000612abd8460401c63ffffffff1690565b63ffffffff169050600883108015612ad3575080155b15612b075760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612bbc565b60088310158015612b25575080612b1f600885613798565b93508310155b8015612b395750612b3687826135ed565b83105b15612bbc576000612b4a8285613798565b905087612b588260206135ed565b10158015612b64575085155b15612b9b576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612c49565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612bf78360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612c248360101b67ffffffffffffffff1690565b1617905060008160201c612c428360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612c6190612bcd565b612bcd565b6040820151612c6f90612bcd565b60401b17612c87612c5c60018460059190911b015190565b825160809190911b90612c9990612bcd565b60c01b17179392505050565b8260108101928215612cd3579160200282015b82811115612cd3578251825591602001919060010190612cb8565b50612cdf929150612cfb565b5090565b6040518060200160405280612cf6612d10565b905290565b5b80821115612cdf5760008155600101612cfc565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612d4157600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612d6c57600080fd5b919050565b60008060408385031215612d8457600080fd5b612d8d83612d48565b946020939093013593505050565b60008083601f840112612dad57600080fd5b50813567ffffffffffffffff811115612dc557600080fd5b602083019150836020828501011115612ddd57600080fd5b9250929050565b60008060008060608587031215612dfa57600080fd5b84359350612e0a60208601612d48565b9250604085013567ffffffffffffffff811115612e2657600080fd5b612e3287828801612d9b565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612e9157612e91612e3e565b60405290565b6040516060810167ffffffffffffffff81118282101715612e9157612e91612e3e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f0157612f01612e3e565b604052919050565b6000610320808385031215612f1d57600080fd5b604051602080820167ffffffffffffffff8382108183111715612f4257612f42612e3e565b8160405283955087601f880112612f5857600080fd5b612f60612e6d565b9487019491508188861115612f7457600080fd5b875b86811015612f9c5780358381168114612f8f5760008081fd5b8452928401928401612f76565b50909352509295945050505050565b600060608284031215612fbd57600080fd5b50919050565b60008083601f840112612fd557600080fd5b50813567ffffffffffffffff811115612fed57600080fd5b6020830191508360208260051b8501011115612ddd57600080fd5b60008060008060008060008060006103e08a8c03121561302757600080fd5b6130308a612d48565b985060208a013597506130468b60408c01612f09565b96506103608a013567ffffffffffffffff8082111561306457600080fd5b6130708d838e01612fab565b97506103808c013591508082111561308757600080fd5b6130938d838e01612fc3565b90975095506103a08c01359150808211156130ad57600080fd5b6130b98d838e01612fab565b94506103c08c01359150808211156130d057600080fd5b506130dd8c828d01612fc3565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561310c57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b8381101561314a578181015183820152602001613132565b8381111561201a5750506000910152565b602081526000825180602084015261317a81604085016020870161312f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080604083850312156131bf57600080fd5b50508035926020909101359150565b600080600080600080600060a0888a0312156131e957600080fd5b8735965060208801359550604088013567ffffffffffffffff8082111561320f57600080fd5b61321b8b838c01612d9b565b909750955060608a013591508082111561323457600080fd5b506132418a828b01612fc3565b9094509250506080880135801515811461325a57600080fd5b8091505092959891949750929550565b60008060006060848603121561327f57600080fd5b61328884612d48565b95602085013595506040909401359392505050565b6000806000604084860312156132b257600080fd5b83359250602084013567ffffffffffffffff8111156132d057600080fd5b6132dc86828701612d9b565b9497909650939450505050565b600080600080600080600060a0888a03121561330457600080fd5b8735965060208801359550604088013567ffffffffffffffff8082111561332a57600080fd5b6133368b838c01612d9b565b909750955060608a013591508082111561334f57600080fd5b5061335c8a828b01612d9b565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561338d57600080fd5b61339686612d48565b945060208601359350604086013567ffffffffffffffff808211156133ba57600080fd5b6133c689838a01612fab565b945060608801359150808211156133dc57600080fd5b506133e988828901612fc3565b969995985093965092949392505050565b803563ffffffff81168114612d6c57600080fd5b60008060006060848603121561342357600080fd5b83359250613433602085016133fa565b9150613441604085016133fa565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036134d9576134d9613479565b5060010190565b6000606082360312156134f257600080fd5b6134fa612e97565b823567ffffffffffffffff8082111561351257600080fd5b9084019036601f83011261352557600080fd5b813560208282111561353957613539612e3e565b613569817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612eba565b9250818352368183860101111561357f57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156135e457825167ffffffffffffffff168252602092830192909101906001016135bb565b50505092915050565b6000821982111561360057613600613479565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261363a57600080fd5b83018035915067ffffffffffffffff82111561365557600080fd5b602001915036819003821315612ddd57600080fd5b600181815b808511156136c357817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156136a9576136a9613479565b808516156136b657918102915b93841c939080029061366f565b509250929050565b6000826136da57506001613786565b816136e757506000613786565b81600181146136fd576002811461370757613723565b6001915050613786565b60ff84111561371857613718613479565b50506001821b613786565b5060208310610133831016604e8410600b8410161715613746575081810a613786565b613750838361366a565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561378257613782613479565b0290505b92915050565b60006129f383836136cb565b6000828210156137aa576137aa613479565b500390565b600063ffffffff838116908316818110156137cc576137cc613479565b039392505050565b600063ffffffff8083168185168083038211156137f3576137f3613479565b01949350505050565b6000845161380e81846020890161312f565b9190910192835250602082015260400191905056fea164736f6c634300080f000a"; bytes internal constant mipsCode = - hex"608060405234801561001057600080fd5b506004361061004c5760003560e01c8063155633fe1461005157806354fd4d50146100765780637dc0d1d0146100bf578063e14ced3214610103575b600080fd5b61005c634000000081565b60405163ffffffff90911681526020015b60405180910390f35b6100b26040518060400160405280600c81526020017f312e312e302d626574612e35000000000000000000000000000000000000000081525081565b60405161006d9190612084565b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003bd7e801e51d48c5d94ea68e8b801dffc275de7516815260200161006d565b610116610111366004612139565b610124565b60405190815260200161006d565b600061012e611ffa565b6080811461013b57600080fd5b6040516106001461014b57600080fd5b6084871461015857600080fd5b6101a4851461016657600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b602081101561021157823560e01c82526004909201916020909101906001016101ed565b5050508061012001511561022f57610227610387565b91505061037e565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061026485606001518660000151866104a3565b9250925092508163ffffffff16600014801561028657508063ffffffff16600c145b156102a057610294876104ca565b9550505050505061037e565b600061031a866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b610160870151875191925061033791839190610524888888610821565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c0870152610375610387565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b602081101561042657601c8601518452602090950194600490930192600101610402565b506000835283830384a0600094508060018114610446576003955061046e565b82801561045e5760018114610467576002965061046c565b6000965061046c565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008060006104b3858786610c07565b96603f601a89901c81169750881695509350505050565b60006104d4611ffa565b506101e051604081015160808083015160a084015160c090940151919390916000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00663ffffffff8716016105475761053285858960e00151610cbb565b63ffffffff1660e08a01529092509050610730565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105805763400000009150610730565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016105b65760019150610730565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161060a57600161012088015260ff85166101008801526105fd610387565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff87160161068e5760208701516040880151610677918791879187918e7f0000000000000000000000003bd7e801e51d48c5d94ea68e8b801dffc275de756105248f51610cfd565b8a5263ffffffff1660408a01529092509050610730565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016106f357602087015160408801516106d9918791879187916105248d51610f33565b63ffffffff1660408b015260208a01529092509050610730565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff8716016107305761072a8585611029565b90925090505b60006107aa886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a01529050610813610387565b9a9950505050505050505050565b84600263ffffffff8416148061083d57508263ffffffff166003145b1561088f5760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061088989898663ffffffff1660021461087d57601f610880565b60005b60ff16846110de565b50610bfc565b600080601f601087901c8116908a90601589901c16602081106108b4576108b46121ad565b602002015192508063ffffffff871615806108d557508663ffffffff16601c145b15610907578a8263ffffffff16602081106108f2576108f26121ad565b6020020151925050601f600b88901c166109be565b60208763ffffffff161015610969578663ffffffff16600c148061093157508663ffffffff16600d145b8061094257508663ffffffff16600e145b15610953578761ffff1692506109be565b6109628861ffff1660106111b6565b92506109be565b60288763ffffffff1610158061098557508663ffffffff166022145b8061099657508663ffffffff166026145b156109be578a8263ffffffff16602081106109b3576109b36121ad565b602002015192508190505b60048763ffffffff16101580156109db575060088763ffffffff16105b806109ec57508663ffffffff166001145b15610a08576109ff8c8c898b8689611229565b50505050610bfc565b63ffffffff6000602089831610610a6d57610a288a61ffff1660106111b6565b9095019463fffffffc8616610a3e8d828e610c07565b915060288a63ffffffff1610158015610a5e57508963ffffffff16603014155b15610a6b57809250600093505b505b6000610a7d8b8b8b8a8a87611417565b63ffffffff1690508963ffffffff166000148015610aa2575060088963ffffffff1610155b8015610ab45750601c8963ffffffff16105b15610b7c578863ffffffff1660081480610ad457508863ffffffff166009145b15610b0757610afb8f8f8b63ffffffff16600814610af25786610af5565b60005b8a6110de565b50505050505050610bfc565b8863ffffffff16600a03610b2957610afb8f8f868a63ffffffff8b1615611b36565b8863ffffffff16600b03610b4c57610afb8f8f868a63ffffffff8b161515611b36565b60108963ffffffff1610158015610b695750601c8963ffffffff16105b15610b7c57610afb8f8f8b8a8a89611c06565b8963ffffffff166038148015610b97575063ffffffff851615155b15610bc75760018e8663ffffffff1660208110610bb657610bb66121ad565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610be657610be3838d83611ebf565b97505b610bf48f8f86846001611b36565b505050505050505b979650505050505050565b6000610c1282611f61565b6003831615610c2057600080fd5b6020820191358360051c8160005b601b811015610c865760208601953583821c6001168015610c565760018114610c6b57610c7c565b60008481526020839052604090209350610c7c565b600082815260208590526040902093505b5050600101610c2e565b50868114610c9c57630badf00d60005260206000fd5b5050601f93909316601c0360031b9290921c63ffffffff169392505050565b6000808284610fff811615610cd557610fff811661100003015b8663ffffffff16600003610cef5784935090810190610cf3565b8693505b5093509350939050565b600080868363ffffffff8d1615610f23577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8e1601610ee2576000610d4e868e63fffffffc1689610c07565b90508a60001a600103610db7576040805160008d8152336020528b83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0100000000000000000000000000000000000000000000000000000000000000179a505b6040517fe03110e1000000000000000000000000000000000000000000000000000000008152600481018c905263ffffffff8b166024820152600090819073ffffffffffffffffffffffffffffffffffffffff8b169063e03110e1906044016040805180830381865afa158015610e32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5691906121dc565b9150915060038f168060040382811015610e6e578092505b50818f1015610e7b578e91505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b03915081198116905083811986161794505050610ed18f63fffffffc168a85611ebf565b909650938601939250610f23915050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff8e1601610f17578a9350610f23565b63ffffffff9350600992505b9950995099509995505050505050565b600080858563ffffffff8b1660011480610f53575063ffffffff8b166002145b80610f64575063ffffffff8b166004145b15610f715788935061101b565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c160161100f576000610fb1868c63fffffffc1689610c07565b90508860038c166004038b811015610fc757809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b1791506000905061101b565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036110cc5763ffffffff84161580611053575063ffffffff84166005145b80611064575063ffffffff84166003145b1561107257600091506110d7565b63ffffffff84166001148061108d575063ffffffff84166002145b8061109e575063ffffffff84166006145b806110af575063ffffffff84166004145b156110bd57600191506110d7565b5063ffffffff905060096110d7565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff1614611163576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff90811687528381169091528316156111af5780600801848463ffffffff166020811061119e5761119e6121ad565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182611213576000611215565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff16146112ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161115a565b8463ffffffff16600414806112c657508463ffffffff166005145b1561133d576000868463ffffffff16602081106112e5576112e56121ad565b602002015190508063ffffffff168363ffffffff1614801561130d57508563ffffffff166004145b8061133557508063ffffffff168363ffffffff161415801561133557508563ffffffff166005145b9150506113ba565b8463ffffffff1660060361135a5760008260030b131590506113ba565b8463ffffffff166007036113765760008260030b1390506113ba565b8463ffffffff166001036113ba57601f601085901c16600081900361139f5760008360030b1291505b8063ffffffff166001036113b85760008360030b121591505b505b8651602088015163ffffffff16885281156113fb5760026113e08661ffff1660106111b6565b63ffffffff90811690911b820160040116602089015261140d565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff86161580611444575060088663ffffffff16101580156114445750600f8663ffffffff16105b1561184d578560088114611487576009811461149057600a811461149957600b81146114a257600c81146114ab57600d81146114b457600e81146114bd576114c2565b602095506114c2565b602195506114c2565b602a95506114c2565b602b95506114c2565b602495506114c2565b602595506114c2565b602695505b508463ffffffff166000036114e7575063ffffffff8216601f600688901c161b611b2c565b8463ffffffff1660020361150b575063ffffffff8216601f600688901c161c611b2c565b8463ffffffff1660030361153f57601f600688901c1661153763ffffffff8516821c60208390036111b6565b915050611b2c565b8463ffffffff1660040361155f575063ffffffff8216601f84161b611b2c565b8463ffffffff1660060361157f575063ffffffff8216601f84161c611b2c565b8463ffffffff166007036115b0576115a98463ffffffff168463ffffffff16901c856020036111b6565b9050611b2c565b8463ffffffff166008036115c5575082611b2c565b8463ffffffff166009036115da575082611b2c565b8463ffffffff16600a036115ef575082611b2c565b8463ffffffff16600b03611604575082611b2c565b8463ffffffff16600c03611619575082611b2c565b8463ffffffff16600f0361162e575082611b2c565b8463ffffffff16601003611643575082611b2c565b8463ffffffff16601103611658575082611b2c565b8463ffffffff1660120361166d575082611b2c565b8463ffffffff16601303611682575082611b2c565b8463ffffffff16601803611697575082611b2c565b8463ffffffff166019036116ac575082611b2c565b8463ffffffff16601a036116c1575082611b2c565b8463ffffffff16601b036116d6575082611b2c565b8463ffffffff166020036116ed5750828201611b2c565b8463ffffffff166021036117045750828201611b2c565b8463ffffffff1660220361171b5750818303611b2c565b8463ffffffff166023036117325750818303611b2c565b8463ffffffff166024036117495750828216611b2c565b8463ffffffff166025036117605750828217611b2c565b8463ffffffff166026036117775750828218611b2c565b8463ffffffff1660270361178f575082821719611b2c565b8463ffffffff16602a036117be578260030b8460030b126117b15760006117b4565b60015b60ff169050611b2c565b8463ffffffff16602b036117e6578263ffffffff168463ffffffff16106117b15760006117b4565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161115a565b6117e6565b8563ffffffff16601c036118c6578463ffffffff166002036118725750828202611b2c565b8463ffffffff166020148061188d57508463ffffffff166021145b15611848578463ffffffff166020036118a4579219925b60005b63800000008516156115a9576401fffffffe600195861b1694016118a7565b8563ffffffff16600f036118e7575065ffffffff0000601083901b16611b2c565b8563ffffffff1660200361191b576115a98460031660080260180363ffffffff168363ffffffff16901c60ff1660086111b6565b8563ffffffff16602103611950576115a98460021660080260100363ffffffff168363ffffffff16901c61ffff1660106111b6565b8563ffffffff1660220361197e575063ffffffff60086003851602811681811b198416918316901b17611b2c565b8563ffffffff16602303611993575080611b2c565b8563ffffffff166024036119c4578360031660080260180363ffffffff168263ffffffff16901c60ff169050611b2c565b8563ffffffff166025036119f6578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611b2c565b8563ffffffff16602603611a27575063ffffffff60086003851602601803811681811c198416918316901c17611b2c565b8563ffffffff16602803611a5c575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611b2c565b8563ffffffff16602903611a92575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611b2c565b8563ffffffff16602a03611ac0575063ffffffff60086003851602811681811c198316918416901c17611b2c565b8563ffffffff16602b03611ad5575081611b2c565b8563ffffffff16602e03611b06575063ffffffff60086003851602601803811681811b198316918416901b17611b2c565b8563ffffffff16603003611b1b575080611b2c565b8563ffffffff166038036117e65750815b9695505050505050565b60208363ffffffff1610611ba6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161115a565b63ffffffff831615801590611bb85750805b15611be75781848463ffffffff1660208110611bd657611bd66121ad565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611c2157506060860151611e67565b8463ffffffff16601103611c405763ffffffff84166060880152611e67565b8463ffffffff16601203611c5957506040860151611e67565b8463ffffffff16601303611c785763ffffffff84166040880152611e67565b8463ffffffff16601803611cac5763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611e67565b8463ffffffff16601903611cdd5763ffffffff84811681851602602081901c821660608a0152166040880152611e67565b8463ffffffff16601a03611da0578260030b600003611d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f00000000000000000000604482015260640161115a565b8260030b8460030b81611d6d57611d6d612200565b0763ffffffff166060880152600383810b9085900b81611d8f57611d8f612200565b0563ffffffff166040880152611e67565b8463ffffffff16601b03611e67578263ffffffff16600003611e1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f00000000000000000000604482015260640161115a565b8263ffffffff168463ffffffff1681611e3957611e39612200565b0663ffffffff908116606089015283811690851681611e5a57611e5a612200565b0463ffffffff1660408801525b63ffffffff821615611e9d5780868363ffffffff1660208110611e8c57611e8c6121ad565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000611eca83611f61565b6003841615611ed857600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611f565760208601953582821c6001168015611f265760018114611f3b57611f4c565b60008581526020839052604090209450611f4c565b600082815260208690526040902094505b5050600101611efe565b509095945050505050565b366103808201811015611ff6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161115a565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101612060612065565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b818110156120b157858101830151858201604001528201612095565b818111156120c3576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261210957600080fd5b50813567ffffffffffffffff81111561212157600080fd5b6020830191508360208285010111156110d757600080fd5b60008060008060006060868803121561215157600080fd5b853567ffffffffffffffff8082111561216957600080fd5b61217589838a016120f7565b9097509550602088013591508082111561218e57600080fd5b5061219b888289016120f7565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080604083850312156121ef57600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b506004361061004c5760003560e01c8063155633fe1461005157806354fd4d50146100765780637dc0d1d0146100bf578063e14ced3214610103575b600080fd5b61005c634000000081565b60405163ffffffff90911681526020015b60405180910390f35b6100b26040518060400160405280600c81526020017f312e312e302d626574612e35000000000000000000000000000000000000000081525081565b60405161006d9190612084565b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000e4fb287531f0b54daba227c87c473787ff5a6b5d16815260200161006d565b610116610111366004612139565b610124565b60405190815260200161006d565b600061012e611ffa565b6080811461013b57600080fd5b6040516106001461014b57600080fd5b6084871461015857600080fd5b6101a4851461016657600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b602081101561021157823560e01c82526004909201916020909101906001016101ed565b5050508061012001511561022f57610227610387565b91505061037e565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061026485606001518660000151866104a3565b9250925092508163ffffffff16600014801561028657508063ffffffff16600c145b156102a057610294876104ca565b9550505050505061037e565b600061031a866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b610160870151875191925061033791839190610524888888610821565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c0870152610375610387565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b602081101561042657601c8601518452602090950194600490930192600101610402565b506000835283830384a0600094508060018114610446576003955061046e565b82801561045e5760018114610467576002965061046c565b6000965061046c565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008060006104b3858786610c07565b96603f601a89901c81169750881695509350505050565b60006104d4611ffa565b506101e051604081015160808083015160a084015160c090940151919390916000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00663ffffffff8716016105475761053285858960e00151610cbb565b63ffffffff1660e08a01529092509050610730565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105805763400000009150610730565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016105b65760019150610730565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161060a57600161012088015260ff85166101008801526105fd610387565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff87160161068e5760208701516040880151610677918791879187918e7f000000000000000000000000e4fb287531f0b54daba227c87c473787ff5a6b5d6105248f51610cfd565b8a5263ffffffff1660408a01529092509050610730565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016106f357602087015160408801516106d9918791879187916105248d51610f33565b63ffffffff1660408b015260208a01529092509050610730565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff8716016107305761072a8585611029565b90925090505b60006107aa886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a01529050610813610387565b9a9950505050505050505050565b84600263ffffffff8416148061083d57508263ffffffff166003145b1561088f5760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061088989898663ffffffff1660021461087d57601f610880565b60005b60ff16846110de565b50610bfc565b600080601f601087901c8116908a90601589901c16602081106108b4576108b46121ad565b602002015192508063ffffffff871615806108d557508663ffffffff16601c145b15610907578a8263ffffffff16602081106108f2576108f26121ad565b6020020151925050601f600b88901c166109be565b60208763ffffffff161015610969578663ffffffff16600c148061093157508663ffffffff16600d145b8061094257508663ffffffff16600e145b15610953578761ffff1692506109be565b6109628861ffff1660106111b6565b92506109be565b60288763ffffffff1610158061098557508663ffffffff166022145b8061099657508663ffffffff166026145b156109be578a8263ffffffff16602081106109b3576109b36121ad565b602002015192508190505b60048763ffffffff16101580156109db575060088763ffffffff16105b806109ec57508663ffffffff166001145b15610a08576109ff8c8c898b8689611229565b50505050610bfc565b63ffffffff6000602089831610610a6d57610a288a61ffff1660106111b6565b9095019463fffffffc8616610a3e8d828e610c07565b915060288a63ffffffff1610158015610a5e57508963ffffffff16603014155b15610a6b57809250600093505b505b6000610a7d8b8b8b8a8a87611417565b63ffffffff1690508963ffffffff166000148015610aa2575060088963ffffffff1610155b8015610ab45750601c8963ffffffff16105b15610b7c578863ffffffff1660081480610ad457508863ffffffff166009145b15610b0757610afb8f8f8b63ffffffff16600814610af25786610af5565b60005b8a6110de565b50505050505050610bfc565b8863ffffffff16600a03610b2957610afb8f8f868a63ffffffff8b1615611b36565b8863ffffffff16600b03610b4c57610afb8f8f868a63ffffffff8b161515611b36565b60108963ffffffff1610158015610b695750601c8963ffffffff16105b15610b7c57610afb8f8f8b8a8a89611c06565b8963ffffffff166038148015610b97575063ffffffff851615155b15610bc75760018e8663ffffffff1660208110610bb657610bb66121ad565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610be657610be3838d83611ebf565b97505b610bf48f8f86846001611b36565b505050505050505b979650505050505050565b6000610c1282611f61565b6003831615610c2057600080fd5b6020820191358360051c8160005b601b811015610c865760208601953583821c6001168015610c565760018114610c6b57610c7c565b60008481526020839052604090209350610c7c565b600082815260208590526040902093505b5050600101610c2e565b50868114610c9c57630badf00d60005260206000fd5b5050601f93909316601c0360031b9290921c63ffffffff169392505050565b6000808284610fff811615610cd557610fff811661100003015b8663ffffffff16600003610cef5784935090810190610cf3565b8693505b5093509350939050565b600080868363ffffffff8d1615610f23577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8e1601610ee2576000610d4e868e63fffffffc1689610c07565b90508a60001a600103610db7576040805160008d8152336020528b83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0100000000000000000000000000000000000000000000000000000000000000179a505b6040517fe03110e1000000000000000000000000000000000000000000000000000000008152600481018c905263ffffffff8b166024820152600090819073ffffffffffffffffffffffffffffffffffffffff8b169063e03110e1906044016040805180830381865afa158015610e32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5691906121dc565b9150915060038f168060040382811015610e6e578092505b50818f1015610e7b578e91505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b03915081198116905083811986161794505050610ed18f63fffffffc168a85611ebf565b909650938601939250610f23915050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff8e1601610f17578a9350610f23565b63ffffffff9350600992505b9950995099509995505050505050565b600080858563ffffffff8b1660011480610f53575063ffffffff8b166002145b80610f64575063ffffffff8b166004145b15610f715788935061101b565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c160161100f576000610fb1868c63fffffffc1689610c07565b90508860038c166004038b811015610fc757809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b1791506000905061101b565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036110cc5763ffffffff84161580611053575063ffffffff84166005145b80611064575063ffffffff84166003145b1561107257600091506110d7565b63ffffffff84166001148061108d575063ffffffff84166002145b8061109e575063ffffffff84166006145b806110af575063ffffffff84166004145b156110bd57600191506110d7565b5063ffffffff905060096110d7565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff1614611163576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff90811687528381169091528316156111af5780600801848463ffffffff166020811061119e5761119e6121ad565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182611213576000611215565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff16146112ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161115a565b8463ffffffff16600414806112c657508463ffffffff166005145b1561133d576000868463ffffffff16602081106112e5576112e56121ad565b602002015190508063ffffffff168363ffffffff1614801561130d57508563ffffffff166004145b8061133557508063ffffffff168363ffffffff161415801561133557508563ffffffff166005145b9150506113ba565b8463ffffffff1660060361135a5760008260030b131590506113ba565b8463ffffffff166007036113765760008260030b1390506113ba565b8463ffffffff166001036113ba57601f601085901c16600081900361139f5760008360030b1291505b8063ffffffff166001036113b85760008360030b121591505b505b8651602088015163ffffffff16885281156113fb5760026113e08661ffff1660106111b6565b63ffffffff90811690911b820160040116602089015261140d565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff86161580611444575060088663ffffffff16101580156114445750600f8663ffffffff16105b1561184d578560088114611487576009811461149057600a811461149957600b81146114a257600c81146114ab57600d81146114b457600e81146114bd576114c2565b602095506114c2565b602195506114c2565b602a95506114c2565b602b95506114c2565b602495506114c2565b602595506114c2565b602695505b508463ffffffff166000036114e7575063ffffffff8216601f600688901c161b611b2c565b8463ffffffff1660020361150b575063ffffffff8216601f600688901c161c611b2c565b8463ffffffff1660030361153f57601f600688901c1661153763ffffffff8516821c60208390036111b6565b915050611b2c565b8463ffffffff1660040361155f575063ffffffff8216601f84161b611b2c565b8463ffffffff1660060361157f575063ffffffff8216601f84161c611b2c565b8463ffffffff166007036115b0576115a98463ffffffff168463ffffffff16901c856020036111b6565b9050611b2c565b8463ffffffff166008036115c5575082611b2c565b8463ffffffff166009036115da575082611b2c565b8463ffffffff16600a036115ef575082611b2c565b8463ffffffff16600b03611604575082611b2c565b8463ffffffff16600c03611619575082611b2c565b8463ffffffff16600f0361162e575082611b2c565b8463ffffffff16601003611643575082611b2c565b8463ffffffff16601103611658575082611b2c565b8463ffffffff1660120361166d575082611b2c565b8463ffffffff16601303611682575082611b2c565b8463ffffffff16601803611697575082611b2c565b8463ffffffff166019036116ac575082611b2c565b8463ffffffff16601a036116c1575082611b2c565b8463ffffffff16601b036116d6575082611b2c565b8463ffffffff166020036116ed5750828201611b2c565b8463ffffffff166021036117045750828201611b2c565b8463ffffffff1660220361171b5750818303611b2c565b8463ffffffff166023036117325750818303611b2c565b8463ffffffff166024036117495750828216611b2c565b8463ffffffff166025036117605750828217611b2c565b8463ffffffff166026036117775750828218611b2c565b8463ffffffff1660270361178f575082821719611b2c565b8463ffffffff16602a036117be578260030b8460030b126117b15760006117b4565b60015b60ff169050611b2c565b8463ffffffff16602b036117e6578263ffffffff168463ffffffff16106117b15760006117b4565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161115a565b6117e6565b8563ffffffff16601c036118c6578463ffffffff166002036118725750828202611b2c565b8463ffffffff166020148061188d57508463ffffffff166021145b15611848578463ffffffff166020036118a4579219925b60005b63800000008516156115a9576401fffffffe600195861b1694016118a7565b8563ffffffff16600f036118e7575065ffffffff0000601083901b16611b2c565b8563ffffffff1660200361191b576115a98460031660080260180363ffffffff168363ffffffff16901c60ff1660086111b6565b8563ffffffff16602103611950576115a98460021660080260100363ffffffff168363ffffffff16901c61ffff1660106111b6565b8563ffffffff1660220361197e575063ffffffff60086003851602811681811b198416918316901b17611b2c565b8563ffffffff16602303611993575080611b2c565b8563ffffffff166024036119c4578360031660080260180363ffffffff168263ffffffff16901c60ff169050611b2c565b8563ffffffff166025036119f6578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611b2c565b8563ffffffff16602603611a27575063ffffffff60086003851602601803811681811c198416918316901c17611b2c565b8563ffffffff16602803611a5c575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611b2c565b8563ffffffff16602903611a92575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611b2c565b8563ffffffff16602a03611ac0575063ffffffff60086003851602811681811c198316918416901c17611b2c565b8563ffffffff16602b03611ad5575081611b2c565b8563ffffffff16602e03611b06575063ffffffff60086003851602601803811681811b198316918416901b17611b2c565b8563ffffffff16603003611b1b575080611b2c565b8563ffffffff166038036117e65750815b9695505050505050565b60208363ffffffff1610611ba6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161115a565b63ffffffff831615801590611bb85750805b15611be75781848463ffffffff1660208110611bd657611bd66121ad565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611c2157506060860151611e67565b8463ffffffff16601103611c405763ffffffff84166060880152611e67565b8463ffffffff16601203611c5957506040860151611e67565b8463ffffffff16601303611c785763ffffffff84166040880152611e67565b8463ffffffff16601803611cac5763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611e67565b8463ffffffff16601903611cdd5763ffffffff84811681851602602081901c821660608a0152166040880152611e67565b8463ffffffff16601a03611da0578260030b600003611d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f00000000000000000000604482015260640161115a565b8260030b8460030b81611d6d57611d6d612200565b0763ffffffff166060880152600383810b9085900b81611d8f57611d8f612200565b0563ffffffff166040880152611e67565b8463ffffffff16601b03611e67578263ffffffff16600003611e1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f00000000000000000000604482015260640161115a565b8263ffffffff168463ffffffff1681611e3957611e39612200565b0663ffffffff908116606089015283811690851681611e5a57611e5a612200565b0463ffffffff1660408801525b63ffffffff821615611e9d5780868363ffffffff1660208110611e8c57611e8c6121ad565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000611eca83611f61565b6003841615611ed857600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611f565760208601953582821c6001168015611f265760018114611f3b57611f4c565b60008581526020839052604090209450611f4c565b600082815260208690526040902094505b5050600101611efe565b509095945050505050565b366103808201811015611ff6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161115a565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101612060612065565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b818110156120b157858101830151858201604001528201612095565b818111156120c3576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261210957600080fd5b50813567ffffffffffffffff81111561212157600080fd5b6020830191508360208285010111156110d757600080fd5b60008060008060006060868803121561215157600080fd5b853567ffffffffffffffff8082111561216957600080fd5b61217589838a016120f7565b9097509550602088013591508082111561218e57600080fd5b5061219b888289016120f7565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080604083850312156121ef57600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; bytes internal constant anchorStateRegistryCode = hex"608060405234801561001057600080fd5b50600436106100675760003560e01c8063838c2d1e11610050578063838c2d1e146100fa578063c303f0df14610104578063f2b4e6171461011757600080fd5b806354fd4d501461006c5780637258a807146100be575b600080fd5b6100a86040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100b5919061085c565b60405180910390f35b6100e56100cc36600461088b565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100b5565b61010261015b565b005b61010261011236600461094f565b6105d4565b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb1681526020016100b5565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156101b0573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526101f69190810190610a68565b92509250925060007f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161025b93929190610b39565b6040805180830381865afa158015610277573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061029b9190610b67565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610384576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f416e63686f72537461746552656769737472793a206661756c7420646973707560448201527f74652067616d65206e6f7420726567697374657265642077697468206661637460648201527f6f72790000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104169190610bc7565b11610422575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561046f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104939190610c0f565b60028111156104a4576104a4610be0565b146104b0575050505050565b60405180604001604052806105308773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610509573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052d9190610bc7565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a49190610bc7565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff16158080156105f45750600054600160ff909116105b8061060e5750303b15801561060e575060005460ff166001145b61069a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161037b565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156106f857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b825181101561075e57600083828151811061071857610718610c30565b60209081029190910181015180820151905163ffffffff16600090815260018084526040909120825181559190920151910155508061075681610c5f565b9150506106fb565b5080156107c257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60005b838110156107fd5781810151838201526020016107e5565b8381111561080c576000848401525b50505050565b6000815180845261082a8160208601602086016107e2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061086f6020830184610812565b9392505050565b63ffffffff8116811461088857600080fd5b50565b60006020828403121561089d57600080fd5b813561086f81610876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156108fa576108fa6108a8565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610947576109476108a8565b604052919050565b6000602080838503121561096257600080fd5b823567ffffffffffffffff8082111561097a57600080fd5b818501915085601f83011261098e57600080fd5b8135818111156109a0576109a06108a8565b6109ae848260051b01610900565b818152848101925060609182028401850191888311156109cd57600080fd5b938501935b82851015610a5c57848903818112156109eb5760008081fd5b6109f36108d7565b86356109fe81610876565b815260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08301811315610a325760008081fd5b610a3a6108d7565b888a0135815290880135898201528189015285525093840193928501926109d2565b50979650505050505050565b600080600060608486031215610a7d57600080fd5b8351610a8881610876565b60208501516040860151919450925067ffffffffffffffff80821115610aad57600080fd5b818601915086601f830112610ac157600080fd5b815181811115610ad357610ad36108a8565b610b0460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610900565b9150808252876020828501011115610b1b57600080fd5b610b2c8160208401602086016107e2565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610b5e6060830184610812565b95945050505050565b60008060408385031215610b7a57600080fd5b825173ffffffffffffffffffffffffffffffffffffffff81168114610b9e57600080fd5b602084015190925067ffffffffffffffff81168114610bbc57600080fd5b809150509250929050565b600060208284031215610bd957600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610c2157600080fd5b81516003811061086f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610cb7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a"; bytes internal constant acc27Code = - hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b5061031761031236600461532d565b610b9f565b005b34801561032557600080fd5b50610317610334366004615388565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b91906153d9565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e366004615388565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000cdadd729ca2319e8955240bdb61a6a6a956a7664610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6610440565b61031761055936600461541a565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161037b91906154b1565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff3660046154c4565b611853565b34801561061057600080fd5b507f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b50610317610667366004615502565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed366004615534565b611a42565b3480156106fe57600080fd5b506009546103d0565b61031761071536600461541a565b6123e3565b6103176123f0565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c53660046154c4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b506103666109123660046154c4565b612949565b34801561092357600080fd5b506103d0610932366004615573565b612b28565b34801561094357600080fd5b506109576109523660046154c4565b612d0b565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd366004615502565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d3660046155a5565b612da2565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae33660046154c4565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b1336600461541a565b6133d1565b348015610b2457600080fd5b50610b2d613823565b60405161037b9392919061562f565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a3660046154c4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb6153aa565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615683565b613883565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef929190615710565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506138df92505050565b61394c565b90506000610d9e82600881518110610d9157610d91615720565b6020026020010151613b02565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec6153aa565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f38615720565b906000526020600020906005020190506000610f5384612949565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613bb6565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff16611178919061577e565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b6615720565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061122357611223615720565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf90615796565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613bb6565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613bb6565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611594576115946153aa565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b615720565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a6153aa565b02179055600281111561175f5761175f6153aa565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e473ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff16826157ce565b95945050505050565b606061183c60546020613cb7565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e6153aa565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba615720565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f0000000000000000000000000000000000000000000000000000000000000004600261577e565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f0000000000000000000000000000000000000000000000000000000000000004600161577e565b8103611dd157611dd186888588613d09565b34611ddb83612b28565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612949565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b016611ee591906157e5565b67ffffffffffffffff16611f008267ffffffffffffffff1690565b67ffffffffffffffff161115611fe2576000611f3d60017f00000000000000000000000000000000000000000000000000000000000000046157ce565b8314611f735767ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611fa8565b611fa87f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16600261580e565b9050611fde817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff166157e5565b9150505b6000604082901b42176000898152608086901b6fffffffffffffffffffffffffffffffff8c1617602052604081209192509060008181526004602052604090205490915060ff1615612060576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808c63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018b8152602001876fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008b815260200190815260200160002060016002805490506122f691906157ce565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6169263d0e30db09234926004808301939282900301818588803b15801561238e57600080fd5b505af11580156123a2573d6000803e3d6000fd5b50506040513393508c92508d91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a45050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff1615612442576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e41690637258a807906024016040805180830381865afa1580156124f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251a919061583e565b909250905081612556576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461258957639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013511612623576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa69092169363d0e30db093926004828101939282900301818588803b1580156128f857600080fd5b505af115801561290c573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612977576129776153aa565b146129ae576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600283815481106129c3576129c3615720565b600091825260208220600590910201805490925063ffffffff90811614612a3257815460028054909163ffffffff16908110612a0157612a01615720565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612a6a90700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612a7e9067ffffffffffffffff16426157ce565b612a9d612a5d846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612ab1919061577e565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612afe5780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612bc7836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612c26576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612c418383615891565b9050670de0b6b3a76400006000612c78827f00000000000000000000000000000000000000000000000000000000000000086158a5565b90506000612c96612c91670de0b6b3a7640000866158a5565b613eba565b90506000612ca48484614115565b90506000612cb28383614164565b90506000612cbf82614192565b90506000612cde82612cd9670de0b6b3a76400008f6158a5565b61437a565b90506000612cec8b83614164565b9050612cf8818d6158a5565b9f9e505050505050505050505050505050565b60028181548110612d1b57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612dce57612dce6153aa565b14612e05576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612e1a57612e1a615720565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612e797f0000000000000000000000000000000000000000000000000000000000000008600161577e565b612f15826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614612f4f576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561304657612fa27f00000000000000000000000000000000000000000000000000000000000000047f00000000000000000000000000000000000000000000000000000000000000086157ce565b6001901b612fc1846fffffffffffffffffffffffffffffffff166143b4565b6fffffffffffffffffffffffffffffffff16612fdd91906158e2565b1561301a5761301161300260016fffffffffffffffffffffffffffffffff87166158f6565b865463ffffffff166000614453565b6003015461303c565b7f00000000000000000000000000000000000000000000000000000000000000005b9150849050613070565b6003850154915061306d6130026fffffffffffffffffffffffffffffffff8616600161591f565b90505b600882901b60088a8a604051613087929190615710565b6040518091039020901b146130c8576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006130d38c614537565b905060006130e2836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000cdadd729ca2319e8955240bdb61a6a6a956a766473ffffffffffffffffffffffffffffffffffffffff169063e14ced329061315c908f908f908f908f908a9060040161599c565b6020604051808303816000875af115801561317b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319f91906159d6565b60048501549114915060009060029061324a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6132e6896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6132f091906159ef565b6132fa9190615a12565b60ff16159050811515810361333b576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff1615613392576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156133fd576133fd6153aa565b14613434576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061344386614566565b935093509350935060006134598585858561496f565b905060007f000000000000000000000000cdadd729ca2319e8955240bdb61a6a6a956a766473ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134ec9190615a34565b9050600189036135e45773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613548367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156135ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135de91906159d6565b5061155b565b600289036136105773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613548565b6003890361363c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613548565b600489036137585760006136826fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614a29565b60095461368f919061577e565b61369a90600161577e565b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af115801561372d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375191906159d6565b505061155b565b600589036137f1576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a40161359b565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360140135606061387c61188d565b9050909192565b600081600001518260200151836040015184606001516040516020016138c2949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b6040805180820190915260008082526020820152815160000361392e576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061395c85614ad7565b919450925090506001816001811115613977576139776153aa565b146139ae576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516139ba838561577e565b146139f1576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613a085790505093506000835b8651811015613af657600080613a7b6040518060400160405280858c60000151613a5f91906157ce565b8152602001858c60200151613a74919061577e565b9052614ad7565b509150915060405180604001604052808383613a97919061577e565b8152602001848b60200151613aac919061577e565b815250888581518110613ac157613ac1615720565b6020908102919091010152613ad760018561577e565b9350613ae3818361577e565b613aed908461577e565b92505050613a35565b50845250919392505050565b60606000806000613b1285614ad7565b919450925090506000816001811115613b2d57613b2d6153aa565b14613b64576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613b6e828461577e565b855114613ba7576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61188485602001518484614f75565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613c0590849061577e565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa61690637eee288d90604401600060405180830381600087803b158015613c9a57600080fd5b505af1158015613cae573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613d286fffffffffffffffffffffffffffffffff8416600161591f565b90506000613d3882866001614453565b9050600086901a8380613e245750613d7160027f00000000000000000000000000000000000000000000000000000000000000046158e2565b6004830154600290613e15906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613e1f9190615a12565b60ff16145b15613e7c5760ff811660011480613e3e575060ff81166002145b613e77576040517ff40239db0000000000000000000000000000000000000000000000000000000081526004810188905260240161261a565b613cae565b60ff811615613cae576040517ff40239db0000000000000000000000000000000000000000000000000000000081526004810188905260240161261a565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613f1957631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261415257637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156141825763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d782136141c057919050565b680755bf798b4a1bf1e582126141de5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b60006143ab670de0b6b3a76400008361439286613eba565b61439c9190615a51565b6143a69190615b0d565b614192565b90505b92915050565b600080614441837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b6000808261449c576144976fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461500a565b6144b7565b6144b7856fffffffffffffffffffffffffffffffff16615196565b9050600284815481106144cc576144cc615720565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461452f57815460028054909163ffffffff1690811061451a5761451a615720565b906000526020600020906005020191506144dd565b509392505050565b600080600080600061454886614566565b935093509350935061455c8484848461496f565b9695505050505050565b600080600080600085905060006002828154811061458657614586615720565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061465d906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614697576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061475e906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156147d357825463ffffffff1661479d7f0000000000000000000000000000000000000000000000000000000000000004600161577e565b83036147a7578391505b600281815481106147ba576147ba615720565b906000526020600020906005020193508094505061469b565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff1661483c614827856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff16149050801561490b576000614874836fffffffffffffffffffffffffffffffff166143b4565b6fffffffffffffffffffffffffffffffff1611156148df5760006148b66148ae60016fffffffffffffffffffffffffffffffff86166158f6565b896001614453565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506148e59050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614961565b600061492d6148ae6fffffffffffffffffffffffffffffffff8516600161591f565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff8416156149dc5760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614a0a9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614ab6847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614b1a576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614b3f576000600160009450945094505050614f6e565b60b78111614c55576000614b546080836157ce565b905080876000015111614b93576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614c0b57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614c42576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250614f6e915050565b60bf8111614db3576000614c6a60b7836157ce565b905080876000015111614ca9576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614d0b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614d53576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614d5d818461577e565b895111614d96576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614da183600161577e565b9750955060009450614f6e9350505050565b60f78111614e18576000614dc860c0836157ce565b905080876000015111614e07576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250614f6e915050565b6000614e2560f7836157ce565b905080876000015111614e64576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec6576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f0e576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f18818461577e565b895111614f51576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f5c83600161577e565b9750955060019450614f6e9350505050565b9193909250565b60608167ffffffffffffffff811115614f9057614f90615654565b6040519080825280601f01601f191660200182016040528015614fba576020820181803683370190505b5090508115615003576000614fcf848661577e565b90506020820160005b84811015614ff0578281015182820152602001614fd8565b84811115614fff576000858301525b5050505b9392505050565b6000816150a9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116150bf5763b34b5c226000526004601cfd5b6150c883615196565b905081615167826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116143ae576143ab61517d83600161577e565b6fffffffffffffffffffffffffffffffff83169061523b565b6000811960018301168161522a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806152c8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126152f657600080fd5b50813567ffffffffffffffff81111561530e57600080fd5b60208301915083602082850101111561532657600080fd5b9250929050565b600080600083850360a081121561534357600080fd5b608081121561535157600080fd5b50839250608084013567ffffffffffffffff81111561536f57600080fd5b61537b868287016152e4565b9497909650939450505050565b6000806040838503121561539b57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615414577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561542f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561546c57602081850181015186830182015201615450565b8181111561547e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006143ab6020830184615446565b6000602082840312156154d657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146154ff57600080fd5b50565b60006020828403121561551457600080fd5b8135615003816154dd565b8035801515811461552f57600080fd5b919050565b6000806000806080858703121561554a57600080fd5b8435935060208501359250604085013591506155686060860161551f565b905092959194509250565b60006020828403121561558557600080fd5b81356fffffffffffffffffffffffffffffffff8116811461500357600080fd5b600080600080600080608087890312156155be57600080fd5b863595506155ce6020880161551f565b9450604087013567ffffffffffffffff808211156155eb57600080fd5b6155f78a838b016152e4565b9096509450606089013591508082111561561057600080fd5b5061561d89828a016152e4565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006118846060830184615446565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561569557600080fd5b6040516080810181811067ffffffffffffffff821117156156df577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156157915761579161574f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036157c7576157c761574f565b5060010190565b6000828210156157e0576157e061574f565b500390565b600067ffffffffffffffff838116908316818110156158065761580661574f565b039392505050565b600067ffffffffffffffff808316818516818304811182151516156158355761583561574f565b02949350505050565b6000806040838503121561585157600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158a0576158a0615862565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156158dd576158dd61574f565b500290565b6000826158f1576158f1615862565b500690565b60006fffffffffffffffffffffffffffffffff838116908316818110156158065761580661574f565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561594a5761594a61574f565b01949350505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6060815260006159b0606083018789615953565b82810360208401526159c3818688615953565b9150508260408301529695505050505050565b6000602082840312156159e857600080fd5b5051919050565b600060ff821660ff841680821015615a0957615a0961574f565b90039392505050565b600060ff831680615a2557615a25615862565b8060ff84160691505092915050565b600060208284031215615a4657600080fd5b8151615003816154dd565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615a9257615a9261574f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615acd57615acd61574f565b60008712925087820587128484161615615ae957615ae961574f565b87850587128184161615615aff57615aff61574f565b505050929093029392505050565b600082615b1c57615b1c615862565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615b7057615b7061574f565b50059056fea164736f6c634300080f000a"; + hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b5061031761031236600461532d565b610b9f565b005b34801561032557600080fd5b50610317610334366004615388565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b91906153d9565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e366004615388565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f00000000000000000000000090ed5f6e29a5cd042d7bd6b1964b6156675fa1db610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6610440565b61031761055936600461541a565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161037b91906154b1565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff3660046154c4565b611853565b34801561061057600080fd5b507f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b50610317610667366004615502565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed366004615534565b611a42565b3480156106fe57600080fd5b506009546103d0565b61031761071536600461541a565b6123e3565b6103176123f0565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c53660046154c4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b506103666109123660046154c4565b612949565b34801561092357600080fd5b506103d0610932366004615573565b612b28565b34801561094357600080fd5b506109576109523660046154c4565b612d0b565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd366004615502565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d3660046155a5565b612da2565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae33660046154c4565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b1336600461541a565b6133d1565b348015610b2457600080fd5b50610b2d613823565b60405161037b9392919061562f565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a3660046154c4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb6153aa565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615683565b613883565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef929190615710565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506138df92505050565b61394c565b90506000610d9e82600881518110610d9157610d91615720565b6020026020010151613b02565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec6153aa565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f38615720565b906000526020600020906005020190506000610f5384612949565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613bb6565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff16611178919061577e565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b6615720565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061122357611223615720565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf90615796565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613bb6565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613bb6565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611594576115946153aa565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b615720565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a6153aa565b02179055600281111561175f5761175f6153aa565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e473ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff16826157ce565b95945050505050565b606061183c60546020613cb7565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e6153aa565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba615720565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f0000000000000000000000000000000000000000000000000000000000000004600261577e565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f0000000000000000000000000000000000000000000000000000000000000004600161577e565b8103611dd157611dd186888588613d09565b34611ddb83612b28565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612949565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b016611ee591906157e5565b67ffffffffffffffff16611f008267ffffffffffffffff1690565b67ffffffffffffffff161115611fe2576000611f3d60017f00000000000000000000000000000000000000000000000000000000000000046157ce565b8314611f735767ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611fa8565b611fa87f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16600261580e565b9050611fde817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff166157e5565b9150505b6000604082901b42176000898152608086901b6fffffffffffffffffffffffffffffffff8c1617602052604081209192509060008181526004602052604090205490915060ff1615612060576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808c63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018b8152602001876fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008b815260200190815260200160002060016002805490506122f691906157ce565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6169263d0e30db09234926004808301939282900301818588803b15801561238e57600080fd5b505af11580156123a2573d6000803e3d6000fd5b50506040513393508c92508d91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a45050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff1615612442576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e41690637258a807906024016040805180830381865afa1580156124f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251a919061583e565b909250905081612556576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461258957639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013511612623576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa69092169363d0e30db093926004828101939282900301818588803b1580156128f857600080fd5b505af115801561290c573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612977576129776153aa565b146129ae576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600283815481106129c3576129c3615720565b600091825260208220600590910201805490925063ffffffff90811614612a3257815460028054909163ffffffff16908110612a0157612a01615720565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612a6a90700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612a7e9067ffffffffffffffff16426157ce565b612a9d612a5d846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612ab1919061577e565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612afe5780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612bc7836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612c26576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612c418383615891565b9050670de0b6b3a76400006000612c78827f00000000000000000000000000000000000000000000000000000000000000086158a5565b90506000612c96612c91670de0b6b3a7640000866158a5565b613eba565b90506000612ca48484614115565b90506000612cb28383614164565b90506000612cbf82614192565b90506000612cde82612cd9670de0b6b3a76400008f6158a5565b61437a565b90506000612cec8b83614164565b9050612cf8818d6158a5565b9f9e505050505050505050505050505050565b60028181548110612d1b57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612dce57612dce6153aa565b14612e05576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612e1a57612e1a615720565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612e797f0000000000000000000000000000000000000000000000000000000000000008600161577e565b612f15826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614612f4f576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561304657612fa27f00000000000000000000000000000000000000000000000000000000000000047f00000000000000000000000000000000000000000000000000000000000000086157ce565b6001901b612fc1846fffffffffffffffffffffffffffffffff166143b4565b6fffffffffffffffffffffffffffffffff16612fdd91906158e2565b1561301a5761301161300260016fffffffffffffffffffffffffffffffff87166158f6565b865463ffffffff166000614453565b6003015461303c565b7f00000000000000000000000000000000000000000000000000000000000000005b9150849050613070565b6003850154915061306d6130026fffffffffffffffffffffffffffffffff8616600161591f565b90505b600882901b60088a8a604051613087929190615710565b6040518091039020901b146130c8576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006130d38c614537565b905060006130e2836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f00000000000000000000000090ed5f6e29a5cd042d7bd6b1964b6156675fa1db73ffffffffffffffffffffffffffffffffffffffff169063e14ced329061315c908f908f908f908f908a9060040161599c565b6020604051808303816000875af115801561317b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319f91906159d6565b60048501549114915060009060029061324a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6132e6896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6132f091906159ef565b6132fa9190615a12565b60ff16159050811515810361333b576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff1615613392576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156133fd576133fd6153aa565b14613434576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061344386614566565b935093509350935060006134598585858561496f565b905060007f00000000000000000000000090ed5f6e29a5cd042d7bd6b1964b6156675fa1db73ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134ec9190615a34565b9050600189036135e45773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613548367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156135ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135de91906159d6565b5061155b565b600289036136105773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613548565b6003890361363c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613548565b600489036137585760006136826fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614a29565b60095461368f919061577e565b61369a90600161577e565b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af115801561372d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375191906159d6565b505061155b565b600589036137f1576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a40161359b565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360140135606061387c61188d565b9050909192565b600081600001518260200151836040015184606001516040516020016138c2949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b6040805180820190915260008082526020820152815160000361392e576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061395c85614ad7565b919450925090506001816001811115613977576139776153aa565b146139ae576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516139ba838561577e565b146139f1576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613a085790505093506000835b8651811015613af657600080613a7b6040518060400160405280858c60000151613a5f91906157ce565b8152602001858c60200151613a74919061577e565b9052614ad7565b509150915060405180604001604052808383613a97919061577e565b8152602001848b60200151613aac919061577e565b815250888581518110613ac157613ac1615720565b6020908102919091010152613ad760018561577e565b9350613ae3818361577e565b613aed908461577e565b92505050613a35565b50845250919392505050565b60606000806000613b1285614ad7565b919450925090506000816001811115613b2d57613b2d6153aa565b14613b64576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613b6e828461577e565b855114613ba7576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61188485602001518484614f75565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613c0590849061577e565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa61690637eee288d90604401600060405180830381600087803b158015613c9a57600080fd5b505af1158015613cae573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613d286fffffffffffffffffffffffffffffffff8416600161591f565b90506000613d3882866001614453565b9050600086901a8380613e245750613d7160027f00000000000000000000000000000000000000000000000000000000000000046158e2565b6004830154600290613e15906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613e1f9190615a12565b60ff16145b15613e7c5760ff811660011480613e3e575060ff81166002145b613e77576040517ff40239db0000000000000000000000000000000000000000000000000000000081526004810188905260240161261a565b613cae565b60ff811615613cae576040517ff40239db0000000000000000000000000000000000000000000000000000000081526004810188905260240161261a565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613f1957631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261415257637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156141825763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d782136141c057919050565b680755bf798b4a1bf1e582126141de5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b60006143ab670de0b6b3a76400008361439286613eba565b61439c9190615a51565b6143a69190615b0d565b614192565b90505b92915050565b600080614441837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b6000808261449c576144976fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461500a565b6144b7565b6144b7856fffffffffffffffffffffffffffffffff16615196565b9050600284815481106144cc576144cc615720565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461452f57815460028054909163ffffffff1690811061451a5761451a615720565b906000526020600020906005020191506144dd565b509392505050565b600080600080600061454886614566565b935093509350935061455c8484848461496f565b9695505050505050565b600080600080600085905060006002828154811061458657614586615720565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061465d906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614697576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061475e906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156147d357825463ffffffff1661479d7f0000000000000000000000000000000000000000000000000000000000000004600161577e565b83036147a7578391505b600281815481106147ba576147ba615720565b906000526020600020906005020193508094505061469b565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff1661483c614827856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff16149050801561490b576000614874836fffffffffffffffffffffffffffffffff166143b4565b6fffffffffffffffffffffffffffffffff1611156148df5760006148b66148ae60016fffffffffffffffffffffffffffffffff86166158f6565b896001614453565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506148e59050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614961565b600061492d6148ae6fffffffffffffffffffffffffffffffff8516600161591f565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff8416156149dc5760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614a0a9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614ab6847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614b1a576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614b3f576000600160009450945094505050614f6e565b60b78111614c55576000614b546080836157ce565b905080876000015111614b93576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614c0b57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614c42576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250614f6e915050565b60bf8111614db3576000614c6a60b7836157ce565b905080876000015111614ca9576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614d0b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614d53576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614d5d818461577e565b895111614d96576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614da183600161577e565b9750955060009450614f6e9350505050565b60f78111614e18576000614dc860c0836157ce565b905080876000015111614e07576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250614f6e915050565b6000614e2560f7836157ce565b905080876000015111614e64576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec6576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f0e576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f18818461577e565b895111614f51576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f5c83600161577e565b9750955060019450614f6e9350505050565b9193909250565b60608167ffffffffffffffff811115614f9057614f90615654565b6040519080825280601f01601f191660200182016040528015614fba576020820181803683370190505b5090508115615003576000614fcf848661577e565b90506020820160005b84811015614ff0578281015182820152602001614fd8565b84811115614fff576000858301525b5050505b9392505050565b6000816150a9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116150bf5763b34b5c226000526004601cfd5b6150c883615196565b905081615167826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116143ae576143ab61517d83600161577e565b6fffffffffffffffffffffffffffffffff83169061523b565b6000811960018301168161522a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806152c8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126152f657600080fd5b50813567ffffffffffffffff81111561530e57600080fd5b60208301915083602082850101111561532657600080fd5b9250929050565b600080600083850360a081121561534357600080fd5b608081121561535157600080fd5b50839250608084013567ffffffffffffffff81111561536f57600080fd5b61537b868287016152e4565b9497909650939450505050565b6000806040838503121561539b57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615414577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561542f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561546c57602081850181015186830182015201615450565b8181111561547e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006143ab6020830184615446565b6000602082840312156154d657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146154ff57600080fd5b50565b60006020828403121561551457600080fd5b8135615003816154dd565b8035801515811461552f57600080fd5b919050565b6000806000806080858703121561554a57600080fd5b8435935060208501359250604085013591506155686060860161551f565b905092959194509250565b60006020828403121561558557600080fd5b81356fffffffffffffffffffffffffffffffff8116811461500357600080fd5b600080600080600080608087890312156155be57600080fd5b863595506155ce6020880161551f565b9450604087013567ffffffffffffffff808211156155eb57600080fd5b6155f78a838b016152e4565b9096509450606089013591508082111561561057600080fd5b5061561d89828a016152e4565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006118846060830184615446565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561569557600080fd5b6040516080810181811067ffffffffffffffff821117156156df577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156157915761579161574f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036157c7576157c761574f565b5060010190565b6000828210156157e0576157e061574f565b500390565b600067ffffffffffffffff838116908316818110156158065761580661574f565b039392505050565b600067ffffffffffffffff808316818516818304811182151516156158355761583561574f565b02949350505050565b6000806040838503121561585157600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158a0576158a0615862565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156158dd576158dd61574f565b500290565b6000826158f1576158f1615862565b500690565b60006fffffffffffffffffffffffffffffffff838116908316818110156158065761580661574f565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561594a5761594a61574f565b01949350505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6060815260006159b0606083018789615953565b82810360208401526159c3818688615953565b9150508260408301529695505050505050565b6000602082840312156159e857600080fd5b5051919050565b600060ff821660ff841680821015615a0957615a0961574f565b90039392505050565b600060ff831680615a2557615a25615862565b8060ff84160691505092915050565b600060208284031215615a4657600080fd5b8151615003816154dd565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615a9257615a9261574f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615acd57615acd61574f565b60008712925087820587128484161615615ae957615ae961574f565b87850587128184161615615aff57615aff61574f565b505050929093029392505050565b600082615b1c57615b1c615862565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615b7057615b7061574f565b50059056fea164736f6c634300080f000a"; bytes internal constant acc28Code = - hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d6103283660046155a8565b610c1b565b005b34801561033b57600080fd5b5061032d61034a366004615603565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615654565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e6610424366004615603565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000cdadd729ca2319e8955240bdb61a6a6a956a7664610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6610456565b61032d61056f366004615695565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b604051610391919061572c565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e661064836600461573f565b6118cf565b34801561065957600080fd5b507f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b036600461577d565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d6107363660046157af565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e366004615695565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e36600461573f565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e36600461573f565b611c05565b34801561099f57600080fd5b506103e66109ae3660046157ee565b611de4565b3480156109bf57600080fd5b506109d36109ce36600461573f565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a7936600461577d565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad9366004615820565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f36600461573f565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f366004615695565b612123565b348015610ba057600080fd5b50610ba9612575565b604051610391939291906158aa565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c0636600461573f565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c47615625565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a368690038601866158fe565b6125d5565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b92919061598b565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061263192505050565b61269e565b90506000610e1a82600881518110610e0d57610e0d61599b565b6020026020010151612854565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f68615625565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb461599b565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f98187612908565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f491906159f9565b905060008382116112055781611207565b835b602084015190915063ffffffff165b818110156113535760008682815481106112325761123261599b565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f61599b565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615a11565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a612908565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89612908565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff16600281111561161057611610615625565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d761599b565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c6615625565b0217905560028111156117db576117db615625565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e473ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615a49565b95945050505050565b60606118b860546020612a09565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612a5b565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036133fc565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c33615625565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f61599b565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd61599b565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615a49565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d91906159f9565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615a8f565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615aa3565b90506000611f52611f4d670de0b6b3a764000086615aa3565b613955565b90506000611f608484613bb0565b90506000611f6e8383613bff565b90506000611f7b82613c2d565b90506000611f9a82611f95670de0b6b3a76400008f615aa3565b613e15565b90506000611fa88b83613bff565b9050611fb4818d615aa3565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686613e4f565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f615625565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000806121958661447e565b935093509350935060006121ab85858585614887565b905060007f000000000000000000000000cdadd729ca2319e8955240bdb61a6a6a956a766473ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615ae0565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615afd565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036124aa5760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614941565b6009546123e191906159f9565b6123ec9060016159f9565b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af115801561247f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a39190615afd565b50506115d7565b60058903612543576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560606125ce611909565b9050909192565b60008160000151826020015183604001518460600151604051602001612614949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612680576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b606060008060006126ae856149ef565b9194509250905060018160018111156126c9576126c9615625565b14612700576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845161270c83856159f9565b14612743576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b604080518082019091526000808252602082015281526020019060019003908161275a5790505093506000835b8651811015612848576000806127cd6040518060400160405280858c600001516127b19190615a49565b8152602001858c602001516127c691906159f9565b90526149ef565b5091509150604051806040016040528083836127e991906159f9565b8152602001848b602001516127fe91906159f9565b8152508885815181106128135761281361599b565b60209081029190910101526128296001856159f9565b935061283581836159f9565b61283f90846159f9565b92505050612787565b50845250919392505050565b60606000806000612864856149ef565b91945092509050600081600181111561287f5761287f615625565b146128b6576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128c082846159f9565b8551146128f9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484614e8d565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129579084906159f9565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa61690637eee288d90604401600060405180830381600087803b1580156129ec57600080fd5b505af1158015612a00573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612a8757612a87615625565b14612abe576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612ad357612ad361599b565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612bba576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612c7a826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612cb55750612cb27f000000000000000000000000000000000000000000000000000000000000000460026159f9565b81145b8015612cbf575084155b15612cf6576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612d1c575086155b15612d53576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612dad576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612dd87f000000000000000000000000000000000000000000000000000000000000000460016159f9565b8103612dea57612dea86888588614f22565b34612df483611de4565b14612e2b576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612e3688611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612e9e576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b016612efe9190615b16565b67ffffffffffffffff16612f198267ffffffffffffffff1690565b67ffffffffffffffff161115612ffb576000612f5660017f0000000000000000000000000000000000000000000000000000000000000004615a49565b8314612f8c5767ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016612fc1565b612fc17f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615b3f565b9050612ff7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615b16565b9150505b6000604082901b42176000898152608086901b6fffffffffffffffffffffffffffffffff8c1617602052604081209192509060008181526004602052604090205490915060ff1615613079576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808c63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018b8152602001876fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008b8152602001908152602001600020600160028054905061330f9190615a49565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6169263d0e30db09234926004808301939282900301818588803b1580156133a757600080fd5b505af11580156133bb573d6000803e3d6000fd5b50506040513393508c92508d91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a45050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561344e576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e41690637258a807906024016040805180830381865afa158015613502573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135269190615b6f565b909250905081613562576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461359557639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161362f576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa69092169363d0e30db093926004828101939282900301818588803b15801561390457600080fd5b505af1158015613918573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136139b457631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613bed57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613c1d5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613c5b57919050565b680755bf798b4a1bf1e58212613c795763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613e46670de0b6b3a764000083613e2d86613955565b613e379190615b93565b613e419190615c4f565b613c2d565b90505b92915050565b60008054700100000000000000000000000000000000900460ff166002811115613e7b57613e7b615625565b14613eb2576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110613ec757613ec761599b565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050613f267f000000000000000000000000000000000000000000000000000000000000000860016159f9565b613fc2826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613ffc576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156140f35761404f7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615a49565b6001901b61406e846fffffffffffffffffffffffffffffffff166150d3565b6fffffffffffffffffffffffffffffffff1661408a9190615cb7565b156140c7576140be6140af60016fffffffffffffffffffffffffffffffff8716615ccb565b865463ffffffff166000615172565b600301546140e9565b7f00000000000000000000000000000000000000000000000000000000000000005b915084905061411d565b6003850154915061411a6140af6fffffffffffffffffffffffffffffffff86166001615cf4565b90505b600882901b60088a8a60405161413492919061598b565b6040518091039020901b14614175576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006141808c615256565b9050600061418f836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000cdadd729ca2319e8955240bdb61a6a6a956a766473ffffffffffffffffffffffffffffffffffffffff169063e14ced3290614209908f908f908f908f908a90600401615d71565b6020604051808303816000875af1158015614228573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061424c9190615afd565b6004850154911491506000906002906142f7906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614393896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61439d9190615dab565b6143a79190615dce565b60ff1615905081151581036143e8576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff161561443f576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061449e5761449e61599b565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614575906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116145af576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614676906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156146eb57825463ffffffff166146b57f000000000000000000000000000000000000000000000000000000000000000460016159f9565b83036146bf578391505b600281815481106146d2576146d261599b565b90600052602060002090600502019350809450506145b3565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff1661475461473f856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff16149050801561482357600061478c836fffffffffffffffffffffffffffffffff166150d3565b6fffffffffffffffffffffffffffffffff1611156147f75760006147ce6147c660016fffffffffffffffffffffffffffffffff8616615ccb565b896001615172565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506147fd9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614879565b60006148456147c66fffffffffffffffffffffffffffffffff85166001615cf4565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff8416156148f45760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b82826040516020016149229291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b6000806149ce847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614a32576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614a57576000600160009450945094505050614e86565b60b78111614b6d576000614a6c608083615a49565b905080876000015111614aab576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614b2357507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614b5a576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250614e86915050565b60bf8111614ccb576000614b8260b783615a49565b905080876000015111614bc1576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614c23576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614c6b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614c7581846159f9565b895111614cae576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614cb98360016159f9565b9750955060009450614e869350505050565b60f78111614d30576000614ce060c083615a49565b905080876000015111614d1f576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250614e86915050565b6000614d3d60f783615a49565b905080876000015111614d7c576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dde576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e26576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e3081846159f9565b895111614e69576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e748360016159f9565b9750955060019450614e869350505050565b9193909250565b60608167ffffffffffffffff811115614ea857614ea86158cf565b6040519080825280601f01601f191660200182016040528015614ed2576020820181803683370190505b5090508115614f1b576000614ee784866159f9565b90506020820160005b84811015614f08578281015182820152602001614ef0565b84811115614f17576000858301525b5050505b9392505050565b6000614f416fffffffffffffffffffffffffffffffff84166001615cf4565b90506000614f5182866001615172565b9050600086901a838061503d5750614f8a60027f0000000000000000000000000000000000000000000000000000000000000004615cb7565b600483015460029061502e906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6150389190615dce565b60ff16145b156150955760ff811660011480615057575060ff81166002145b615090576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401613626565b612a00565b60ff811615612a00576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401613626565b600080615160837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826151bb576151b66fffffffffffffffffffffffffffffffff86167f0000000000000000000000000000000000000000000000000000000000000004615285565b6151d6565b6151d6856fffffffffffffffffffffffffffffffff16615411565b9050600284815481106151eb576151eb61599b565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461524e57815460028054909163ffffffff169081106152395761523961599b565b906000526020600020906005020191506151fc565b509392505050565b60008060008060006152678661447e565b935093509350935061527b84848484614887565b9695505050505050565b600081615324846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161533a5763b34b5c226000526004601cfd5b61534383615411565b9050816153e2826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613e4957613e466153f88360016159f9565b6fffffffffffffffffffffffffffffffff8316906154b6565b600081196001830116816154a5827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b600080615543847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261557157600080fd5b50813567ffffffffffffffff81111561558957600080fd5b6020830191508360208285010111156155a157600080fd5b9250929050565b600080600083850360a08112156155be57600080fd5b60808112156155cc57600080fd5b50839250608084013567ffffffffffffffff8111156155ea57600080fd5b6155f68682870161555f565b9497909650939450505050565b6000806040838503121561561657600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061568f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156156aa57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b818110156156e7576020818501810151868301820152016156cb565b818111156156f9576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613e4660208301846156c1565b60006020828403121561575157600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461577a57600080fd5b50565b60006020828403121561578f57600080fd5b8135614f1b81615758565b803580151581146157aa57600080fd5b919050565b600080600080608085870312156157c557600080fd5b8435935060208501359250604085013591506157e36060860161579a565b905092959194509250565b60006020828403121561580057600080fd5b81356fffffffffffffffffffffffffffffffff81168114614f1b57600080fd5b6000806000806000806080878903121561583957600080fd5b863595506158496020880161579a565b9450604087013567ffffffffffffffff8082111561586657600080fd5b6158728a838b0161555f565b9096509450606089013591508082111561588b57600080fd5b5061589889828a0161555f565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061190060608301846156c1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561591057600080fd5b6040516080810181811067ffffffffffffffff8211171561595a577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615a0c57615a0c6159ca565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615a4257615a426159ca565b5060010190565b600082821015615a5b57615a5b6159ca565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615a9e57615a9e615a60565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615adb57615adb6159ca565b500290565b600060208284031215615af257600080fd5b8151614f1b81615758565b600060208284031215615b0f57600080fd5b5051919050565b600067ffffffffffffffff83811690831681811015615b3757615b376159ca565b039392505050565b600067ffffffffffffffff80831681851681830481118215151615615b6657615b666159ca565b02949350505050565b60008060408385031215615b8257600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615bd457615bd46159ca565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615c0f57615c0f6159ca565b60008712925087820587128484161615615c2b57615c2b6159ca565b87850587128184161615615c4157615c416159ca565b505050929093029392505050565b600082615c5e57615c5e615a60565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615cb257615cb26159ca565b500590565b600082615cc657615cc6615a60565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615b3757615b376159ca565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615d1f57615d1f6159ca565b01949350505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615d85606083018789615d28565b8281036020840152615d98818688615d28565b9150508260408301529695505050505050565b600060ff821660ff841680821015615dc557615dc56159ca565b90039392505050565b600060ff831680615de157615de1615a60565b8060ff8416069150509291505056fea164736f6c634300080f000a"; + hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d6103283660046155a8565b610c1b565b005b34801561033b57600080fd5b5061032d61034a366004615603565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615654565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e6610424366004615603565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f00000000000000000000000090ed5f6e29a5cd042d7bd6b1964b6156675fa1db610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6610456565b61032d61056f366004615695565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b604051610391919061572c565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e661064836600461573f565b6118cf565b34801561065957600080fd5b507f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b036600461577d565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d6107363660046157af565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e366004615695565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e36600461573f565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e36600461573f565b611c05565b34801561099f57600080fd5b506103e66109ae3660046157ee565b611de4565b3480156109bf57600080fd5b506109d36109ce36600461573f565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a7936600461577d565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad9366004615820565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f36600461573f565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f366004615695565b612123565b348015610ba057600080fd5b50610ba9612575565b604051610391939291906158aa565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c0636600461573f565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c47615625565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a368690038601866158fe565b6125d5565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b92919061598b565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061263192505050565b61269e565b90506000610e1a82600881518110610e0d57610e0d61599b565b6020026020010151612854565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f68615625565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb461599b565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f98187612908565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f491906159f9565b905060008382116112055781611207565b835b602084015190915063ffffffff165b818110156113535760008682815481106112325761123261599b565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f61599b565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615a11565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a612908565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89612908565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff16600281111561161057611610615625565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d761599b565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c6615625565b0217905560028111156117db576117db615625565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e473ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615a49565b95945050505050565b60606118b860546020612a09565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612a5b565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036133fc565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c33615625565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f61599b565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd61599b565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615a49565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d91906159f9565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615a8f565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615aa3565b90506000611f52611f4d670de0b6b3a764000086615aa3565b613955565b90506000611f608484613bb0565b90506000611f6e8383613bff565b90506000611f7b82613c2d565b90506000611f9a82611f95670de0b6b3a76400008f615aa3565b613e15565b90506000611fa88b83613bff565b9050611fb4818d615aa3565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686613e4f565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f615625565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000806121958661447e565b935093509350935060006121ab85858585614887565b905060007f00000000000000000000000090ed5f6e29a5cd042d7bd6b1964b6156675fa1db73ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615ae0565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615afd565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036124aa5760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614941565b6009546123e191906159f9565b6123ec9060016159f9565b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af115801561247f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a39190615afd565b50506115d7565b60058903612543576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560606125ce611909565b9050909192565b60008160000151826020015183604001518460600151604051602001612614949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612680576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b606060008060006126ae856149ef565b9194509250905060018160018111156126c9576126c9615625565b14612700576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845161270c83856159f9565b14612743576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b604080518082019091526000808252602082015281526020019060019003908161275a5790505093506000835b8651811015612848576000806127cd6040518060400160405280858c600001516127b19190615a49565b8152602001858c602001516127c691906159f9565b90526149ef565b5091509150604051806040016040528083836127e991906159f9565b8152602001848b602001516127fe91906159f9565b8152508885815181106128135761281361599b565b60209081029190910101526128296001856159f9565b935061283581836159f9565b61283f90846159f9565b92505050612787565b50845250919392505050565b60606000806000612864856149ef565b91945092509050600081600181111561287f5761287f615625565b146128b6576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128c082846159f9565b8551146128f9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484614e8d565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129579084906159f9565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa61690637eee288d90604401600060405180830381600087803b1580156129ec57600080fd5b505af1158015612a00573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612a8757612a87615625565b14612abe576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612ad357612ad361599b565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612bba576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612c7a826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612cb55750612cb27f000000000000000000000000000000000000000000000000000000000000000460026159f9565b81145b8015612cbf575084155b15612cf6576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612d1c575086155b15612d53576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612dad576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612dd87f000000000000000000000000000000000000000000000000000000000000000460016159f9565b8103612dea57612dea86888588614f22565b34612df483611de4565b14612e2b576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612e3688611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612e9e576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b016612efe9190615b16565b67ffffffffffffffff16612f198267ffffffffffffffff1690565b67ffffffffffffffff161115612ffb576000612f5660017f0000000000000000000000000000000000000000000000000000000000000004615a49565b8314612f8c5767ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016612fc1565b612fc17f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615b3f565b9050612ff7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615b16565b9150505b6000604082901b42176000898152608086901b6fffffffffffffffffffffffffffffffff8c1617602052604081209192509060008181526004602052604090205490915060ff1615613079576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808c63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018b8152602001876fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008b8152602001908152602001600020600160028054905061330f9190615a49565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6169263d0e30db09234926004808301939282900301818588803b1580156133a757600080fd5b505af11580156133bb573d6000803e3d6000fd5b50506040513393508c92508d91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a45050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561344e576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e41690637258a807906024016040805180830381865afa158015613502573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135269190615b6f565b909250905081613562576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461359557639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161362f576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa69092169363d0e30db093926004828101939282900301818588803b15801561390457600080fd5b505af1158015613918573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136139b457631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613bed57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613c1d5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613c5b57919050565b680755bf798b4a1bf1e58212613c795763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613e46670de0b6b3a764000083613e2d86613955565b613e379190615b93565b613e419190615c4f565b613c2d565b90505b92915050565b60008054700100000000000000000000000000000000900460ff166002811115613e7b57613e7b615625565b14613eb2576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110613ec757613ec761599b565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050613f267f000000000000000000000000000000000000000000000000000000000000000860016159f9565b613fc2826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613ffc576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156140f35761404f7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615a49565b6001901b61406e846fffffffffffffffffffffffffffffffff166150d3565b6fffffffffffffffffffffffffffffffff1661408a9190615cb7565b156140c7576140be6140af60016fffffffffffffffffffffffffffffffff8716615ccb565b865463ffffffff166000615172565b600301546140e9565b7f00000000000000000000000000000000000000000000000000000000000000005b915084905061411d565b6003850154915061411a6140af6fffffffffffffffffffffffffffffffff86166001615cf4565b90505b600882901b60088a8a60405161413492919061598b565b6040518091039020901b14614175576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006141808c615256565b9050600061418f836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f00000000000000000000000090ed5f6e29a5cd042d7bd6b1964b6156675fa1db73ffffffffffffffffffffffffffffffffffffffff169063e14ced3290614209908f908f908f908f908a90600401615d71565b6020604051808303816000875af1158015614228573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061424c9190615afd565b6004850154911491506000906002906142f7906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614393896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61439d9190615dab565b6143a79190615dce565b60ff1615905081151581036143e8576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff161561443f576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061449e5761449e61599b565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614575906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116145af576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614676906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156146eb57825463ffffffff166146b57f000000000000000000000000000000000000000000000000000000000000000460016159f9565b83036146bf578391505b600281815481106146d2576146d261599b565b90600052602060002090600502019350809450506145b3565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff1661475461473f856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff16149050801561482357600061478c836fffffffffffffffffffffffffffffffff166150d3565b6fffffffffffffffffffffffffffffffff1611156147f75760006147ce6147c660016fffffffffffffffffffffffffffffffff8616615ccb565b896001615172565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506147fd9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614879565b60006148456147c66fffffffffffffffffffffffffffffffff85166001615cf4565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff8416156148f45760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b82826040516020016149229291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b6000806149ce847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614a32576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614a57576000600160009450945094505050614e86565b60b78111614b6d576000614a6c608083615a49565b905080876000015111614aab576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614b2357507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614b5a576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250614e86915050565b60bf8111614ccb576000614b8260b783615a49565b905080876000015111614bc1576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614c23576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614c6b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614c7581846159f9565b895111614cae576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614cb98360016159f9565b9750955060009450614e869350505050565b60f78111614d30576000614ce060c083615a49565b905080876000015111614d1f576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250614e86915050565b6000614d3d60f783615a49565b905080876000015111614d7c576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dde576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e26576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e3081846159f9565b895111614e69576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e748360016159f9565b9750955060019450614e869350505050565b9193909250565b60608167ffffffffffffffff811115614ea857614ea86158cf565b6040519080825280601f01601f191660200182016040528015614ed2576020820181803683370190505b5090508115614f1b576000614ee784866159f9565b90506020820160005b84811015614f08578281015182820152602001614ef0565b84811115614f17576000858301525b5050505b9392505050565b6000614f416fffffffffffffffffffffffffffffffff84166001615cf4565b90506000614f5182866001615172565b9050600086901a838061503d5750614f8a60027f0000000000000000000000000000000000000000000000000000000000000004615cb7565b600483015460029061502e906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6150389190615dce565b60ff16145b156150955760ff811660011480615057575060ff81166002145b615090576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401613626565b612a00565b60ff811615612a00576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401613626565b600080615160837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826151bb576151b66fffffffffffffffffffffffffffffffff86167f0000000000000000000000000000000000000000000000000000000000000004615285565b6151d6565b6151d6856fffffffffffffffffffffffffffffffff16615411565b9050600284815481106151eb576151eb61599b565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461524e57815460028054909163ffffffff169081106152395761523961599b565b906000526020600020906005020191506151fc565b509392505050565b60008060008060006152678661447e565b935093509350935061527b84848484614887565b9695505050505050565b600081615324846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161533a5763b34b5c226000526004601cfd5b61534383615411565b9050816153e2826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613e4957613e466153f88360016159f9565b6fffffffffffffffffffffffffffffffff8316906154b6565b600081196001830116816154a5827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b600080615543847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261557157600080fd5b50813567ffffffffffffffff81111561558957600080fd5b6020830191508360208285010111156155a157600080fd5b9250929050565b600080600083850360a08112156155be57600080fd5b60808112156155cc57600080fd5b50839250608084013567ffffffffffffffff8111156155ea57600080fd5b6155f68682870161555f565b9497909650939450505050565b6000806040838503121561561657600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061568f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156156aa57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b818110156156e7576020818501810151868301820152016156cb565b818111156156f9576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613e4660208301846156c1565b60006020828403121561575157600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461577a57600080fd5b50565b60006020828403121561578f57600080fd5b8135614f1b81615758565b803580151581146157aa57600080fd5b919050565b600080600080608085870312156157c557600080fd5b8435935060208501359250604085013591506157e36060860161579a565b905092959194509250565b60006020828403121561580057600080fd5b81356fffffffffffffffffffffffffffffffff81168114614f1b57600080fd5b6000806000806000806080878903121561583957600080fd5b863595506158496020880161579a565b9450604087013567ffffffffffffffff8082111561586657600080fd5b6158728a838b0161555f565b9096509450606089013591508082111561588b57600080fd5b5061589889828a0161555f565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061190060608301846156c1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561591057600080fd5b6040516080810181811067ffffffffffffffff8211171561595a577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615a0c57615a0c6159ca565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615a4257615a426159ca565b5060010190565b600082821015615a5b57615a5b6159ca565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615a9e57615a9e615a60565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615adb57615adb6159ca565b500290565b600060208284031215615af257600080fd5b8151614f1b81615758565b600060208284031215615b0f57600080fd5b5051919050565b600067ffffffffffffffff83811690831681811015615b3757615b376159ca565b039392505050565b600067ffffffffffffffff80831681851681830481118215151615615b6657615b666159ca565b02949350505050565b60008060408385031215615b8257600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615bd457615bd46159ca565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615c0f57615c0f6159ca565b60008712925087820587128484161615615c2b57615c2b6159ca565b87850587128184161615615c4157615c416159ca565b505050929093029392505050565b600082615c5e57615c5e615a60565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615cb257615cb26159ca565b500590565b600082615cc657615cc6615a60565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615b3757615b376159ca565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615d1f57615d1f6159ca565b01949350505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615d85606083018789615d28565b8281036020840152615d98818688615d28565b9150508260408301529695505050505050565b600060ff821660ff841680821015615dc557615dc56159ca565b90039392505050565b600060ff831680615de157615de1615a60565b8060ff8416069150509291505056fea164736f6c634300080f000a"; } diff --git a/packages/contracts-bedrock/test/setup/Setup.sol b/packages/contracts-bedrock/test/setup/Setup.sol index 7cf4d2a47d08f..537585d7105d7 100644 --- a/packages/contracts-bedrock/test/setup/Setup.sol +++ b/packages/contracts-bedrock/test/setup/Setup.sol @@ -41,6 +41,8 @@ import { Vm } from "forge-std/Vm.sol"; import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; import { DataAvailabilityChallenge } from "src/L1/DataAvailabilityChallenge.sol"; import { WETH } from "src/L2/WETH.sol"; +import { SuperchainWETH } from "src/L2/SuperchainWETH.sol"; +import { ETHLiquidity } from "src/L2/ETHLiquidity.sol"; /// @title Setup /// @dev This contact is responsible for setting up the contracts in state. It currently @@ -94,6 +96,8 @@ contract Setup { LegacyMessagePasser legacyMessagePasser = LegacyMessagePasser(Predeploys.LEGACY_MESSAGE_PASSER); GovernanceToken governanceToken = GovernanceToken(Predeploys.GOVERNANCE_TOKEN); WETH weth = WETH(payable(Predeploys.WETH)); + SuperchainWETH superchainWeth = SuperchainWETH(payable(Predeploys.SUPERCHAIN_WETH)); + ETHLiquidity ethLiquidity = ETHLiquidity(Predeploys.ETH_LIQUIDITY); /// @dev Deploys the Deploy contract without including its bytecode in the bytecode /// of this contract by fetching the bytecode dynamically using `vm.getCode()`. @@ -211,6 +215,8 @@ contract Setup { labelPredeploy(Predeploys.EAS); labelPredeploy(Predeploys.SCHEMA_REGISTRY); labelPredeploy(Predeploys.WETH); + labelPredeploy(Predeploys.SUPERCHAIN_WETH); + labelPredeploy(Predeploys.ETH_LIQUIDITY); // L2 Preinstalls labelPreinstall(Preinstalls.MultiCall3);