From 82d14b9d0b0f6be3df43268c41cffec4701368f8 Mon Sep 17 00:00:00 2001 From: Paul Razvan Berg Date: Thu, 29 Jun 2023 18:18:07 +0300 Subject: [PATCH] docs: roll v4.0.0-beta.6 docs: update README --- CHANGELOG.md | 32 ++++++++ README.md | 116 +++++++++++----------------- package.json | 2 +- src/PRBProxyRegistry.sol | 2 +- test/registry/version/version.t.sol | 2 +- test/utils/Precompiles.sol | 2 +- 6 files changed, 81 insertions(+), 75 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7221137..d91645f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Common Changelog](https://common-changelog.org/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +[4.0.0-beta.6]: https://github.com/PaulRBerg/prb-proxy/compare/v4.0.0-beta.5...v4.0.0-beta.6 [4.0.0-beta.5]: https://github.com/PaulRBerg/prb-proxy/compare/v4.0.0-beta.4...v4.0.0-beta.5 [4.0.0-beta.4]: https://github.com/PaulRBerg/prb-proxy/compare/v4.0.0-beta.3...v4.0.0-beta.4 [4.0.0-beta.3]: https://github.com/PaulRBerg/prb-proxy/compare/v4.0.0-beta.2...v4.0.0-beta.3 @@ -14,6 +15,37 @@ The format is based on [Common Changelog](https://common-changelog.org/), and th [1.0.1]: https://github.com/PaulRBerg/prb-proxy/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/PaulRBerg/prb-proxy/releases/tag/v1.0.0 +## [4.0.0-beta.6] - 2023-06-29 + +### Changed + +- Change `proxies` getter to `getProxy` ([#100](https://github.com/PaulRBerg/prb-proxy/pull/118)) (@PaulRBerg) +- Improve documentation in NatSpec comments (@PaulRBerg) +- Make the registry in charge of plugins ([#120](https://github.com/PaulRBerg/prb-proxy/pull/120)) (@PaulRBerg) +- Make the `owner` an immutable variable ([#120](https://github.com/PaulRBerg/prb-proxy/pull/120)) (@PaulRBerg) +- Rename `methodList` to `methods` +- Use `owner` instead of `tx.origin` as CREATE2 salt ([#130](https://github.com/PaulRBerg/prb-proxy/pull/130)) (@PaulRBerg) + +### Added + +- Add `deployAndExecuteAndInstallPlugin` function ([#134](https://github.com/PaulRBerg/prb-proxy/pull/134)) (@PaulRBerg) +- Add `deployAndInstallPlugin` function ([#131](https://github.com/PaulRBerg/prb-proxy/pull/131)) (@PaulRBerg) +- Add new getters for reading the plugins and the permissions ([#120](https://github.com/PaulRBerg/prb-proxy/pull/120)) (@PaulRBerg) +- Store plugin methods in reverse mapping ([#131](https://github.com/PaulRBerg/prb-proxy/pull/131)) (@PaulRBerg) + +### Removed + +- Remove `deployAndExecuteFor` function ([#113](https://github.com/PaulRBerg/prb-proxy/pull/113)) (@PaulRBerg) +- Remove `minGasReserve` storage variable ([#114](https://github.com/PaulRBerg/prb-proxy/pull/114)) (@PaulRBerg) +- Remove `nextSeeds` storage variable ([#130](https://github.com/PaulRBerg/prb-proxy/pull/130)) (@PaulRBerg) +- Remove `PRBProxyAnnex` ([#120](https://github.com/PaulRBerg/prb-proxy/pull/120)) (@PaulRBerg) +- Remove proxy storage ([#120](https://github.com/PaulRBerg/prb-proxy/pull/120)) (@PaulRBerg) +- Remove `transferOwnership` functionality ([#119](https://github.com/PaulRBerg/prb-proxy/pull/119)) (@PaulRBerg) + +### Fixed + +- Check for plugin method collisions ([#129](https://github.com/PaulRBerg/prb-proxy/pull/129)) (@PaulRBerg) + ## [4.0.0-beta.5] - 2023-05-30 ### Changed diff --git a/README.md b/README.md index 68cf041..705a6f3 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ [license-badge]: https://img.shields.io/badge/License-MIT-blue.svg PRBProxy is a **proxy contract that allows for the composition of Ethereum transactions on behalf of the contract owner**, acting as a smart wallet -that enables multiple contract calls within a single transaction. Externally owned accounts (EOAs) do not have this functionality; they are limited to -interacting with only one contract per transaction. +that enables multiple contract calls within a single transaction. In Ethereum, externally owned accounts (EOAs) do not have this functionality; they +are limited to interacting with only one contract per transaction. Some key features of PRBProxy include: @@ -19,35 +19,13 @@ Some key features of PRBProxy include: - Use of [CREATE2][eip-1014] to deploy the proxies at deterministic addresses. - A unique registry system ensures that each user has a distinct proxy. - An access control system that permits third-party accounts (called "envoys") to call target contracts on behalf of the owner. -- A plugin system that enables the proxy to respond to callbacks +- A plugin system that enables the proxy to respond to callbacks. - Reversion with custom errors rather than reason strings for improved error handling. - Comprehensive documentation via NatSpec comments. - Development and testing using Foundry. Overall, PRBProxy is a powerful tool for transaction composition, providing numerous features and benefits not available through EOAs. -## Background - -The concept of a proxy contract has gained popularity thanks to DappHub, the team responsible for creating the decentralized stablecoin -[DAI](https://makerdao.com). DappHub created [DSProxy](https://github.com/dapphub/ds-proxy), a widely used tool that allows for the execution of -multiple contract calls in a single transaction. Major DeFi players like Maker, Balancer, and DeFi Saver all rely on DSProxy. - -However, as the Ethereum ecosystem has evolved since DSProxy's launch in 2017, the tool has become outdated. With significant improvements to the -Solidity compiler and new EVM OPCODES, as well as the introduction of more user-friendly development environments like -[Foundry](https://book.getfoundry.sh/), it was time for an update. - -Enter PRBProxy, the modern successor to DSProxy; a "DSProxy 2.0", if you will. It improves upon DSProxy in several ways: - -1. PRBProxy is deployed with [CREATE2][eip-1014], which allows clients to pre-compute the proxy contract's address. -2. The `CREATE2` salts are generated in a way that eliminates the risk of front-running. -3. The proxy owner is immutable, and so it cannot be changed during any `DELEGATECALL`. -4. PRBProxy uses high-level Solidity code that is easier to comprehend and less prone to errors. -5. PRBProxy offers more features than DSProxy. - -Using CREATE2 eliminates the risk of a [chain reorg](https://en.bitcoin.it/wiki/Chain_Reorganization) overriding the proxy contract owner, making -PRBProxy a more secure alternative to DSProxy. With DSProxy, users must wait for several blocks to be mined before assuming the contract is secure. -However, PRBProxy eliminates this risk entirely, allowing users to even safely send funds to the proxy before it is deployed. - ## Install ### Foundry @@ -81,67 +59,65 @@ PRBProxy is available as an npm package: pnpm add @prb/proxy ``` -## Usage - -There are multiple ways to deploy a proxy: - -- Call the `deploy` function. -- Call the `deployFor` function, which accepts the owner as an argument. -- Call the `deployAndExecute` function, which deploys the proxy and executes a delegate call to a target contract in a single transaction. +## Background -Once the proxy is deployed, you can start interacting with target contracts by ABI-encoding the target's functions and pass the data to the `execute` -function on the proxy. +The concept of a forwarding proxy has gained popularity thanks to DappHub, the developer team behind the decentralized stablecoin +[DAI](https://makerdao.com). DappHub created [DSProxy](https://github.com/dapphub/ds-proxy), a widely used tool that allows for the execution of +multiple contract calls in a single transaction. Major DeFi players like Maker, Balancer, and DeFi Saver all rely on DSProxy. -### Addresses +However, as the Ethereum ecosystem has evolved since DSProxy's launch in 2017, the tool has become outdated. With significant improvements to the +Solidity compiler and new EVM OPCODES, as well as the introduction of more user-friendly development environments like +[Foundry](https://book.getfoundry.sh/), it was time for an update. -The registry and the enshrined target are deployed at the same address on the following chains: +Enter PRBProxy, the modern successor to DSProxy; a "DSProxy 2.0", if you will. It improves upon DSProxy in several ways: -| Contract | Chain | [Chain ID](https://chainlist.org/) | Address | -| -------- | ----------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -| Registry | Ethereum Goerli Testnet | 5 | [0xa87bc4C1Bc54E1C1B28d2dD942A094A6B665B8C9](https://goerli.etherscan.io/address/0xa87bc4C1Bc54E1C1B28d2dD942A094A6B665B8C9#code) | +1. PRBProxy is deployed with [CREATE2][eip-1014], which allows clients to pre-compute the proxy contract's address. +2. The `CREATE2` salts are generated in a way that eliminates the risk of front-running. +3. The proxy owner is immutable, and so it cannot be changed during any `DELEGATECALL`. +4. PRBProxy uses high-level Solidity code that is easier to comprehend and less prone to errors. +5. PRBProxy offers more features than DSProxy. -### Targets +Using CREATE2 eliminates the risk of a [chain reorg](https://en.bitcoin.it/wiki/Chain_Reorganization) overriding the proxy contract owner, making +PRBProxy a more secure alternative to DSProxy. With DSProxy, users must wait for several blocks to be mined before assuming the contract is secure. +However, PRBProxy eliminates this risk entirely, making it possible to safely send funds to the proxy before it is deployed. -To make use of PRBProxy, you need a so-called "target". Target contract consist of stateless scripts and are the key to leveraging PRBProxy for -transaction composition. +## Usage -As an example, here's a target contract that wraps ETH into WETH (the ERC-20 version of ETH) and deposits the resulting WETH into a DeFi protocol -called Acme: +There are multiple ways to deploy a proxy: -```solidity -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.18 <=0.9.0; +| Function | Description | +| ---------------------------- | -------------------------------------------------------------------------------------------------------- | +| `deploy` | Deploy a proxy for `msg.sender` | +| `deployFor` | Deploy a proxy for the provided `owner` | +| `deployAndExecute` | Deploy a proxy for `msg.sender`, and delegate calls to the provided target | +| `deployAndInstallPlugin` | Deploy a proxy for `msg.sender`, and installs the provided plugin | +| `deployAndExecuteAndInstall` | Deploy a proxy for `msg.sender`, delegate calls to the provided target, and installs the provided plugin | -interface AcmeLike { - function depositCollateral(address token, uint256 collateralAmount); -} +Once the proxy is deployed, you can start interacting with target contracts by calling the `execute` function on the proxy by passing the ABI-encoding +function signatures and data. -interface WethLike { - function deposit() external payable; -} +### Documentation -function wrapEthAndDepositCollateral(AcmeLike acme) external payable override { - uint256 depositAmount = msg.value; +See this repository's [wiki](https://github.com/PaulRBerg/prb-proxy/wiki) page for guidance on how to write plugins, targets, and front-end +integrations. - // Convert the received ETH to WETH. - WethLike weth = WethLike(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); - weth.deposit{ value: depositAmount }(); +### Addresses - // Deposit the WETH as collateral into the Acme DeFi protocol. - acme.depositCollateral(address(weth), depositAmount); -} -``` +The registry is deployed on the following chain: -For more examples of target contracts, see the [Targets][targets] wiki. +| Contract | Chain | [Chain ID](https://chainlist.org/) | Address | +| ---------------- | -------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| PRBProxyRegistry | Goerli Testnet | 5 | [0x33e200B5fb5e0C57d370d5202c26A35d07A46B98](https://goerli.etherscan.io/address/0x33e200B5fb5e0C57d370d5202c26A35d07A46B98#code) | ### Frontends -Integrating PRBProxy into a frontend app is a straightforward process: +Integrating PRBProxy into a frontend app would look something like this: -1. Begin by calling the `getCurrentProxy` function on the registry to determine if the user already has a proxy. -2. If the user does not have a proxy, ask them to deploy one by calling either the `deploy` or `deployFor` function. +1. Begin by calling the `getProxy` function on the registry to determine if the user already has a proxy. +2. If the user does not have a proxy, deploy one for them using one of the deploy methods outlined above. 3. Interact with your desired target contract using the `execute` function. -4. Going forward, treat the proxy address as the user of your system. +4. Install relevant plugins, which can make the proxy react to your protocol events. +5. Going forward, treat the proxy address as the user of your system. However, this is just scratching the surface. For more examples of how to use PRBProxy in a frontend environment, check out the [Frontends][frontends] wiki. Additionally, Maker's developer guide, [Working with DSProxy][dsproxy-guide], provides an in-depth exploration of the proxy concept that can @@ -149,10 +125,10 @@ also help you understand how to use PRBProxy. Just be sure to keep in mind the d ## Gas Efficiency -It costs 528,529 gas to deploy a PRBProxy, whereas a DSProxy costs 596,198 gas - a reduction in deployment costs of roughly 12%. +It costs ~528,529 gas to deploy a PRBProxy, whereas a DSProxy costs 596,198 gas - a reduction in deployment costs of roughly 12%. The `execute` function in PRBProxy is slightly more expensive than in its counterpart, due to the safety checks in our implementation. However, the -majority of gas costs when calling execute are instead related to the logic being executed in the target contract. +majority of gas cost when calling `execute` is due to the target contract. ## Contributing @@ -210,7 +186,6 @@ If you discover any bugs or security issues, please report them via [Telegram](h ## Acknowledgments - [ds-proxy](https://github.com/dapphub/ds-proxy) - DappHub's proxy, which powers the Maker protocol. -- [wand](https://github.com/nmushegian/wand) - attempt to build DSProxy 2.0, started by one of the original authors of DSProxy. - [dsa-contracts](https://github.com/Instadapp/dsa-contracts) - InstaDapp's DeFi Smart Accounts. ## License @@ -221,7 +196,6 @@ This project is licensed under MIT. [eip-1014]: https://eips.ethereum.org/EIPS/eip-1014 [frontends]: https://github.com/PaulRBerg/prb-proxy/wiki/Frontends -[targets]: https://github.com/PaulRBerg/prb-proxy/wiki/Targets [se-3667]: https://ethereum.stackexchange.com/questions/3667/difference-between-call-callcode-and-delegatecall/3672 [dsproxy-guide]: https://github.com/makerdao/developerguides/blob/9ded1b68228e6cd70885f1326349c6bf087b9573/devtools/working-with-dsproxy/working-with-dsproxy.md diff --git a/package.json b/package.json index 943eeb0..fa9f73c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@prb/proxy", "description": "Proxy contract to compose Ethereum transactions on behalf of the owner", - "version": "4.0.0-beta.5", + "version": "4.0.0-beta.6", "author": { "name": "Paul Razvan Berg", "url": "https://github.com/PaulRBerg" diff --git a/src/PRBProxyRegistry.sol b/src/PRBProxyRegistry.sol index 4755f49..32d3c01 100644 --- a/src/PRBProxyRegistry.sol +++ b/src/PRBProxyRegistry.sol @@ -32,7 +32,7 @@ contract PRBProxyRegistry is IPRBProxyRegistry { //////////////////////////////////////////////////////////////////////////*/ /// @inheritdoc IPRBProxyRegistry - string public constant override VERSION = "4.0.0-beta.5"; + string public constant override VERSION = "4.0.0-beta.6"; /*////////////////////////////////////////////////////////////////////////// USER-FACING STORAGE diff --git a/test/registry/version/version.t.sol b/test/registry/version/version.t.sol index 3619b63..c406972 100644 --- a/test/registry/version/version.t.sol +++ b/test/registry/version/version.t.sol @@ -6,7 +6,7 @@ import { Registry_Test } from "../Registry.t.sol"; contract Version_Test is Registry_Test { function test_Version() external { string memory actualVersion = registry.VERSION(); - string memory expectedVersion = "4.0.0-beta.5"; + string memory expectedVersion = "4.0.0-beta.6"; assertEq(actualVersion, expectedVersion, "registry version mismatch"); } } diff --git a/test/utils/Precompiles.sol b/test/utils/Precompiles.sol index de44671..6c9ea24 100644 --- a/test/utils/Precompiles.sol +++ b/test/utils/Precompiles.sol @@ -12,7 +12,7 @@ contract Precompiles { //////////////////////////////////////////////////////////////////////////*/ bytes public constant BYTECODE_REGISTRY = - hex"6080806040523461001657612801908161001c8239f35b600080fdfe60806040818152600491823610156200001757600080fd5b60009260e08435811c928363092af8131462001215575082631ddef5b914620011625782634bddd93a1462000e125782635cabcdf71462000d4d57826361be48591462000cf15782636383afb21462000b5357826366b0182d1462000a4c57826374912cd214620009bf578263775c300c14620009375782639d1bd1591462000865578263aa4b826a1462000782578263b31d1b991462000718578263b7fba4d314620006d8578263b96784031462000674578263fa557e93146200044557508163fb4a4d08146200014c575063ffa1ad7414620000f457600080fd5b34620001485781600319360112620001485780516200014491620001188262001420565b600c82526b342e302e302d626574612e3560a01b6020830152519182916020835260208301906200145e565b0390f35b5080fd5b83833462000148576020928360031936011262000441576200016d620012bc565b908251906200017c8262001404565b8482528351868101906001600160601b03193360601b16825260148152620001a48162001420565b519051908781106200042f575b509082858051620001c281620013d2565b338152888a82015201526001600160601b0360a01b9233848854161787556001928484541684558151926001600160401b038085116200041c57600294808c6200020d885462001395565b968d601f988a8a8211620003d4575b5050508d828985116001146200036057509262000354575b5050600019600383901b1c191690871b1785555b8851916109f190818401928484109084111762000341575090829162001df08339039089f58015620003375787620002e9969594938893829360018060a01b03169a8b96818055556200029c825462001395565b9081620002ef575b50505050338152600689522091825416179055825184815233907f2d8895d948115783fa362a57339c4c179365fafeafdd7dca66364ae296f50b75873392a362001a20565b51908152f35b80849183116001146200030b57505050555b808a8080620002a4565b6200032f90600080516020620027e18339815191529492930160051c840162001536565b555562000301565b86513d89823e3d90fd5b634e487b7160e01b8c526041905260248bfd5b015190508d8062000234565b8a82528b9550600080516020620027e1833981519152939291601f198616915b828210620003ba5750508411620003a0575b505050811b01855562000248565b015160001960f88460031b161c191690558d808062000392565b8484015186558d9790950194938401939081019062000380565b620004099252600080516020620027e18339815191528a80870160051c82019286881062000412575b0160051c019062001571565b8d388a6200021c565b92508192620003fd565b634e487b7160e01b8a526041825260248afd5b60001990880360031b1b1687620001b1565b8280fd5b848434620001485780600319360112620001485762000463620012bc565b926200046e620012d8565b60018060a01b03809516845260209460038652838520911684528452818320908251809486845492838152019381528681205b8260078301106200060557928792620005119592620001449989965493838310620005e7575b50828210620005c8575b828210620005a9575b8282106200058a575b8282106200056b575b8282106200054e575b82821062000531575b50106200051c575b50905003836200143c565b51918291826200134e565b6001600160e01b031916815201808762000506565b83811b6001600160e01b03191685529093019260010184620004fe565b83891b6001600160e01b03191685529093019260010184620004f5565b606084901b6001600160e01b03191685529093019260010184620004ec565b608084901b6001600160e01b03191685529093019260010184620004e3565b60a084901b6001600160e01b03191685529093019260010184620004da565b60c084901b6001600160e01b03191685529093019260010184620004d1565b84901b6001600160e01b031916855290930192600101848b620004c7565b80546001600160e01b031981861b8116875260c082811b82168b89015260a083811b83168a8a0152608084811b84166060808c019190915285901b8416908a0152838a1b831690890152828b1b82169088015216858501526101009094019360089190910190600101620004a1565b5090503462000441576020366003190112620004415762000694620012bc565b3384526006602052828420549092906001600160a01b031615620006c15783620006be8462001a20565b80f35b60249250519063963e961b60e01b82523390820152fd5b505050346200014857602036600319011262000148576020916001600160a01b039082908262000707620012bc565b168152600685522054169051908152f35b509050346200044157606036600319011262000441578160209360ff926200073f620012bc565b62000749620012d8565b62000753620012ef565b6001600160a01b0392831685529288528484209082168452875283832091168252855220549151911615158152f35b50905034620004415760603660031901126200044157620007a2620012bc565b91620007ad620012d8565b906044358015158091036200086157338652600660209081528287205490946001600160a01b03918216156200084a57907f4f2bd80fb4928b06abcd76e3b26209a615f0612f98dc4a8b176934b1a3899333939291338952865280838920971696878952865280838920951694858952865282882060ff1981541660ff84161790553388526006865282882054169482519485528401523392a480f35b60249084519063963e961b60e01b82523390820152fd5b8580fd5b5083833462000148576060366003190112620001485762000885620012bc565b926024356001600160401b038111620009335790620008a983923690830162001306565b9091620008b5620012ef565b3387526006602052949095205493946001600160a01b03948516908162000907575050602095620008f16200090093620008f9933691620014c1565b90336200182d565b9362001a20565b5191168152f35b84516356352f0b60e11b8152339181019182526001600160a01b03909216602082015281906040010390fd5b8380fd5b5090503462000441578260031936011262000441573383526006602052818320546001600160a01b03919082169081620009935750506200098b602093835190620009828262001404565b8152336200158a565b915191168152f35b83516356352f0b60e11b8152339181019182526001600160a01b03909216602082015281906040010390fd5b50905034620004415760203660031901126200044157620009df620012bc565b9260018060a01b0391828516825260066020528284832054168062000a1d57505082516020946200098b9262000a158362001404565b82526200158a565b84516356352f0b60e11b81526001600160a01b0380881693820193845290911660208301529081906040010390fd5b50505034620001485781600319360112620001485760018060a01b039182815416916001938454169381519280916002549162000a898362001395565b8087529282811690811562000b24575060011462000ad5575b505050829162000abb620001449460609303846200143c565b80519586958652602086015284015260608301906200145e565b925060028352600080516020620027e18339815191525b82841062000b0b5750505082016020018162000abb6200014462000aa2565b8054602085880181019190915290930192810162000aec565b60ff191660208089019190915293151560051b8701909301935084925062000abb915062000144905062000aa2565b83859134620004415781600319360112620004415762000b72620012bc565b62000b7c620012d8565b8351638da5cb5b60e01b815260209691926001600160a01b03928891839190829086165afa90811562000ce757908291879162000cb3575b5016855260038652838520911684528452818320908251809486845492838152019381528681205b82600783011062000c4457928792620005119592620001449989965493838310620005e75750828210620005c857828210620005a9578282106200058a578282106200056b578282106200054e57828210620005315750106200051c5750905003836200143c565b80546001600160e01b031981861b8116875260c082811b82168b89015260a083811b83168a8a0152608084811b84166060808c019190915285901b8416908a0152838a1b831690890152828b1b8216908801521685850152610100909401936008919091019060010162000bdc565b62000cd89150883d8a1162000cdf575b62000ccf81836200143c565b810190620014a0565b8862000bb4565b503d62000cc3565b85513d88823e3d90fd5b5050503462000148578060031936011262000148576020918162000d14620012bc565b9162000d1f62001336565b6001600160a01b039384168252600586528282206001600160e01b0319909116825285522054915191168152f35b5082843462000e0f57606036600319011262000e0f5762000d6d620012bc565b62000d77620012d8565b9062000d82620012ef565b91845195638da5cb5b60e01b87526020968781838160018060a01b038098165afa90811562000e055791848896949288969460ff999162000de3575b5016855288528185852091168452875283832091168252855220541690519015158152f35b62000dfe91508b3d8d1162000cdf5762000ccf81836200143c565b8b62000dbe565b87513d88823e3d90fd5b80fd5b90929150346200093357602092836003193601126200115e5762000e35620012bc565b338652600685528386205490946001600160a01b039290918316156200114757338752600382528285882096169586885282528487209385519083829687928282549586815201918c52828c20948c5b8b826007830110620010cc57508462000eed975493838310620010ae575b508282106200108f575b82821062001070575b82821062001051575b82821062001032575b82821062001015575b82821062000ff8575b501062000fe2575b50905003856200143c565b835190811562000fcb5750865b81811062000f8a5750509060067f0971095f3fa0f917fd0ad98319d7cdb8e837d8c98d5e47fb2700e8b68ac961c99233885260038152858820878952815285882080548982558062000f68575b505033885252838620541692518062000f623394826200134e565b0390a480f35b62000f82918a526007838b20910160031c81019062001571565b388062000f47565b33885260058352858820600191906001600160e01b031962000fad83896200150b565b51168a52845286892080546001600160a01b03191690550162000efa565b85516338d4b05760e01b8152908101879052602490fd5b6001600160e01b03191681528591013862000ee2565b83811b6001600160e01b0319168552909301926001018462000eda565b838d1b6001600160e01b0319168552909301926001018462000ed1565b606084901b6001600160e01b0319168552909301926001018462000ec8565b608084901b6001600160e01b0319168552909301926001018462000ebf565b60a084901b6001600160e01b0319168552909301926001018462000eb6565b60c084901b6001600160e01b0319168552909301926001018462000ead565b84901b6001600160e01b031916855290930192600101843862000ea3565b836008949750600193966101009396928a549283809363ffffffff60e01b809681941b16875260c0938383861b1682890152838360a0928282851b16818c0152608083838d606090818484871b169101521b16908c01521b16908801521b169084015216878201520195019101928692899495929562000e85565b60249085519063963e961b60e01b82523390820152fd5b8480fd5b5082843462000e0f578160031936011262000e0f5762001181620012bc565b906200118c62001336565b8351638da5cb5b60e01b81526020956001600160a01b039487918391829088165afa9081156200120b578392918591879591620011e9575b50168252600586528282206001600160e01b0319909116825285522054915191168152f35b620012049150883d8a1162000cdf5762000ccf81836200143c565b88620011c4565b85513d85823e3d90fd5b8285873462000e0f578160031936011262000e0f5762001234620012bc565b92602435946001600160401b0386116200044157620012598495963690840162001306565b338552600660205294909320546001600160a01b0394929085169081620012925750505093620008f16200098b926020963691620014c1565b6356352f0b60e11b8352339083019081526001600160a01b03909116602082015281906040010390fd5b600435906001600160a01b0382168203620012d357565b600080fd5b602435906001600160a01b0382168203620012d357565b604435906001600160a01b0382168203620012d357565b9181601f84011215620012d3578235916001600160401b038311620012d35760208381860195010111620012d357565b602435906001600160e01b031982168203620012d357565b6020908160408183019282815285518094520193019160005b82811062001376575050505090565b83516001600160e01b0319168552938101939281019260010162001367565b90600182811c92168015620013c7575b6020831014620013b157565b634e487b7160e01b600052602260045260246000fd5b91607f1691620013a5565b606081019081106001600160401b03821117620013ee57604052565b634e487b7160e01b600052604160045260246000fd5b602081019081106001600160401b03821117620013ee57604052565b604081019081106001600160401b03821117620013ee57604052565b90601f801991011681019081106001600160401b03821117620013ee57604052565b919082519283825260005b8481106200148b575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520162001469565b90816020910312620012d357516001600160a01b0381168103620012d35790565b9291926001600160401b038211620013ee5760405191620014ed601f8201601f1916602001846200143c565b829481845281830111620012d3578281602093846000960137010152565b8051821015620015205760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b7f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf5b81811062001564575050565b6000815560010162001558565b8181106200157d575050565b6000815560010162001571565b9190604092835193602091828601956001600160601b03198260601b16875260148152620015b88162001420565b5195519583811062001818575b50815193620015d485620013d2565b808360018060a01b038094169687815260008782015201526001600160601b0360a01b918583600054161760005560019783895416895582516001600160401b0390818111620013ee57806002956200162e875462001395565b601f8111620017cc575b508990601f83116001146200174f5760009262001743575b5050600019600383901b1c1916908b1b1784555b8551906109f19081830190811183821017620013ee57829162001df0833903906000f5801562001738577f2d8895d948115783fa362a57339c4c179365fafeafdd7dca66364ae296f50b7594939291600091169881805555620016c8815462001395565b9081620016f0575b5050846000526006845286826000209182541617905551918583523392a3565b81601f600093116001146200170a5750555b3880620016d0565b90829062001730601f600080516020620027e1833981519152940160051c840162001536565b555562001702565b84513d6000823e3d90fd5b01519050388062001650565b908d935087600052600080516020620027e1833981519152916000601f198516905b8d828210620017ac575050841162001792575b505050811b01845562001664565b015160001960f88460031b161c1916905538808062001784565b91929395968291958786015181550195019301908f959493929162001771565b620018069088600052600080516020620027e1833981519152601f850160051c8101918d86106200180d575b601f0160051c019062001571565b3862001638565b9091508190620017f8565b60001990840360031b1b9095169438620015c5565b92916040805191602092838101906001600160601b03198860601b168252601481526200185a8162001420565b5190519084811062001a0e575b50908251966200187788620013d2565b818460018060a01b038080941698898c5216998a8882015201526001600160601b0360a01b9286846000541617600055600198848a541617895582516001600160401b0390818111620013ee5780600295620018d4875462001395565b601f8111620019ce575b508990601f83116001146200196c5760009262001743575050600019600383901b1c1916908b1b1784558551906109f19081830190811183821017620013ee57829162001df0833903906000f5801562001738577f2d8895d948115783fa362a57339c4c179365fafeafdd7dca66364ae296f50b7594939291600091169881805555620016c8815462001395565b908d935087600052600080516020620027e1833981519152916000601f198516905b8d828210620019ae57505084116200179257505050811b01845562001664565b91929395968291958786015181550195019301908f95949392916200198e565b62001a079088600052600080516020620027e1833981519152601f850160051c8101918d86106200180d57601f0160051c019062001571565b38620018de565b60001990850360031b1b163862001867565b60408051631abad16560e21b81526001600160a01b0392831692600490600080848481838a5af193841562001de357819462001d15575b508351801562001cfe57815b81811062001c69575050338152602092600384528582208783528452858220908551906001600160401b03821162001c565768010000000000000000821162001c565750815481835580821062001c03575b50908692918587019183528583208160031c91845b83811062001ba65750600719811690038062001b25575b5050505060067f71b3c95c0b8611d2f0f9c4e492ebbcf20d034943bccac6ef1a71ae90e0f243fa943383525220541692518062001b203394826200134e565b0390a4565b928493855b81811062001b6257505050015560067f71b3c95c0b8611d2f0f9c4e492ebbcf20d034943bccac6ef1a71ae90e0f243fa388062001ae1565b9195979880975062001b93600192949596885160e01c908560021b60031b9163ffffffff809116831b921b19161790565b96019101918a9698979594939262001b2a565b9091929394809650865b896008821062001bd0575050838201558995949392919060010162001aca565b62001bf98893600193995160e01c908a60021b60031b9163ffffffff809116831b921b19161790565b9201960162001bb0565b62001c3490838552868520600780850160031c820192601c8660021b168062001c3b575b500160031c019062001571565b3862001ab5565b60001990818601918254918d0360031b1c1690553862001c27565b634e487b7160e01b845260419052602483fd5b6001600160e01b031962001c7e82886200150b565b511633845260056020908082528986208387528252868a8720541662001cc65733865281528885209185525286832080546001600160a01b0319168917905560010162001a63565b338652815288852082865290528784205488516361a2116b60e11b815290861681880152602481018a90526044810191909152606490fd5b85516362d3093d60e11b8152808501889052602490fd5b9093503d8085833e62001d2981836200143c565b81016020908183820312620008615782516001600160401b039384821162001dc8570181601f8201121562001ddf57805193841162001dcc578360051b9088519462001d78858401876200143c565b8552838086019282010192831162001dc8578301905b82821062001da25750505050923862001a57565b81516001600160e01b03198116810362001dc457815290830190830162001d8e565b8880fd5b8780fd5b634e487b7160e01b875260418652602487fd5b8680fd5b508451903d90823e3d90fdfe60c08060405234620000ca573360a0526366b0182d60e01b8152600081600481335afa8015620000c4576000809281926200009b575b506080526001600160a01b03821662000087575b60405161068e9081620003638239608051818181610192015281816102c401526104a5015260a05181818161014d0152818161031301526105250152f35b6200009291620002b2565b50388062000049565b909150620000bb92503d8092823e620000b482620000e5565b016200018e565b90913862000035565b62000221565b600080fd5b634e487b7160e01b600052604160045260246000fd5b60c0601f91909101601f19168101906001600160401b038211908210176200010c57604052565b620000cf565b601f909101601f19168101906001600160401b038211908210176200010c57604052565b60e051906001600160a01b0382168203620000ca57565b6001600160401b0381116200010c57601f01601f191660200190565b60005b8381106200017d5750506000910152565b81810151838201526020016200016c565b606060bf19820112620000ca5760c0516001600160a01b0381168103620000ca5791620001ba62000136565b610100519092906001600160401b038111620000ca578160df82011215620000ca578060c00151620001ec816200014d565b92620001fc604051948562000112565b81845260e08284010111620000ca576200021e9160e060208501910162000169565b90565b6040513d6000823e3d90fd5b3d156200025d573d9062000241826200014d565b9162000251604051938462000112565b82523d6000602084013e565b606090565b906020916200027d8151809281855285808601910162000169565b601f01601f1916010190565b9091620002a36200021e9360408452604084019062000262565b91602081840391015262000262565b9190823b156200034157600080825160208401865af4907fb24ebe141c5f2a744b103bea65fce6c40e0dc65d7341d092c09b160f40447990620002f46200022d565b60405190956001600160a01b0316928190620003139088908362000289565b0390a2156200031e57565b508051156200032f57602081519101fd5b60405163061a160d60e41b8152600490fd5b604051636d17e5ef60e11b81526001600160a01b0384166004820152602490fdfe60806040526004361015610027575b36156100255761001d366102b5565b602081519101f35b005b6000803560e01c9081631cff79cd1461005a575080637b1039991461005557638da5cb5b0361000e5761017c565b610137565b60403660031901126100ca57600435610072816100cd565b60243567ffffffffffffffff928382116100ca57366023830112156100ca5781600401359384116100ca5736602485840101116100ca576100c66100ba8560248501866104a2565b60405191829182610123565b0390f35b80fd5b6001600160a01b038116036100de57565b600080fd5b919082519283825260005b84811061010f575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016100ee565b9060206101349281815201906100e3565b90565b346100de5760003660031901126100de576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100de5760003660031901126100de576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176101f957604052565b6101c1565b908160209103126100de5751610134816100cd565b6040513d6000823e3d90fd5b908160008237016000815290565b67ffffffffffffffff81116101f957601f01601f191660200190565b3d15610274573d9061025a8261022d565b9161026860405193846101d7565b82523d6000602084013e565b606090565b606090610134939260408252806040830152806000848401376000838284010152601f80199101168101906020838284030191015201906100e3565b6040516361be485960e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0381811660048401526001600160e01b03196000351660248401819052939493906020846044817f000000000000000000000000000000000000000000000000000000000000000085165afa93841561044e5760009461041e575b5083169182156103e357505060008060405180610362818961021f565b0390845af4907fc4dabe0d7ef7462e2218f2c398c21ef217803e1c46f5cf802d1a5d1d9b503f2f610391610249565b80966103a260405192839283610279565b0390a2156103ad5750565b8251909150156103c05750805190602001fd5b60405163023c045d60e21b81526001600160a01b03919091166004820152602490fd5b604051638848730f60e01b81523360048201526001600160a01b039190911660248201526001600160e01b0319919091166044820152606490fd5b61044091945060203d8111610447575b61043881836101d7565b8101906101fe565b9238610345565b503d61042e565b610213565b908160209103126100de575180151581036100de5790565b9291926104778261022d565b9161048560405193846101d7565b8294818452818301116100de578281602093846000960137010152565b917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0333818316036104ee575b505061013492916104e891369161046b565b906105e5565b60405163b31d1b9960e01b81526001600160a01b0383811660048301523360248301528616604482015290602090829060649082907f0000000000000000000000000000000000000000000000000000000000000000165afa90811561044e57600091610592575b501561056257806104d6565b6040516355d1750960e01b81526001600160a01b0391821660048201523360248201529084166044820152606490fd5b6105b3915060203d81116105b9575b6105ab81836101d7565b810190610453565b38610556565b503d6105a1565b90916105d7610134936040845260408401906100e3565b9160208184039101526100e3565b9190823b1561066d57600080825160208401865af4907fb24ebe141c5f2a744b103bea65fce6c40e0dc65d7341d092c09b160f40447990610624610249565b60405190956001600160a01b0316928190610641908890836105c0565b0390a21561064b57565b5080511561065b57602081519101fd5b60405163061a160d60e41b8152600490fd5b604051636d17e5ef60e11b81526001600160a01b0384166004820152602490fd405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"; + hex"6080806040523461001657612801908161001c8239f35b600080fdfe60806040818152600491823610156200001757600080fd5b60009260e08435811c928363092af8131462001215575082631ddef5b914620011625782634bddd93a1462000e125782635cabcdf71462000d4d57826361be48591462000cf15782636383afb21462000b5357826366b0182d1462000a4c57826374912cd214620009bf578263775c300c14620009375782639d1bd1591462000865578263aa4b826a1462000782578263b31d1b991462000718578263b7fba4d314620006d8578263b96784031462000674578263fa557e93146200044557508163fb4a4d08146200014c575063ffa1ad7414620000f457600080fd5b34620001485781600319360112620001485780516200014491620001188262001420565b600c82526b1a1718171816b132ba30971b60a11b6020830152519182916020835260208301906200145e565b0390f35b5080fd5b83833462000148576020928360031936011262000441576200016d620012bc565b908251906200017c8262001404565b8482528351868101906001600160601b03193360601b16825260148152620001a48162001420565b519051908781106200042f575b509082858051620001c281620013d2565b338152888a82015201526001600160601b0360a01b9233848854161787556001928484541684558151926001600160401b038085116200041c57600294808c6200020d885462001395565b968d601f988a8a8211620003d4575b5050508d828985116001146200036057509262000354575b5050600019600383901b1c191690871b1785555b8851916109f190818401928484109084111762000341575090829162001df08339039089f58015620003375787620002e9969594938893829360018060a01b03169a8b96818055556200029c825462001395565b9081620002ef575b50505050338152600689522091825416179055825184815233907f2d8895d948115783fa362a57339c4c179365fafeafdd7dca66364ae296f50b75873392a362001a20565b51908152f35b80849183116001146200030b57505050555b808a8080620002a4565b6200032f90600080516020620027e18339815191529492930160051c840162001536565b555562000301565b86513d89823e3d90fd5b634e487b7160e01b8c526041905260248bfd5b015190508d8062000234565b8a82528b9550600080516020620027e1833981519152939291601f198616915b828210620003ba5750508411620003a0575b505050811b01855562000248565b015160001960f88460031b161c191690558d808062000392565b8484015186558d9790950194938401939081019062000380565b620004099252600080516020620027e18339815191528a80870160051c82019286881062000412575b0160051c019062001571565b8d388a6200021c565b92508192620003fd565b634e487b7160e01b8a526041825260248afd5b60001990880360031b1b1687620001b1565b8280fd5b848434620001485780600319360112620001485762000463620012bc565b926200046e620012d8565b60018060a01b03809516845260209460038652838520911684528452818320908251809486845492838152019381528681205b8260078301106200060557928792620005119592620001449989965493838310620005e7575b50828210620005c8575b828210620005a9575b8282106200058a575b8282106200056b575b8282106200054e575b82821062000531575b50106200051c575b50905003836200143c565b51918291826200134e565b6001600160e01b031916815201808762000506565b83811b6001600160e01b03191685529093019260010184620004fe565b83891b6001600160e01b03191685529093019260010184620004f5565b606084901b6001600160e01b03191685529093019260010184620004ec565b608084901b6001600160e01b03191685529093019260010184620004e3565b60a084901b6001600160e01b03191685529093019260010184620004da565b60c084901b6001600160e01b03191685529093019260010184620004d1565b84901b6001600160e01b031916855290930192600101848b620004c7565b80546001600160e01b031981861b8116875260c082811b82168b89015260a083811b83168a8a0152608084811b84166060808c019190915285901b8416908a0152838a1b831690890152828b1b82169088015216858501526101009094019360089190910190600101620004a1565b5090503462000441576020366003190112620004415762000694620012bc565b3384526006602052828420549092906001600160a01b031615620006c15783620006be8462001a20565b80f35b60249250519063963e961b60e01b82523390820152fd5b505050346200014857602036600319011262000148576020916001600160a01b039082908262000707620012bc565b168152600685522054169051908152f35b509050346200044157606036600319011262000441578160209360ff926200073f620012bc565b62000749620012d8565b62000753620012ef565b6001600160a01b0392831685529288528484209082168452875283832091168252855220549151911615158152f35b50905034620004415760603660031901126200044157620007a2620012bc565b91620007ad620012d8565b906044358015158091036200086157338652600660209081528287205490946001600160a01b03918216156200084a57907f4f2bd80fb4928b06abcd76e3b26209a615f0612f98dc4a8b176934b1a3899333939291338952865280838920971696878952865280838920951694858952865282882060ff1981541660ff84161790553388526006865282882054169482519485528401523392a480f35b60249084519063963e961b60e01b82523390820152fd5b8580fd5b5083833462000148576060366003190112620001485762000885620012bc565b926024356001600160401b038111620009335790620008a983923690830162001306565b9091620008b5620012ef565b3387526006602052949095205493946001600160a01b03948516908162000907575050602095620008f16200090093620008f9933691620014c1565b90336200182d565b9362001a20565b5191168152f35b84516356352f0b60e11b8152339181019182526001600160a01b03909216602082015281906040010390fd5b8380fd5b5090503462000441578260031936011262000441573383526006602052818320546001600160a01b03919082169081620009935750506200098b602093835190620009828262001404565b8152336200158a565b915191168152f35b83516356352f0b60e11b8152339181019182526001600160a01b03909216602082015281906040010390fd5b50905034620004415760203660031901126200044157620009df620012bc565b9260018060a01b0391828516825260066020528284832054168062000a1d57505082516020946200098b9262000a158362001404565b82526200158a565b84516356352f0b60e11b81526001600160a01b0380881693820193845290911660208301529081906040010390fd5b50505034620001485781600319360112620001485760018060a01b039182815416916001938454169381519280916002549162000a898362001395565b8087529282811690811562000b24575060011462000ad5575b505050829162000abb620001449460609303846200143c565b80519586958652602086015284015260608301906200145e565b925060028352600080516020620027e18339815191525b82841062000b0b5750505082016020018162000abb6200014462000aa2565b8054602085880181019190915290930192810162000aec565b60ff191660208089019190915293151560051b8701909301935084925062000abb915062000144905062000aa2565b83859134620004415781600319360112620004415762000b72620012bc565b62000b7c620012d8565b8351638da5cb5b60e01b815260209691926001600160a01b03928891839190829086165afa90811562000ce757908291879162000cb3575b5016855260038652838520911684528452818320908251809486845492838152019381528681205b82600783011062000c4457928792620005119592620001449989965493838310620005e75750828210620005c857828210620005a9578282106200058a578282106200056b578282106200054e57828210620005315750106200051c5750905003836200143c565b80546001600160e01b031981861b8116875260c082811b82168b89015260a083811b83168a8a0152608084811b84166060808c019190915285901b8416908a0152838a1b831690890152828b1b8216908801521685850152610100909401936008919091019060010162000bdc565b62000cd89150883d8a1162000cdf575b62000ccf81836200143c565b810190620014a0565b8862000bb4565b503d62000cc3565b85513d88823e3d90fd5b5050503462000148578060031936011262000148576020918162000d14620012bc565b9162000d1f62001336565b6001600160a01b039384168252600586528282206001600160e01b0319909116825285522054915191168152f35b5082843462000e0f57606036600319011262000e0f5762000d6d620012bc565b62000d77620012d8565b9062000d82620012ef565b91845195638da5cb5b60e01b87526020968781838160018060a01b038098165afa90811562000e055791848896949288969460ff999162000de3575b5016855288528185852091168452875283832091168252855220541690519015158152f35b62000dfe91508b3d8d1162000cdf5762000ccf81836200143c565b8b62000dbe565b87513d88823e3d90fd5b80fd5b90929150346200093357602092836003193601126200115e5762000e35620012bc565b338652600685528386205490946001600160a01b039290918316156200114757338752600382528285882096169586885282528487209385519083829687928282549586815201918c52828c20948c5b8b826007830110620010cc57508462000eed975493838310620010ae575b508282106200108f575b82821062001070575b82821062001051575b82821062001032575b82821062001015575b82821062000ff8575b501062000fe2575b50905003856200143c565b835190811562000fcb5750865b81811062000f8a5750509060067f0971095f3fa0f917fd0ad98319d7cdb8e837d8c98d5e47fb2700e8b68ac961c99233885260038152858820878952815285882080548982558062000f68575b505033885252838620541692518062000f623394826200134e565b0390a480f35b62000f82918a526007838b20910160031c81019062001571565b388062000f47565b33885260058352858820600191906001600160e01b031962000fad83896200150b565b51168a52845286892080546001600160a01b03191690550162000efa565b85516338d4b05760e01b8152908101879052602490fd5b6001600160e01b03191681528591013862000ee2565b83811b6001600160e01b0319168552909301926001018462000eda565b838d1b6001600160e01b0319168552909301926001018462000ed1565b606084901b6001600160e01b0319168552909301926001018462000ec8565b608084901b6001600160e01b0319168552909301926001018462000ebf565b60a084901b6001600160e01b0319168552909301926001018462000eb6565b60c084901b6001600160e01b0319168552909301926001018462000ead565b84901b6001600160e01b031916855290930192600101843862000ea3565b836008949750600193966101009396928a549283809363ffffffff60e01b809681941b16875260c0938383861b1682890152838360a0928282851b16818c0152608083838d606090818484871b169101521b16908c01521b16908801521b169084015216878201520195019101928692899495929562000e85565b60249085519063963e961b60e01b82523390820152fd5b8480fd5b5082843462000e0f578160031936011262000e0f5762001181620012bc565b906200118c62001336565b8351638da5cb5b60e01b81526020956001600160a01b039487918391829088165afa9081156200120b578392918591879591620011e9575b50168252600586528282206001600160e01b0319909116825285522054915191168152f35b620012049150883d8a1162000cdf5762000ccf81836200143c565b88620011c4565b85513d85823e3d90fd5b8285873462000e0f578160031936011262000e0f5762001234620012bc565b92602435946001600160401b0386116200044157620012598495963690840162001306565b338552600660205294909320546001600160a01b0394929085169081620012925750505093620008f16200098b926020963691620014c1565b6356352f0b60e11b8352339083019081526001600160a01b03909116602082015281906040010390fd5b600435906001600160a01b0382168203620012d357565b600080fd5b602435906001600160a01b0382168203620012d357565b604435906001600160a01b0382168203620012d357565b9181601f84011215620012d3578235916001600160401b038311620012d35760208381860195010111620012d357565b602435906001600160e01b031982168203620012d357565b6020908160408183019282815285518094520193019160005b82811062001376575050505090565b83516001600160e01b0319168552938101939281019260010162001367565b90600182811c92168015620013c7575b6020831014620013b157565b634e487b7160e01b600052602260045260246000fd5b91607f1691620013a5565b606081019081106001600160401b03821117620013ee57604052565b634e487b7160e01b600052604160045260246000fd5b602081019081106001600160401b03821117620013ee57604052565b604081019081106001600160401b03821117620013ee57604052565b90601f801991011681019081106001600160401b03821117620013ee57604052565b919082519283825260005b8481106200148b575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520162001469565b90816020910312620012d357516001600160a01b0381168103620012d35790565b9291926001600160401b038211620013ee5760405191620014ed601f8201601f1916602001846200143c565b829481845281830111620012d3578281602093846000960137010152565b8051821015620015205760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b7f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf5b81811062001564575050565b6000815560010162001558565b8181106200157d575050565b6000815560010162001571565b9190604092835193602091828601956001600160601b03198260601b16875260148152620015b88162001420565b5195519583811062001818575b50815193620015d485620013d2565b808360018060a01b038094169687815260008782015201526001600160601b0360a01b918583600054161760005560019783895416895582516001600160401b0390818111620013ee57806002956200162e875462001395565b601f8111620017cc575b508990601f83116001146200174f5760009262001743575b5050600019600383901b1c1916908b1b1784555b8551906109f19081830190811183821017620013ee57829162001df0833903906000f5801562001738577f2d8895d948115783fa362a57339c4c179365fafeafdd7dca66364ae296f50b7594939291600091169881805555620016c8815462001395565b9081620016f0575b5050846000526006845286826000209182541617905551918583523392a3565b81601f600093116001146200170a5750555b3880620016d0565b90829062001730601f600080516020620027e1833981519152940160051c840162001536565b555562001702565b84513d6000823e3d90fd5b01519050388062001650565b908d935087600052600080516020620027e1833981519152916000601f198516905b8d828210620017ac575050841162001792575b505050811b01845562001664565b015160001960f88460031b161c1916905538808062001784565b91929395968291958786015181550195019301908f959493929162001771565b620018069088600052600080516020620027e1833981519152601f850160051c8101918d86106200180d575b601f0160051c019062001571565b3862001638565b9091508190620017f8565b60001990840360031b1b9095169438620015c5565b92916040805191602092838101906001600160601b03198860601b168252601481526200185a8162001420565b5190519084811062001a0e575b50908251966200187788620013d2565b818460018060a01b038080941698898c5216998a8882015201526001600160601b0360a01b9286846000541617600055600198848a541617895582516001600160401b0390818111620013ee5780600295620018d4875462001395565b601f8111620019ce575b508990601f83116001146200196c5760009262001743575050600019600383901b1c1916908b1b1784558551906109f19081830190811183821017620013ee57829162001df0833903906000f5801562001738577f2d8895d948115783fa362a57339c4c179365fafeafdd7dca66364ae296f50b7594939291600091169881805555620016c8815462001395565b908d935087600052600080516020620027e1833981519152916000601f198516905b8d828210620019ae57505084116200179257505050811b01845562001664565b91929395968291958786015181550195019301908f95949392916200198e565b62001a079088600052600080516020620027e1833981519152601f850160051c8101918d86106200180d57601f0160051c019062001571565b38620018de565b60001990850360031b1b163862001867565b60408051631abad16560e21b81526001600160a01b0392831692600490600080848481838a5af193841562001de357819462001d15575b508351801562001cfe57815b81811062001c69575050338152602092600384528582208783528452858220908551906001600160401b03821162001c565768010000000000000000821162001c565750815481835580821062001c03575b50908692918587019183528583208160031c91845b83811062001ba65750600719811690038062001b25575b5050505060067f71b3c95c0b8611d2f0f9c4e492ebbcf20d034943bccac6ef1a71ae90e0f243fa943383525220541692518062001b203394826200134e565b0390a4565b928493855b81811062001b6257505050015560067f71b3c95c0b8611d2f0f9c4e492ebbcf20d034943bccac6ef1a71ae90e0f243fa388062001ae1565b9195979880975062001b93600192949596885160e01c908560021b60031b9163ffffffff809116831b921b19161790565b96019101918a9698979594939262001b2a565b9091929394809650865b896008821062001bd0575050838201558995949392919060010162001aca565b62001bf98893600193995160e01c908a60021b60031b9163ffffffff809116831b921b19161790565b9201960162001bb0565b62001c3490838552868520600780850160031c820192601c8660021b168062001c3b575b500160031c019062001571565b3862001ab5565b60001990818601918254918d0360031b1c1690553862001c27565b634e487b7160e01b845260419052602483fd5b6001600160e01b031962001c7e82886200150b565b511633845260056020908082528986208387528252868a8720541662001cc65733865281528885209185525286832080546001600160a01b0319168917905560010162001a63565b338652815288852082865290528784205488516361a2116b60e11b815290861681880152602481018a90526044810191909152606490fd5b85516362d3093d60e11b8152808501889052602490fd5b9093503d8085833e62001d2981836200143c565b81016020908183820312620008615782516001600160401b039384821162001dc8570181601f8201121562001ddf57805193841162001dcc578360051b9088519462001d78858401876200143c565b8552838086019282010192831162001dc8578301905b82821062001da25750505050923862001a57565b81516001600160e01b03198116810362001dc457815290830190830162001d8e565b8880fd5b8780fd5b634e487b7160e01b875260418652602487fd5b8680fd5b508451903d90823e3d90fdfe60c08060405234620000ca573360a0526366b0182d60e01b8152600081600481335afa8015620000c4576000809281926200009b575b506080526001600160a01b03821662000087575b60405161068e9081620003638239608051818181610192015281816102c401526104a5015260a05181818161014d0152818161031301526105250152f35b6200009291620002b2565b50388062000049565b909150620000bb92503d8092823e620000b482620000e5565b016200018e565b90913862000035565b62000221565b600080fd5b634e487b7160e01b600052604160045260246000fd5b60c0601f91909101601f19168101906001600160401b038211908210176200010c57604052565b620000cf565b601f909101601f19168101906001600160401b038211908210176200010c57604052565b60e051906001600160a01b0382168203620000ca57565b6001600160401b0381116200010c57601f01601f191660200190565b60005b8381106200017d5750506000910152565b81810151838201526020016200016c565b606060bf19820112620000ca5760c0516001600160a01b0381168103620000ca5791620001ba62000136565b610100519092906001600160401b038111620000ca578160df82011215620000ca578060c00151620001ec816200014d565b92620001fc604051948562000112565b81845260e08284010111620000ca576200021e9160e060208501910162000169565b90565b6040513d6000823e3d90fd5b3d156200025d573d9062000241826200014d565b9162000251604051938462000112565b82523d6000602084013e565b606090565b906020916200027d8151809281855285808601910162000169565b601f01601f1916010190565b9091620002a36200021e9360408452604084019062000262565b91602081840391015262000262565b9190823b156200034157600080825160208401865af4907fb24ebe141c5f2a744b103bea65fce6c40e0dc65d7341d092c09b160f40447990620002f46200022d565b60405190956001600160a01b0316928190620003139088908362000289565b0390a2156200031e57565b508051156200032f57602081519101fd5b60405163061a160d60e41b8152600490fd5b604051636d17e5ef60e11b81526001600160a01b0384166004820152602490fdfe60806040526004361015610027575b36156100255761001d366102b5565b602081519101f35b005b6000803560e01c9081631cff79cd1461005a575080637b1039991461005557638da5cb5b0361000e5761017c565b610137565b60403660031901126100ca57600435610072816100cd565b60243567ffffffffffffffff928382116100ca57366023830112156100ca5781600401359384116100ca5736602485840101116100ca576100c66100ba8560248501866104a2565b60405191829182610123565b0390f35b80fd5b6001600160a01b038116036100de57565b600080fd5b919082519283825260005b84811061010f575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016100ee565b9060206101349281815201906100e3565b90565b346100de5760003660031901126100de576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346100de5760003660031901126100de576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176101f957604052565b6101c1565b908160209103126100de5751610134816100cd565b6040513d6000823e3d90fd5b908160008237016000815290565b67ffffffffffffffff81116101f957601f01601f191660200190565b3d15610274573d9061025a8261022d565b9161026860405193846101d7565b82523d6000602084013e565b606090565b606090610134939260408252806040830152806000848401376000838284010152601f80199101168101906020838284030191015201906100e3565b6040516361be485960e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0381811660048401526001600160e01b03196000351660248401819052939493906020846044817f000000000000000000000000000000000000000000000000000000000000000085165afa93841561044e5760009461041e575b5083169182156103e357505060008060405180610362818961021f565b0390845af4907fc4dabe0d7ef7462e2218f2c398c21ef217803e1c46f5cf802d1a5d1d9b503f2f610391610249565b80966103a260405192839283610279565b0390a2156103ad5750565b8251909150156103c05750805190602001fd5b60405163023c045d60e21b81526001600160a01b03919091166004820152602490fd5b604051638848730f60e01b81523360048201526001600160a01b039190911660248201526001600160e01b0319919091166044820152606490fd5b61044091945060203d8111610447575b61043881836101d7565b8101906101fe565b9238610345565b503d61042e565b610213565b908160209103126100de575180151581036100de5790565b9291926104778261022d565b9161048560405193846101d7565b8294818452818301116100de578281602093846000960137010152565b917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0333818316036104ee575b505061013492916104e891369161046b565b906105e5565b60405163b31d1b9960e01b81526001600160a01b0383811660048301523360248301528616604482015290602090829060649082907f0000000000000000000000000000000000000000000000000000000000000000165afa90811561044e57600091610592575b501561056257806104d6565b6040516355d1750960e01b81526001600160a01b0391821660048201523360248201529084166044820152606490fd5b6105b3915060203d81116105b9575b6105ab81836101d7565b810190610453565b38610556565b503d6105a1565b90916105d7610134936040845260408401906100e3565b9160208184039101526100e3565b9190823b1561066d57600080825160208401865af4907fb24ebe141c5f2a744b103bea65fce6c40e0dc65d7341d092c09b160f40447990610624610249565b60405190956001600160a01b0316928190610641908890836105c0565b0390a21561064b57565b5080511561065b57602081519101fd5b60405163061a160d60e41b8152600490fd5b604051636d17e5ef60e11b81526001600160a01b0384166004820152602490fd405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"; /*////////////////////////////////////////////////////////////////////////// DEPLOYERS