Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 2 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6819675 | 56 days ago | Contract Creation | 0 ETH | |||
6819675 | 56 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
TransparentUpgradeableProxy
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 1 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/TransparentUpgradeableProxy.sol) pragma solidity ^0.8.20; import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol"; import {ERC1967Proxy} from "../ERC1967/ERC1967Proxy.sol"; import {IERC1967} from "../../interfaces/IERC1967.sol"; import {ProxyAdmin} from "./ProxyAdmin.sol"; /** * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy} * does not implement this interface directly, and its upgradeability mechanism is implemented by an internal dispatch * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not * include them in the ABI so this interface must be used to interact with it. */ interface ITransparentUpgradeableProxy is IERC1967 { function upgradeToAndCall(address, bytes calldata) external payable; } /** * @dev This contract implements a proxy that is upgradeable through an associated {ProxyAdmin} instance. * * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector * clashing], which can potentially be used in an attack, this contract uses the * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two * things that go hand in hand: * * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if * that call matches the {ITransparentUpgradeableProxy-upgradeToAndCall} function exposed by the proxy itself. * 2. If the admin calls the proxy, it can call the `upgradeToAndCall` function but any other call won't be forwarded to * the implementation. If the admin tries to call a function on the implementation it will fail with an error indicating * the proxy admin cannot fallback to the target implementation. * * These properties mean that the admin account can only be used for upgrading the proxy, so it's best if it's a * dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to * call a function from the proxy implementation. For this reason, the proxy deploys an instance of {ProxyAdmin} and * allows upgrades only if they come through it. You should think of the `ProxyAdmin` instance as the administrative * interface of the proxy, including the ability to change who can trigger upgrades by transferring ownership. * * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not * inherit from that interface, and instead `upgradeToAndCall` is implicitly implemented using a custom dispatch * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the * implementation. * * NOTE: This proxy does not inherit from {Context} deliberately. The {ProxyAdmin} of this contract won't send a * meta-transaction in any way, and any other meta-transaction setup should be made in the implementation contract. * * IMPORTANT: This contract avoids unnecessary storage reads by setting the admin only during construction as an * immutable variable, preventing any changes thereafter. However, the admin slot defined in ERC-1967 can still be * overwritten by the implementation logic pointed to by this proxy. In such cases, the contract may end up in an * undesirable state where the admin slot is different from the actual admin. * * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the * compiler will not check that there are no selector conflicts, due to the note above. A selector clash between any new * function and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This * could render the `upgradeToAndCall` function inaccessible, preventing upgradeability and compromising transparency. */ contract TransparentUpgradeableProxy is ERC1967Proxy { // An immutable address for the admin to avoid unnecessary SLOADs before each call // at the expense of removing the ability to change the admin once it's set. // This is acceptable if the admin is always a ProxyAdmin instance or similar contract // with its own ability to transfer the permissions to another account. address private immutable _admin; /** * @dev The proxy caller is the current admin, and can't fallback to the proxy target. */ error ProxyDeniedAdminAccess(); /** * @dev Initializes an upgradeable proxy managed by an instance of a {ProxyAdmin} with an `initialOwner`, * backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in * {ERC1967Proxy-constructor}. */ constructor(address _logic, address initialOwner, bytes memory _data) payable ERC1967Proxy(_logic, _data) { _admin = address(new ProxyAdmin(initialOwner)); // Set the storage value and emit an event for ERC-1967 compatibility ERC1967Utils.changeAdmin(_proxyAdmin()); } /** * @dev Returns the admin of this proxy. */ function _proxyAdmin() internal virtual returns (address) { return _admin; } /** * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior. */ function _fallback() internal virtual override { if (msg.sender == _proxyAdmin()) { if (msg.sig != ITransparentUpgradeableProxy.upgradeToAndCall.selector) { revert ProxyDeniedAdminAccess(); } else { _dispatchUpgradeToAndCall(); } } else { super._fallback(); } } /** * @dev Upgrade the implementation of the proxy. See {ERC1967Utils-upgradeToAndCall}. * * Requirements: * * - If `data` is empty, `msg.value` must be zero. */ function _dispatchUpgradeToAndCall() private { (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes)); ERC1967Utils.upgradeToAndCall(newImplementation, data); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; import {StdStorage} from "./StdStorage.sol"; import {Vm, VmSafe} from "./Vm.sol"; abstract contract CommonBase { // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D. address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); // console.sol and console2.sol work by executing a staticcall to this address. address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67; // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38. address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller")))); // Address of the test contract, deployed by the DEFAULT_SENDER. address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f; // Deterministic deployment address of the Multicall3 contract. address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11; // The order of the secp256k1 curve. uint256 internal constant SECP256K1_ORDER = 115792089237316195423570985008687907852837564279074904382605163141518161494337; uint256 internal constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; Vm internal constant vm = Vm(VM_ADDRESS); StdStorage internal stdstore; } abstract contract TestBase is CommonBase {} abstract contract ScriptBase is CommonBase { VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; // 💬 ABOUT // Forge Std's default Script. // 🧩 MODULES import {console} from "./console.sol"; import {console2} from "./console2.sol"; import {safeconsole} from "./safeconsole.sol"; import {StdChains} from "./StdChains.sol"; import {StdCheatsSafe} from "./StdCheats.sol"; import {stdJson} from "./StdJson.sol"; import {stdMath} from "./StdMath.sol"; import {StdStorage, stdStorageSafe} from "./StdStorage.sol"; import {StdStyle} from "./StdStyle.sol"; import {StdUtils} from "./StdUtils.sol"; import {VmSafe} from "./Vm.sol"; // 📦 BOILERPLATE import {ScriptBase} from "./Base.sol"; // ⭐️ SCRIPT abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils { // Note: IS_SCRIPT() must return true. bool public IS_SCRIPT = true; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; import {VmSafe} from "./Vm.sol"; /** * StdChains provides information about EVM compatible chains that can be used in scripts/tests. * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the * alias used in this contract, which can be found as the first argument to the * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function. * * There are two main ways to use this contract: * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or * `setChain(string memory chainAlias, Chain memory chain)` * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`. * * The first time either of those are used, chains are initialized with the default set of RPC URLs. * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in * `defaultRpcUrls`. * * The `setChain` function is straightforward, and it simply saves off the given chain data. * * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say * we want to retrieve the RPC URL for `mainnet`: * - If you have specified data with `setChain`, it will return that. * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it * is valid (e.g. a URL is specified, or an environment variable is given and exists). * - If neither of the above conditions is met, the default data is returned. * * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults. */ abstract contract StdChains { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); bool private stdChainsInitialized; struct ChainData { string name; uint256 chainId; string rpcUrl; } struct Chain { // The chain name. string name; // The chain's Chain ID. uint256 chainId; // The chain's alias. (i.e. what gets specified in `foundry.toml`). string chainAlias; // A default RPC endpoint for this chain. // NOTE: This default RPC URL is included for convenience to facilitate quick tests and // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy // usage as you will be throttled and this is a disservice to others who need this endpoint. string rpcUrl; } // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data. mapping(string => Chain) private chains; // Maps from the chain's alias to it's default RPC URL. mapping(string => string) private defaultRpcUrls; // Maps from a chain ID to it's alias. mapping(uint256 => string) private idToAlias; bool private fallbackToDefaultRpcUrls = true; // The RPC URL will be fetched from config or defaultRpcUrls if possible. function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) { require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string."); initializeStdChains(); chain = chains[chainAlias]; require( chain.chainId != 0, string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found.")) ); chain = getChainWithUpdatedRpcUrl(chainAlias, chain); } function getChain(uint256 chainId) internal virtual returns (Chain memory chain) { require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0."); initializeStdChains(); string memory chainAlias = idToAlias[chainId]; chain = chains[chainAlias]; require( chain.chainId != 0, string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found.")) ); chain = getChainWithUpdatedRpcUrl(chainAlias, chain); } // set chain info, with priority to argument's rpcUrl field. function setChain(string memory chainAlias, ChainData memory chain) internal virtual { require( bytes(chainAlias).length != 0, "StdChains setChain(string,ChainData): Chain alias cannot be the empty string." ); require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0."); initializeStdChains(); string memory foundAlias = idToAlias[chain.chainId]; require( bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)), string( abi.encodePacked( "StdChains setChain(string,ChainData): Chain ID ", vm.toString(chain.chainId), " already used by \"", foundAlias, "\"." ) ) ); uint256 oldChainId = chains[chainAlias].chainId; delete idToAlias[oldChainId]; chains[chainAlias] = Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl}); idToAlias[chain.chainId] = chainAlias; } // set chain info, with priority to argument's rpcUrl field. function setChain(string memory chainAlias, Chain memory chain) internal virtual { setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl})); } function _toUpper(string memory str) private pure returns (string memory) { bytes memory strb = bytes(str); bytes memory copy = new bytes(strb.length); for (uint256 i = 0; i < strb.length; i++) { bytes1 b = strb[i]; if (b >= 0x61 && b <= 0x7A) { copy[i] = bytes1(uint8(b) - 32); } else { copy[i] = b; } } return string(copy); } // lookup rpcUrl, in descending order of priority: // current -> config (foundry.toml) -> environment variable -> default function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) private view returns (Chain memory) { if (bytes(chain.rpcUrl).length == 0) { try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) { chain.rpcUrl = configRpcUrl; } catch (bytes memory err) { string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL")); if (fallbackToDefaultRpcUrls) { chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]); } else { chain.rpcUrl = vm.envString(envName); } // Distinguish 'not found' from 'cannot read' // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions bytes memory oldNotFoundError = abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias))); bytes memory newNotFoundError = abi.encodeWithSignature( "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias)) ); bytes32 errHash = keccak256(err); if ( (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError)) || bytes(chain.rpcUrl).length == 0 ) { /// @solidity memory-safe-assembly assembly { revert(add(32, err), mload(err)) } } } } return chain; } function setFallbackToDefaultRpcUrls(bool useDefault) internal { fallbackToDefaultRpcUrls = useDefault; } function initializeStdChains() private { if (stdChainsInitialized) return; stdChainsInitialized = true; // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol` setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545")); setChainWithDefaultRpcUrl( "mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP") ); setChainWithDefaultRpcUrl( "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001") ); setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io")); setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io")); setChainWithDefaultRpcUrl( "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io") ); setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc")); setChainWithDefaultRpcUrl( "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc") ); setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc")); setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com")); setChainWithDefaultRpcUrl( "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology") ); setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc")); setChainWithDefaultRpcUrl( "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc") ); setChainWithDefaultRpcUrl( "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org") ); setChainWithDefaultRpcUrl( "bnb_smart_chain_testnet", ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel") ); setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com")); setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network")); setChainWithDefaultRpcUrl( "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network") ); setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network")); setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org")); setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org")); setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io")); setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io")); setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/")); setChainWithDefaultRpcUrl( "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/") ); setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com")); setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com")); setChainWithDefaultRpcUrl( "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com") ); setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc")); setChainWithDefaultRpcUrl( "flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc") ); } // set chain info, with priority to chainAlias' rpc url in foundry.toml function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private { string memory rpcUrl = chain.rpcUrl; defaultRpcUrls[chainAlias] = rpcUrl; chain.rpcUrl = ""; setChain(chainAlias, chain); chain.rpcUrl = rpcUrl; // restore argument } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; pragma experimental ABIEncoderV2; import {StdStorage, stdStorage} from "./StdStorage.sol"; import {console2} from "./console2.sol"; import {Vm} from "./Vm.sol"; abstract contract StdCheatsSafe { Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); uint256 private constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; bool private gasMeteringOff; // Data structures to parse Transaction objects from the broadcast artifact // that conform to EIP1559. The Raw structs is what is parsed from the JSON // and then converted to the one that is used by the user for better UX. struct RawTx1559 { string[] arguments; address contractAddress; string contractName; // json value name = function string functionSig; bytes32 hash; // json value name = tx RawTx1559Detail txDetail; // json value name = type string opcode; } struct RawTx1559Detail { AccessList[] accessList; bytes data; address from; bytes gas; bytes nonce; address to; bytes txType; bytes value; } struct Tx1559 { string[] arguments; address contractAddress; string contractName; string functionSig; bytes32 hash; Tx1559Detail txDetail; string opcode; } struct Tx1559Detail { AccessList[] accessList; bytes data; address from; uint256 gas; uint256 nonce; address to; uint256 txType; uint256 value; } // Data structures to parse Transaction objects from the broadcast artifact // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON // and then converted to the one that is used by the user for better UX. struct TxLegacy { string[] arguments; address contractAddress; string contractName; string functionSig; string hash; string opcode; TxDetailLegacy transaction; } struct TxDetailLegacy { AccessList[] accessList; uint256 chainId; bytes data; address from; uint256 gas; uint256 gasPrice; bytes32 hash; uint256 nonce; bytes1 opcode; bytes32 r; bytes32 s; uint256 txType; address to; uint8 v; uint256 value; } struct AccessList { address accessAddress; bytes32[] storageKeys; } // Data structures to parse Receipt objects from the broadcast artifact. // The Raw structs is what is parsed from the JSON // and then converted to the one that is used by the user for better UX. struct RawReceipt { bytes32 blockHash; bytes blockNumber; address contractAddress; bytes cumulativeGasUsed; bytes effectiveGasPrice; address from; bytes gasUsed; RawReceiptLog[] logs; bytes logsBloom; bytes status; address to; bytes32 transactionHash; bytes transactionIndex; } struct Receipt { bytes32 blockHash; uint256 blockNumber; address contractAddress; uint256 cumulativeGasUsed; uint256 effectiveGasPrice; address from; uint256 gasUsed; ReceiptLog[] logs; bytes logsBloom; uint256 status; address to; bytes32 transactionHash; uint256 transactionIndex; } // Data structures to parse the entire broadcast artifact, assuming the // transactions conform to EIP1559. struct EIP1559ScriptArtifact { string[] libraries; string path; string[] pending; Receipt[] receipts; uint256 timestamp; Tx1559[] transactions; TxReturn[] txReturns; } struct RawEIP1559ScriptArtifact { string[] libraries; string path; string[] pending; RawReceipt[] receipts; TxReturn[] txReturns; uint256 timestamp; RawTx1559[] transactions; } struct RawReceiptLog { // json value = address address logAddress; bytes32 blockHash; bytes blockNumber; bytes data; bytes logIndex; bool removed; bytes32[] topics; bytes32 transactionHash; bytes transactionIndex; bytes transactionLogIndex; } struct ReceiptLog { // json value = address address logAddress; bytes32 blockHash; uint256 blockNumber; bytes data; uint256 logIndex; bytes32[] topics; uint256 transactionIndex; uint256 transactionLogIndex; bool removed; } struct TxReturn { string internalType; string value; } struct Account { address addr; uint256 key; } enum AddressType { Payable, NonPayable, ZeroAddress, Precompile, ForgeAddress } // Checks that `addr` is not blacklisted by token contracts that have a blacklist. function assumeNotBlacklisted(address token, address addr) internal view virtual { // Nothing to check if `token` is not a contract. uint256 tokenCodeSize; assembly { tokenCodeSize := extcodesize(token) } require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract."); bool success; bytes memory returnData; // 4-byte selector for `isBlacklisted(address)`, used by USDC. (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr)); vm.assume(!success || abi.decode(returnData, (bool)) == false); // 4-byte selector for `isBlackListed(address)`, used by USDT. (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr)); vm.assume(!success || abi.decode(returnData, (bool)) == false); } // Checks that `addr` is not blacklisted by token contracts that have a blacklist. // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for // backwards compatibility, since this name was used in the original PR which already has // a release. This function can be removed in a future release once we want a breaking change. function assumeNoBlacklisted(address token, address addr) internal view virtual { assumeNotBlacklisted(token, addr); } function assumeAddressIsNot(address addr, AddressType addressType) internal virtual { if (addressType == AddressType.Payable) { assumeNotPayable(addr); } else if (addressType == AddressType.NonPayable) { assumePayable(addr); } else if (addressType == AddressType.ZeroAddress) { assumeNotZeroAddress(addr); } else if (addressType == AddressType.Precompile) { assumeNotPrecompile(addr); } else if (addressType == AddressType.ForgeAddress) { assumeNotForgeAddress(addr); } } function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual { assumeAddressIsNot(addr, addressType1); assumeAddressIsNot(addr, addressType2); } function assumeAddressIsNot( address addr, AddressType addressType1, AddressType addressType2, AddressType addressType3 ) internal virtual { assumeAddressIsNot(addr, addressType1); assumeAddressIsNot(addr, addressType2); assumeAddressIsNot(addr, addressType3); } function assumeAddressIsNot( address addr, AddressType addressType1, AddressType addressType2, AddressType addressType3, AddressType addressType4 ) internal virtual { assumeAddressIsNot(addr, addressType1); assumeAddressIsNot(addr, addressType2); assumeAddressIsNot(addr, addressType3); assumeAddressIsNot(addr, addressType4); } // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to // `addr` and checking the `success` return value. // NOTE: This function may result in state changes depending on the fallback/receive logic // implemented by `addr`, which should be taken into account when this function is used. function _isPayable(address addr) private returns (bool) { require( addr.balance < UINT256_MAX, "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds" ); uint256 origBalanceTest = address(this).balance; uint256 origBalanceAddr = address(addr).balance; vm.deal(address(this), 1); (bool success,) = payable(addr).call{value: 1}(""); // reset balances vm.deal(address(this), origBalanceTest); vm.deal(addr, origBalanceAddr); return success; } // NOTE: This function may result in state changes depending on the fallback/receive logic // implemented by `addr`, which should be taken into account when this function is used. See the // `_isPayable` method for more information. function assumePayable(address addr) internal virtual { vm.assume(_isPayable(addr)); } function assumeNotPayable(address addr) internal virtual { vm.assume(!_isPayable(addr)); } function assumeNotZeroAddress(address addr) internal pure virtual { vm.assume(addr != address(0)); } function assumeNotPrecompile(address addr) internal pure virtual { assumeNotPrecompile(addr, _pureChainId()); } function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual { // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific // address), but the same rationale for excluding them applies so we include those too. // These are reserved by Ethereum and may be on all EVM-compatible chains. vm.assume(addr < address(0x1) || addr > address(0xff)); // forgefmt: disable-start if (chainId == 10 || chainId == 420) { // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21 vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800)); } else if (chainId == 42161 || chainId == 421613) { // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068)); } else if (chainId == 43114 || chainId == 43113) { // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59 vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff)); vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF)); vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff)); } // forgefmt: disable-end } function assumeNotForgeAddress(address addr) internal pure virtual { // vm, console, and Create2Deployer addresses vm.assume( addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67 && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C ); } function readEIP1559ScriptArtifact(string memory path) internal view virtual returns (EIP1559ScriptArtifact memory) { string memory data = vm.readFile(path); bytes memory parsedData = vm.parseJson(data); RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact)); EIP1559ScriptArtifact memory artifact; artifact.libraries = rawArtifact.libraries; artifact.path = rawArtifact.path; artifact.timestamp = rawArtifact.timestamp; artifact.pending = rawArtifact.pending; artifact.txReturns = rawArtifact.txReturns; artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts); artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions); return artifact; } function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) { Tx1559[] memory txs = new Tx1559[](rawTxs.length); for (uint256 i; i < rawTxs.length; i++) { txs[i] = rawToConvertedEIPTx1559(rawTxs[i]); } return txs; } function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) { Tx1559 memory transaction; transaction.arguments = rawTx.arguments; transaction.contractName = rawTx.contractName; transaction.functionSig = rawTx.functionSig; transaction.hash = rawTx.hash; transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail); transaction.opcode = rawTx.opcode; return transaction; } function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail) internal pure virtual returns (Tx1559Detail memory) { Tx1559Detail memory txDetail; txDetail.data = rawDetail.data; txDetail.from = rawDetail.from; txDetail.to = rawDetail.to; txDetail.nonce = _bytesToUint(rawDetail.nonce); txDetail.txType = _bytesToUint(rawDetail.txType); txDetail.value = _bytesToUint(rawDetail.value); txDetail.gas = _bytesToUint(rawDetail.gas); txDetail.accessList = rawDetail.accessList; return txDetail; } function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) { string memory deployData = vm.readFile(path); bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions"); RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[])); return rawToConvertedEIPTx1559s(rawTxs); } function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) { string memory deployData = vm.readFile(path); string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]")); bytes memory parsedDeployData = vm.parseJson(deployData, key); RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559)); return rawToConvertedEIPTx1559(rawTx); } // Analogous to readTransactions, but for receipts. function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) { string memory deployData = vm.readFile(path); bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts"); RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[])); return rawToConvertedReceipts(rawReceipts); } function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) { string memory deployData = vm.readFile(path); string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]")); bytes memory parsedDeployData = vm.parseJson(deployData, key); RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt)); return rawToConvertedReceipt(rawReceipt); } function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) { Receipt[] memory receipts = new Receipt[](rawReceipts.length); for (uint256 i; i < rawReceipts.length; i++) { receipts[i] = rawToConvertedReceipt(rawReceipts[i]); } return receipts; } function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) { Receipt memory receipt; receipt.blockHash = rawReceipt.blockHash; receipt.to = rawReceipt.to; receipt.from = rawReceipt.from; receipt.contractAddress = rawReceipt.contractAddress; receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice); receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed); receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed); receipt.status = _bytesToUint(rawReceipt.status); receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex); receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber); receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs); receipt.logsBloom = rawReceipt.logsBloom; receipt.transactionHash = rawReceipt.transactionHash; return receipt; } function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs) internal pure virtual returns (ReceiptLog[] memory) { ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length); for (uint256 i; i < rawLogs.length; i++) { logs[i].logAddress = rawLogs[i].logAddress; logs[i].blockHash = rawLogs[i].blockHash; logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber); logs[i].data = rawLogs[i].data; logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex); logs[i].topics = rawLogs[i].topics; logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex); logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex); logs[i].removed = rawLogs[i].removed; } return logs; } // Deploy a contract by fetching the contract bytecode from // the artifacts directory // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))` function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) { bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); /// @solidity memory-safe-assembly assembly { addr := create(0, add(bytecode, 0x20), mload(bytecode)) } require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed."); } function deployCode(string memory what) internal virtual returns (address addr) { bytes memory bytecode = vm.getCode(what); /// @solidity memory-safe-assembly assembly { addr := create(0, add(bytecode, 0x20), mload(bytecode)) } require(addr != address(0), "StdCheats deployCode(string): Deployment failed."); } /// @dev deploy contract with value on construction function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) { bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); /// @solidity memory-safe-assembly assembly { addr := create(val, add(bytecode, 0x20), mload(bytecode)) } require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed."); } function deployCode(string memory what, uint256 val) internal virtual returns (address addr) { bytes memory bytecode = vm.getCode(what); /// @solidity memory-safe-assembly assembly { addr := create(val, add(bytecode, 0x20), mload(bytecode)) } require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed."); } // creates a labeled address and the corresponding private key function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) { privateKey = uint256(keccak256(abi.encodePacked(name))); addr = vm.addr(privateKey); vm.label(addr, name); } // creates a labeled address function makeAddr(string memory name) internal virtual returns (address addr) { (addr,) = makeAddrAndKey(name); } // Destroys an account immediately, sending the balance to beneficiary. // Destroying means: balance will be zero, code will be empty, and nonce will be 0 // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce // only after tx ends, this will run immediately. function destroyAccount(address who, address beneficiary) internal virtual { uint256 currBalance = who.balance; vm.etch(who, abi.encode()); vm.deal(who, 0); vm.resetNonce(who); uint256 beneficiaryBalance = beneficiary.balance; vm.deal(beneficiary, currBalance + beneficiaryBalance); } // creates a struct containing both a labeled address and the corresponding private key function makeAccount(string memory name) internal virtual returns (Account memory account) { (account.addr, account.key) = makeAddrAndKey(name); } function deriveRememberKey(string memory mnemonic, uint32 index) internal virtual returns (address who, uint256 privateKey) { privateKey = vm.deriveKey(mnemonic, index); who = vm.rememberKey(privateKey); } function _bytesToUint(bytes memory b) private pure returns (uint256) { require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32."); return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); } function isFork() internal view virtual returns (bool status) { try vm.activeFork() { status = true; } catch (bytes memory) {} } modifier skipWhenForking() { if (!isFork()) { _; } } modifier skipWhenNotForking() { if (isFork()) { _; } } modifier noGasMetering() { vm.pauseGasMetering(); // To prevent turning gas monitoring back on with nested functions that use this modifier, // we check if gasMetering started in the off position. If it did, we don't want to turn // it back on until we exit the top level function that used the modifier // // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well. // funcA will have `gasStartedOff` as false, funcB will have it as true, // so we only turn metering back on at the end of the funcA bool gasStartedOff = gasMeteringOff; gasMeteringOff = true; _; // if gas metering was on when this modifier was called, turn it back on at the end if (!gasStartedOff) { gasMeteringOff = false; vm.resumeGasMetering(); } } // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We // can't simply access the chain ID in a normal view or pure function because the solc View Pure // Checker changed `chainid` from pure to view in 0.8.0. function _viewChainId() private view returns (uint256 chainId) { // Assembly required since `block.chainid` was introduced in 0.8.0. assembly { chainId := chainid() } address(this); // Silence warnings in older Solc versions. } function _pureChainId() private pure returns (uint256 chainId) { function() internal view returns (uint256) fnIn = _viewChainId; function() internal pure returns (uint256) pureChainId; assembly { pureChainId := fnIn } chainId = pureChainId(); } } // Wrappers around cheatcodes to avoid footguns abstract contract StdCheats is StdCheatsSafe { using stdStorage for StdStorage; StdStorage private stdstore; Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; // Skip forward or rewind time by the specified number of seconds function skip(uint256 time) internal virtual { vm.warp(block.timestamp + time); } function rewind(uint256 time) internal virtual { vm.warp(block.timestamp - time); } // Setup a prank from an address that has some ether function hoax(address msgSender) internal virtual { vm.deal(msgSender, 1 << 128); vm.prank(msgSender); } function hoax(address msgSender, uint256 give) internal virtual { vm.deal(msgSender, give); vm.prank(msgSender); } function hoax(address msgSender, address origin) internal virtual { vm.deal(msgSender, 1 << 128); vm.prank(msgSender, origin); } function hoax(address msgSender, address origin, uint256 give) internal virtual { vm.deal(msgSender, give); vm.prank(msgSender, origin); } // Start perpetual prank from an address that has some ether function startHoax(address msgSender) internal virtual { vm.deal(msgSender, 1 << 128); vm.startPrank(msgSender); } function startHoax(address msgSender, uint256 give) internal virtual { vm.deal(msgSender, give); vm.startPrank(msgSender); } // Start perpetual prank from an address that has some ether // tx.origin is set to the origin parameter function startHoax(address msgSender, address origin) internal virtual { vm.deal(msgSender, 1 << 128); vm.startPrank(msgSender, origin); } function startHoax(address msgSender, address origin, uint256 give) internal virtual { vm.deal(msgSender, give); vm.startPrank(msgSender, origin); } function changePrank(address msgSender) internal virtual { console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); vm.stopPrank(); vm.startPrank(msgSender); } function changePrank(address msgSender, address txOrigin) internal virtual { vm.stopPrank(); vm.startPrank(msgSender, txOrigin); } // The same as Vm's `deal` // Use the alternative signature for ERC20 tokens function deal(address to, uint256 give) internal virtual { vm.deal(to, give); } // Set the balance of an account for any ERC20 token // Use the alternative signature to update `totalSupply` function deal(address token, address to, uint256 give) internal virtual { deal(token, to, give, false); } // Set the balance of an account for any ERC1155 token // Use the alternative signature to update `totalSupply` function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual { dealERC1155(token, to, id, give, false); } function deal(address token, address to, uint256 give, bool adjust) internal virtual { // get current balance (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); uint256 prevBal = abi.decode(balData, (uint256)); // update balance stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give); // update total supply if (adjust) { (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd)); uint256 totSup = abi.decode(totSupData, (uint256)); if (give < prevBal) { totSup -= (prevBal - give); } else { totSup += (give - prevBal); } stdstore.target(token).sig(0x18160ddd).checked_write(totSup); } } function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual { // get current balance (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id)); uint256 prevBal = abi.decode(balData, (uint256)); // update balance stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give); // update total supply if (adjust) { (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id)); require( totSupData.length != 0, "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply." ); uint256 totSup = abi.decode(totSupData, (uint256)); if (give < prevBal) { totSup -= (prevBal - give); } else { totSup += (give - prevBal); } stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup); } } function dealERC721(address token, address to, uint256 id) internal virtual { // check if token id is already minted and the actual owner. (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id)); require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted."); // get owner current balance (, bytes memory fromBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address)))); uint256 fromPrevBal = abi.decode(fromBalData, (uint256)); // get new user current balance (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); uint256 toPrevBal = abi.decode(toBalData, (uint256)); // update balances stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal); stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal); // update owner stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to); } function deployCodeTo(string memory what, address where) internal virtual { deployCodeTo(what, "", 0, where); } function deployCodeTo(string memory what, bytes memory args, address where) internal virtual { deployCodeTo(what, args, 0, where); } function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual { bytes memory creationCode = vm.getCode(what); vm.etch(where, abi.encodePacked(creationCode, args)); (bool success, bytes memory runtimeBytecode) = where.call{value: value}(""); require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode."); vm.etch(where, runtimeBytecode); } // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere. function console2_log_StdCheats(string memory p0) private view { (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0)); status; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.9.0; pragma experimental ABIEncoderV2; import {VmSafe} from "./Vm.sol"; // Helpers for parsing and writing JSON files // To parse: // ``` // using stdJson for string; // string memory json = vm.readFile("<some_path>"); // json.readUint("<json_path>"); // ``` // To write: // ``` // using stdJson for string; // string memory json = "json"; // json.serialize("a", uint256(123)); // string memory semiFinal = json.serialize("b", string("test")); // string memory finalJson = json.serialize("c", semiFinal); // finalJson.write("<some_path>"); // ``` library stdJson { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); function keyExists(string memory json, string memory key) internal view returns (bool) { return vm.keyExistsJson(json, key); } function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { return vm.parseJson(json, key); } function readUint(string memory json, string memory key) internal pure returns (uint256) { return vm.parseJsonUint(json, key); } function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) { return vm.parseJsonUintArray(json, key); } function readInt(string memory json, string memory key) internal pure returns (int256) { return vm.parseJsonInt(json, key); } function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) { return vm.parseJsonIntArray(json, key); } function readBytes32(string memory json, string memory key) internal pure returns (bytes32) { return vm.parseJsonBytes32(json, key); } function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) { return vm.parseJsonBytes32Array(json, key); } function readString(string memory json, string memory key) internal pure returns (string memory) { return vm.parseJsonString(json, key); } function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) { return vm.parseJsonStringArray(json, key); } function readAddress(string memory json, string memory key) internal pure returns (address) { return vm.parseJsonAddress(json, key); } function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) { return vm.parseJsonAddressArray(json, key); } function readBool(string memory json, string memory key) internal pure returns (bool) { return vm.parseJsonBool(json, key); } function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) { return vm.parseJsonBoolArray(json, key); } function readBytes(string memory json, string memory key) internal pure returns (bytes memory) { return vm.parseJsonBytes(json, key); } function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) { return vm.parseJsonBytesArray(json, key); } function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) { return keyExists(json, key) ? readUint(json, key) : defaultValue; } function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue) internal view returns (uint256[] memory) { return keyExists(json, key) ? readUintArray(json, key) : defaultValue; } function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) { return keyExists(json, key) ? readInt(json, key) : defaultValue; } function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue) internal view returns (int256[] memory) { return keyExists(json, key) ? readIntArray(json, key) : defaultValue; } function readBytes32Or(string memory json, string memory key, bytes32 defaultValue) internal view returns (bytes32) { return keyExists(json, key) ? readBytes32(json, key) : defaultValue; } function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue) internal view returns (bytes32[] memory) { return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue; } function readStringOr(string memory json, string memory key, string memory defaultValue) internal view returns (string memory) { return keyExists(json, key) ? readString(json, key) : defaultValue; } function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue) internal view returns (string[] memory) { return keyExists(json, key) ? readStringArray(json, key) : defaultValue; } function readAddressOr(string memory json, string memory key, address defaultValue) internal view returns (address) { return keyExists(json, key) ? readAddress(json, key) : defaultValue; } function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue) internal view returns (address[] memory) { return keyExists(json, key) ? readAddressArray(json, key) : defaultValue; } function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) { return keyExists(json, key) ? readBool(json, key) : defaultValue; } function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue) internal view returns (bool[] memory) { return keyExists(json, key) ? readBoolArray(json, key) : defaultValue; } function readBytesOr(string memory json, string memory key, bytes memory defaultValue) internal view returns (bytes memory) { return keyExists(json, key) ? readBytes(json, key) : defaultValue; } function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue) internal view returns (bytes[] memory) { return keyExists(json, key) ? readBytesArray(json, key) : defaultValue; } function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { return vm.serializeJson(jsonKey, rootObject); } function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, bool[] memory value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { return vm.serializeUint(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, uint256[] memory value) internal returns (string memory) { return vm.serializeUint(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { return vm.serializeInt(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, int256[] memory value) internal returns (string memory) { return vm.serializeInt(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { return vm.serializeAddress(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, address[] memory value) internal returns (string memory) { return vm.serializeAddress(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { return vm.serializeBytes32(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, bytes32[] memory value) internal returns (string memory) { return vm.serializeBytes32(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { return vm.serializeBytes(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, bytes[] memory value) internal returns (string memory) { return vm.serializeBytes(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, string memory value) internal returns (string memory) { return vm.serializeString(jsonKey, key, value); } function serialize(string memory jsonKey, string memory key, string[] memory value) internal returns (string memory) { return vm.serializeString(jsonKey, key, value); } function write(string memory jsonKey, string memory path) internal { vm.writeJson(jsonKey, path); } function write(string memory jsonKey, string memory path, string memory valueKey) internal { vm.writeJson(jsonKey, path, valueKey); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; library stdMath { int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968; function abs(int256 a) internal pure returns (uint256) { // Required or it will fail when `a = type(int256).min` if (a == INT256_MIN) { return 57896044618658097711785492504343953926634992332820282019728792003956564819968; } return uint256(a > 0 ? a : -a); } function delta(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a - b : b - a; } function delta(int256 a, int256 b) internal pure returns (uint256) { // a and b are of the same sign // this works thanks to two's complement, the left-most bit is the sign bit if ((a ^ b) > -1) { return delta(abs(a), abs(b)); } // a and b are of opposite signs return abs(a) + abs(b); } function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) { uint256 absDelta = delta(a, b); return absDelta * 1e18 / b; } function percentDelta(int256 a, int256 b) internal pure returns (uint256) { uint256 absDelta = delta(a, b); uint256 absB = abs(b); return absDelta * 1e18 / absB; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; import {Vm} from "./Vm.sol"; struct FindData { uint256 slot; uint256 offsetLeft; uint256 offsetRight; bool found; } struct StdStorage { mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds; bytes32[] _keys; bytes4 _sig; uint256 _depth; address _target; bytes32 _set; bool _enable_packed_slots; bytes _calldata; } library stdStorageSafe { event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot); event WARNING_UninitedSlot(address who, uint256 slot); Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; function sigs(string memory sigStr) internal pure returns (bytes4) { return bytes4(keccak256(bytes(sigStr))); } function getCallParams(StdStorage storage self) internal view returns (bytes memory) { if (self._calldata.length == 0) { return flatten(self._keys); } else { return self._calldata; } } // Calls target contract with configured parameters function callTarget(StdStorage storage self) internal view returns (bool, bytes32) { bytes memory cald = abi.encodePacked(self._sig, getCallParams(self)); (bool success, bytes memory rdat) = self._target.staticcall(cald); bytes32 result = bytesToBytes32(rdat, 32 * self._depth); return (success, result); } // Tries mutating slot value to determine if the targeted value is stored in it. // If current value is 0, then we are setting slot value to type(uint256).max // Otherwise, we set it to 0. That way, return value should always be affected. function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) { bytes32 prevSlotValue = vm.load(self._target, slot); (bool success, bytes32 prevReturnValue) = callTarget(self); bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0); vm.store(self._target, slot, testVal); (, bytes32 newReturnValue) = callTarget(self); vm.store(self._target, slot, prevSlotValue); return (success && (prevReturnValue != newReturnValue)); } // Tries setting one of the bits in slot to 1 until return value changes. // Index of resulted bit is an offset packed slot has from left/right side function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) { for (uint256 offset = 0; offset < 256; offset++) { uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset); vm.store(self._target, slot, bytes32(valueToPut)); (bool success, bytes32 data) = callTarget(self); if (success && (uint256(data) > 0)) { return (true, offset); } } return (false, 0); } function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) { bytes32 prevSlotValue = vm.load(self._target, slot); (bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true); (bool foundRight, uint256 offsetRight) = findOffset(self, slot, false); // `findOffset` may mutate slot value, so we are setting it to initial value vm.store(self._target, slot, prevSlotValue); return (foundLeft && foundRight, offsetLeft, offsetRight); } function find(StdStorage storage self) internal returns (FindData storage) { return find(self, true); } /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against // slot complexity: // if flat, will be bytes32(uint256(uint)); // if map, will be keccak256(abi.encode(key, uint(slot))); // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot))))); // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth); function find(StdStorage storage self, bool _clear) internal returns (FindData storage) { address who = self._target; bytes4 fsig = self._sig; uint256 field_depth = self._depth; bytes memory params = getCallParams(self); // calldata to test against if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { if (_clear) { clear(self); } return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; } vm.record(); (, bytes32 callResult) = callTarget(self); (bytes32[] memory reads,) = vm.accesses(address(who)); if (reads.length == 0) { revert("stdStorage find(StdStorage): No storage use detected for target."); } else { for (uint256 i = reads.length; --i >= 0;) { bytes32 prev = vm.load(who, reads[i]); if (prev == bytes32(0)) { emit WARNING_UninitedSlot(who, uint256(reads[i])); } if (!checkSlotMutatesCall(self, reads[i])) { continue; } (uint256 offsetLeft, uint256 offsetRight) = (0, 0); if (self._enable_packed_slots) { bool found; (found, offsetLeft, offsetRight) = findOffsets(self, reads[i]); if (!found) { continue; } } // Check that value between found offsets is equal to the current call result uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight; if (uint256(callResult) != curVal) { continue; } emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i])); self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] = FindData(uint256(reads[i]), offsetLeft, offsetRight, true); break; } } require( self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found, "stdStorage find(StdStorage): Slot(s) not found." ); if (_clear) { clear(self); } return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; } function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { self._target = _target; return self; } function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { self._sig = _sig; return self; } function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { self._sig = sigs(_sig); return self; } function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { self._calldata = _calldata; return self; } function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { self._keys.push(bytes32(uint256(uint160(who)))); return self; } function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { self._keys.push(bytes32(amt)); return self; } function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { self._keys.push(key); return self; } function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { self._enable_packed_slots = true; return self; } function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { self._depth = _depth; return self; } function read(StdStorage storage self) private returns (bytes memory) { FindData storage data = find(self, false); uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight); uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight; clear(self); return abi.encode(value); } function read_bytes32(StdStorage storage self) internal returns (bytes32) { return abi.decode(read(self), (bytes32)); } function read_bool(StdStorage storage self) internal returns (bool) { int256 v = read_int(self); if (v == 0) return false; if (v == 1) return true; revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool."); } function read_address(StdStorage storage self) internal returns (address) { return abi.decode(read(self), (address)); } function read_uint(StdStorage storage self) internal returns (uint256) { return abi.decode(read(self), (uint256)); } function read_int(StdStorage storage self) internal returns (int256) { return abi.decode(read(self), (int256)); } function parent(StdStorage storage self) internal returns (uint256, bytes32) { address who = self._target; uint256 field_depth = self._depth; vm.startMappingRecording(); uint256 child = find(self, true).slot - field_depth; (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); if (!found) { revert( "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." ); } return (uint256(parent_slot), key); } function root(StdStorage storage self) internal returns (uint256) { address who = self._target; uint256 field_depth = self._depth; vm.startMappingRecording(); uint256 child = find(self, true).slot - field_depth; bool found; bytes32 root_slot; bytes32 parent_slot; (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); if (!found) { revert( "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." ); } while (found) { root_slot = parent_slot; (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot)); } return uint256(root_slot); } function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) { bytes32 out; uint256 max = b.length > 32 ? 32 : b.length; for (uint256 i = 0; i < max; i++) { out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); } return out; } function flatten(bytes32[] memory b) private pure returns (bytes memory) { bytes memory result = new bytes(b.length * 32); for (uint256 i = 0; i < b.length; i++) { bytes32 k = b[i]; /// @solidity memory-safe-assembly assembly { mstore(add(result, add(32, mul(32, i))), k) } } return result; } function clear(StdStorage storage self) internal { delete self._target; delete self._sig; delete self._keys; delete self._depth; delete self._enable_packed_slots; delete self._calldata; } // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight` // (slotValue & mask) >> offsetRight will be the value of the given packed variable function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) { // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight; // using assembly because (1 << 256) causes overflow assembly { mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1)) } } // Returns slot value with updated packed variable. function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight) internal pure returns (bytes32 newValue) { return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight)); } } library stdStorage { Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); function sigs(string memory sigStr) internal pure returns (bytes4) { return stdStorageSafe.sigs(sigStr); } function find(StdStorage storage self) internal returns (uint256) { return find(self, true); } function find(StdStorage storage self, bool _clear) internal returns (uint256) { return stdStorageSafe.find(self, _clear).slot; } function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { return stdStorageSafe.target(self, _target); } function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { return stdStorageSafe.sig(self, _sig); } function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { return stdStorageSafe.sig(self, _sig); } function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { return stdStorageSafe.with_key(self, who); } function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { return stdStorageSafe.with_key(self, amt); } function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { return stdStorageSafe.with_key(self, key); } function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { return stdStorageSafe.with_calldata(self, _calldata); } function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { return stdStorageSafe.enable_packed_slots(self); } function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { return stdStorageSafe.depth(self, _depth); } function clear(StdStorage storage self) internal { stdStorageSafe.clear(self); } function checked_write(StdStorage storage self, address who) internal { checked_write(self, bytes32(uint256(uint160(who)))); } function checked_write(StdStorage storage self, uint256 amt) internal { checked_write(self, bytes32(amt)); } function checked_write_int(StdStorage storage self, int256 val) internal { checked_write(self, bytes32(uint256(val))); } function checked_write(StdStorage storage self, bool write) internal { bytes32 t; /// @solidity memory-safe-assembly assembly { t := write } checked_write(self, t); } function checked_write(StdStorage storage self, bytes32 set) internal { address who = self._target; bytes4 fsig = self._sig; uint256 field_depth = self._depth; bytes memory params = stdStorageSafe.getCallParams(self); if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { find(self, false); } FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; if ((data.offsetLeft + data.offsetRight) > 0) { uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight)); require( uint256(set) < maxVal, string( abi.encodePacked( "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ", vm.toString(maxVal) ) ) ); } bytes32 curVal = vm.load(who, bytes32(data.slot)); bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight); vm.store(who, bytes32(data.slot), valToSet); (bool success, bytes32 callResult) = stdStorageSafe.callTarget(self); if (!success || callResult != set) { vm.store(who, bytes32(data.slot), curVal); revert("stdStorage find(StdStorage): Failed to write value."); } clear(self); } function read_bytes32(StdStorage storage self) internal returns (bytes32) { return stdStorageSafe.read_bytes32(self); } function read_bool(StdStorage storage self) internal returns (bool) { return stdStorageSafe.read_bool(self); } function read_address(StdStorage storage self) internal returns (address) { return stdStorageSafe.read_address(self); } function read_uint(StdStorage storage self) internal returns (uint256) { return stdStorageSafe.read_uint(self); } function read_int(StdStorage storage self) internal returns (int256) { return stdStorageSafe.read_int(self); } function parent(StdStorage storage self) internal returns (uint256, bytes32) { return stdStorageSafe.parent(self); } function root(StdStorage storage self) internal returns (uint256) { return stdStorageSafe.root(self); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; import {VmSafe} from "./Vm.sol"; library StdStyle { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); string constant RED = "\u001b[91m"; string constant GREEN = "\u001b[92m"; string constant YELLOW = "\u001b[93m"; string constant BLUE = "\u001b[94m"; string constant MAGENTA = "\u001b[95m"; string constant CYAN = "\u001b[96m"; string constant BOLD = "\u001b[1m"; string constant DIM = "\u001b[2m"; string constant ITALIC = "\u001b[3m"; string constant UNDERLINE = "\u001b[4m"; string constant INVERSE = "\u001b[7m"; string constant RESET = "\u001b[0m"; function styleConcat(string memory style, string memory self) private pure returns (string memory) { return string(abi.encodePacked(style, self, RESET)); } function red(string memory self) internal pure returns (string memory) { return styleConcat(RED, self); } function red(uint256 self) internal pure returns (string memory) { return red(vm.toString(self)); } function red(int256 self) internal pure returns (string memory) { return red(vm.toString(self)); } function red(address self) internal pure returns (string memory) { return red(vm.toString(self)); } function red(bool self) internal pure returns (string memory) { return red(vm.toString(self)); } function redBytes(bytes memory self) internal pure returns (string memory) { return red(vm.toString(self)); } function redBytes32(bytes32 self) internal pure returns (string memory) { return red(vm.toString(self)); } function green(string memory self) internal pure returns (string memory) { return styleConcat(GREEN, self); } function green(uint256 self) internal pure returns (string memory) { return green(vm.toString(self)); } function green(int256 self) internal pure returns (string memory) { return green(vm.toString(self)); } function green(address self) internal pure returns (string memory) { return green(vm.toString(self)); } function green(bool self) internal pure returns (string memory) { return green(vm.toString(self)); } function greenBytes(bytes memory self) internal pure returns (string memory) { return green(vm.toString(self)); } function greenBytes32(bytes32 self) internal pure returns (string memory) { return green(vm.toString(self)); } function yellow(string memory self) internal pure returns (string memory) { return styleConcat(YELLOW, self); } function yellow(uint256 self) internal pure returns (string memory) { return yellow(vm.toString(self)); } function yellow(int256 self) internal pure returns (string memory) { return yellow(vm.toString(self)); } function yellow(address self) internal pure returns (string memory) { return yellow(vm.toString(self)); } function yellow(bool self) internal pure returns (string memory) { return yellow(vm.toString(self)); } function yellowBytes(bytes memory self) internal pure returns (string memory) { return yellow(vm.toString(self)); } function yellowBytes32(bytes32 self) internal pure returns (string memory) { return yellow(vm.toString(self)); } function blue(string memory self) internal pure returns (string memory) { return styleConcat(BLUE, self); } function blue(uint256 self) internal pure returns (string memory) { return blue(vm.toString(self)); } function blue(int256 self) internal pure returns (string memory) { return blue(vm.toString(self)); } function blue(address self) internal pure returns (string memory) { return blue(vm.toString(self)); } function blue(bool self) internal pure returns (string memory) { return blue(vm.toString(self)); } function blueBytes(bytes memory self) internal pure returns (string memory) { return blue(vm.toString(self)); } function blueBytes32(bytes32 self) internal pure returns (string memory) { return blue(vm.toString(self)); } function magenta(string memory self) internal pure returns (string memory) { return styleConcat(MAGENTA, self); } function magenta(uint256 self) internal pure returns (string memory) { return magenta(vm.toString(self)); } function magenta(int256 self) internal pure returns (string memory) { return magenta(vm.toString(self)); } function magenta(address self) internal pure returns (string memory) { return magenta(vm.toString(self)); } function magenta(bool self) internal pure returns (string memory) { return magenta(vm.toString(self)); } function magentaBytes(bytes memory self) internal pure returns (string memory) { return magenta(vm.toString(self)); } function magentaBytes32(bytes32 self) internal pure returns (string memory) { return magenta(vm.toString(self)); } function cyan(string memory self) internal pure returns (string memory) { return styleConcat(CYAN, self); } function cyan(uint256 self) internal pure returns (string memory) { return cyan(vm.toString(self)); } function cyan(int256 self) internal pure returns (string memory) { return cyan(vm.toString(self)); } function cyan(address self) internal pure returns (string memory) { return cyan(vm.toString(self)); } function cyan(bool self) internal pure returns (string memory) { return cyan(vm.toString(self)); } function cyanBytes(bytes memory self) internal pure returns (string memory) { return cyan(vm.toString(self)); } function cyanBytes32(bytes32 self) internal pure returns (string memory) { return cyan(vm.toString(self)); } function bold(string memory self) internal pure returns (string memory) { return styleConcat(BOLD, self); } function bold(uint256 self) internal pure returns (string memory) { return bold(vm.toString(self)); } function bold(int256 self) internal pure returns (string memory) { return bold(vm.toString(self)); } function bold(address self) internal pure returns (string memory) { return bold(vm.toString(self)); } function bold(bool self) internal pure returns (string memory) { return bold(vm.toString(self)); } function boldBytes(bytes memory self) internal pure returns (string memory) { return bold(vm.toString(self)); } function boldBytes32(bytes32 self) internal pure returns (string memory) { return bold(vm.toString(self)); } function dim(string memory self) internal pure returns (string memory) { return styleConcat(DIM, self); } function dim(uint256 self) internal pure returns (string memory) { return dim(vm.toString(self)); } function dim(int256 self) internal pure returns (string memory) { return dim(vm.toString(self)); } function dim(address self) internal pure returns (string memory) { return dim(vm.toString(self)); } function dim(bool self) internal pure returns (string memory) { return dim(vm.toString(self)); } function dimBytes(bytes memory self) internal pure returns (string memory) { return dim(vm.toString(self)); } function dimBytes32(bytes32 self) internal pure returns (string memory) { return dim(vm.toString(self)); } function italic(string memory self) internal pure returns (string memory) { return styleConcat(ITALIC, self); } function italic(uint256 self) internal pure returns (string memory) { return italic(vm.toString(self)); } function italic(int256 self) internal pure returns (string memory) { return italic(vm.toString(self)); } function italic(address self) internal pure returns (string memory) { return italic(vm.toString(self)); } function italic(bool self) internal pure returns (string memory) { return italic(vm.toString(self)); } function italicBytes(bytes memory self) internal pure returns (string memory) { return italic(vm.toString(self)); } function italicBytes32(bytes32 self) internal pure returns (string memory) { return italic(vm.toString(self)); } function underline(string memory self) internal pure returns (string memory) { return styleConcat(UNDERLINE, self); } function underline(uint256 self) internal pure returns (string memory) { return underline(vm.toString(self)); } function underline(int256 self) internal pure returns (string memory) { return underline(vm.toString(self)); } function underline(address self) internal pure returns (string memory) { return underline(vm.toString(self)); } function underline(bool self) internal pure returns (string memory) { return underline(vm.toString(self)); } function underlineBytes(bytes memory self) internal pure returns (string memory) { return underline(vm.toString(self)); } function underlineBytes32(bytes32 self) internal pure returns (string memory) { return underline(vm.toString(self)); } function inverse(string memory self) internal pure returns (string memory) { return styleConcat(INVERSE, self); } function inverse(uint256 self) internal pure returns (string memory) { return inverse(vm.toString(self)); } function inverse(int256 self) internal pure returns (string memory) { return inverse(vm.toString(self)); } function inverse(address self) internal pure returns (string memory) { return inverse(vm.toString(self)); } function inverse(bool self) internal pure returns (string memory) { return inverse(vm.toString(self)); } function inverseBytes(bytes memory self) internal pure returns (string memory) { return inverse(vm.toString(self)); } function inverseBytes32(bytes32 self) internal pure returns (string memory) { return inverse(vm.toString(self)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; pragma experimental ABIEncoderV2; import {IMulticall3} from "./interfaces/IMulticall3.sol"; import {MockERC20} from "./mocks/MockERC20.sol"; import {MockERC721} from "./mocks/MockERC721.sol"; import {VmSafe} from "./Vm.sol"; abstract contract StdUtils { /*////////////////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////////////////*/ IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; uint256 private constant INT256_MIN_ABS = 57896044618658097711785492504343953926634992332820282019728792003956564819968; uint256 private constant SECP256K1_ORDER = 115792089237316195423570985008687907852837564279074904382605163141518161494337; uint256 private constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; /*////////////////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); // If x is between min and max, return x directly. This is to ensure that dictionary values // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 if (x >= min && x <= max) return x; uint256 size = max - min + 1; // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. // This helps ensure coverage of the min/max values. if (x <= 3 && size > x) return min + x; if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. if (x > max) { uint256 diff = x - max; uint256 rem = diff % size; if (rem == 0) return max; result = min + rem - 1; } else if (x < min) { uint256 diff = min - x; uint256 rem = diff % size; if (rem == 0) return min; result = max - rem + 1; } } function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { result = _bound(x, min, max); console2_log_StdUtils("Bound result", result); } function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); // Shifting all int256 values to uint256 to use _bound function. The range of two types are: // int256 : -(2**255) ~ (2**255 - 1) // uint256: 0 ~ (2**256 - 1) // So, add 2**255, INT256_MIN_ABS to the integer values. // // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. // So, use `~uint256(x) + 1` instead. uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); uint256 y = _bound(_x, _min, _max); // To move it back to int256 value, subtract INT256_MIN_ABS at here. result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); } function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { result = _bound(x, min, max); console2_log_StdUtils("Bound result", vm.toString(result)); } function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) { result = _bound(privateKey, 1, SECP256K1_ORDER - 1); } function bytesToUint(bytes memory b) internal pure virtual returns (uint256) { require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); } /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) { console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead."); return vm.computeCreateAddress(deployer, nonce); } function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) internal pure virtual returns (address) { console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); return vm.computeCreate2Address(salt, initcodeHash, deployer); } /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) { console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); return vm.computeCreate2Address(salt, initCodeHash); } /// @dev returns an initialized mock ERC20 contract function deployMockERC20(string memory name, string memory symbol, uint8 decimals) internal returns (MockERC20 mock) { mock = new MockERC20(); mock.initialize(name, symbol, decimals); } /// @dev returns an initialized mock ERC721 contract function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) { mock = new MockERC721(); mock.initialize(name, symbol); } /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) { return hashInitCode(creationCode, ""); } /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode /// @param args the ABI-encoded arguments to the constructor of C function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) { return keccak256(abi.encodePacked(creationCode, args)); } // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. function getTokenBalances(address token, address[] memory addresses) internal virtual returns (uint256[] memory balances) { uint256 tokenCodeSize; assembly { tokenCodeSize := extcodesize(token) } require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract."); // ABI encode the aggregate call to Multicall3. uint256 length = addresses.length; IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); for (uint256 i = 0; i < length; ++i) { // 0x70a08231 = bytes4("balanceOf(address)")) calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))}); } // Make the aggregate call. (, bytes[] memory returnData) = multicall.aggregate(calls); // ABI decode the return data and return the balances. balances = new uint256[](length); for (uint256 i = 0; i < length; ++i) { balances[i] = abi.decode(returnData[i], (uint256)); } } /*////////////////////////////////////////////////////////////////////////// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { return address(uint160(uint256(bytesValue))); } // This section is used to prevent the compilation of console, which shortens the compilation time when console is // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid // any breaking changes to function signatures. function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn) internal pure returns (function(bytes memory) internal pure fnOut) { assembly { fnOut := fnIn } } function _sendLogPayload(bytes memory payload) internal pure { _castLogPayloadViewToPure(_sendLogPayloadView)(payload); } function _sendLogPayloadView(bytes memory payload) private view { uint256 payloadLength = payload.length; address consoleAddress = CONSOLE2_ADDRESS; /// @solidity memory-safe-assembly assembly { let payloadStart := add(payload, 32) let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) } } function console2_log_StdUtils(string memory p0) private pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function console2_log_StdUtils(string memory p0, uint256 p1) private pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); } function console2_log_StdUtils(string memory p0, string memory p1) private pure { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } }
// Automatically @generated by scripts/vm.py. Do not modify manually. // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.2 <0.9.0; pragma experimental ABIEncoderV2; /// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may /// result in Script simulations differing from on-chain execution. It is recommended to only use /// these cheats in scripts. interface VmSafe { /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`. enum CallerMode { // No caller modification is currently active. None, // A one time broadcast triggered by a `vm.broadcast()` call is currently active. Broadcast, // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active. RecurrentBroadcast, // A one time prank triggered by a `vm.prank()` call is currently active. Prank, // A recurrent prank triggered by a `vm.startPrank()` call is currently active. RecurrentPrank } /// The kind of account access that occurred. enum AccountAccessKind { // The account was called. Call, // The account was called via delegatecall. DelegateCall, // The account was called via callcode. CallCode, // The account was called via staticcall. StaticCall, // The account was created. Create, // The account was selfdestructed. SelfDestruct, // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess). Resume, // The account's balance was read. Balance, // The account's codesize was read. Extcodesize, // The account's codehash was read. Extcodehash, // The account's code was copied. Extcodecopy } /// Forge execution contexts. enum ForgeContext { // Test group execution context (test, coverage or snapshot). TestGroup, // `forge test` execution context. Test, // `forge coverage` execution context. Coverage, // `forge snapshot` execution context. Snapshot, // Script group execution context (dry run, broadcast or resume). ScriptGroup, // `forge script` execution context. ScriptDryRun, // `forge script --broadcast` execution context. ScriptBroadcast, // `forge script --resume` execution context. ScriptResume, // Unknown `forge` execution context. Unknown } /// An Ethereum log. Returned by `getRecordedLogs`. struct Log { // The topics of the log, including the signature, if any. bytes32[] topics; // The raw data of the log. bytes data; // The address of the log's emitter. address emitter; } /// An RPC URL and its alias. Returned by `rpcUrlStructs`. struct Rpc { // The alias of the RPC URL. string key; // The RPC URL. string url; } /// An RPC log object. Returned by `eth_getLogs`. struct EthGetLogs { // The address of the log's emitter. address emitter; // The topics of the log, including the signature, if any. bytes32[] topics; // The raw data of the log. bytes data; // The block hash. bytes32 blockHash; // The block number. uint64 blockNumber; // The transaction hash. bytes32 transactionHash; // The transaction index in the block. uint64 transactionIndex; // The log index. uint256 logIndex; // Whether the log was removed. bool removed; } /// A single entry in a directory listing. Returned by `readDir`. struct DirEntry { // The error message, if any. string errorMessage; // The path of the entry. string path; // The depth of the entry. uint64 depth; // Whether the entry is a directory. bool isDir; // Whether the entry is a symlink. bool isSymlink; } /// Metadata information about a file. /// This structure is returned from the `fsMetadata` function and represents known /// metadata about a file such as its permissions, size, modification /// times, etc. struct FsMetadata { // True if this metadata is for a directory. bool isDir; // True if this metadata is for a symlink. bool isSymlink; // The size of the file, in bytes, this metadata is for. uint256 length; // True if this metadata is for a readonly (unwritable) file. bool readOnly; // The last modification time listed in this metadata. uint256 modified; // The last access time of this metadata. uint256 accessed; // The creation time listed in this metadata. uint256 created; } /// A wallet with a public and private key. struct Wallet { // The wallet's address. address addr; // The wallet's public key `X`. uint256 publicKeyX; // The wallet's public key `Y`. uint256 publicKeyY; // The wallet's private key. uint256 privateKey; } /// The result of a `tryFfi` call. struct FfiResult { // The exit code of the call. int32 exitCode; // The optionally hex-decoded `stdout` data. bytes stdout; // The `stderr` data. bytes stderr; } /// Information on the chain and fork. struct ChainInfo { // The fork identifier. Set to zero if no fork is active. uint256 forkId; // The chain ID of the current fork. uint256 chainId; } /// The result of a `stopAndReturnStateDiff` call. struct AccountAccess { // The chain and fork the access occurred. ChainInfo chainInfo; // The kind of account access that determines what the account is. // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee. // If kind is Create, then the account is the newly created account. // If kind is SelfDestruct, then the account is the selfdestruct recipient. // If kind is a Resume, then account represents a account context that has resumed. AccountAccessKind kind; // The account that was accessed. // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT. address account; // What accessed the account. address accessor; // If the account was initialized or empty prior to the access. // An account is considered initialized if it has code, a // non-zero nonce, or a non-zero balance. bool initialized; // The previous balance of the accessed account. uint256 oldBalance; // The potential new balance of the accessed account. // That is, all balance changes are recorded here, even if reverts occurred. uint256 newBalance; // Code of the account deployed by CREATE. bytes deployedCode; // Value passed along with the account access uint256 value; // Input data provided to the CREATE or CALL bytes data; // If this access reverted in either the current or parent context. bool reverted; // An ordered list of storage accesses made during an account access operation. StorageAccess[] storageAccesses; // Call depth traversed during the recording of state differences uint64 depth; } /// The storage accessed during an `AccountAccess`. struct StorageAccess { // The account whose storage was accessed. address account; // The slot that was accessed. bytes32 slot; // If the access was a write. bool isWrite; // The previous value of the slot. bytes32 previousValue; // The new value of the slot. bytes32 newValue; // If the access was reverted. bool reverted; } /// Gas used. Returned by `lastCallGas`. struct Gas { // The gas limit of the call. uint64 gasLimit; // The total gas used. uint64 gasTotalUsed; // DEPRECATED: The amount of gas used for memory expansion. Ref: <https://github.com/foundry-rs/foundry/pull/7934#pullrequestreview-2069236939> uint64 gasMemoryUsed; // The amount of gas refunded. int64 gasRefunded; // The amount of gas remaining. uint64 gasRemaining; } /// The result of the `stopDebugTraceRecording` call struct DebugStep { // The stack before executing the step of the run. // stack\[0\] represents the top of the stack. // and only stack data relevant to the opcode execution is contained. uint256[] stack; // The memory input data before executing the step of the run. // only input data relevant to the opcode execution is contained. // e.g. for MLOAD, it will have memory\[offset:offset+32\] copied here. // the offset value can be get by the stack data. bytes memoryInput; // The opcode that was accessed. uint8 opcode; // The call depth of the step. uint64 depth; // Whether the call end up with out of gas error. bool isOutOfGas; // The contract address where the opcode is running address contractAddr; } /// The transaction type (`txType`) of the broadcast. enum BroadcastTxType { // Represents a CALL broadcast tx. Call, // Represents a CREATE broadcast tx. Create, // Represents a CREATE2 broadcast tx. Create2 } /// Represents a transaction's broadcast details. struct BroadcastTxSummary { // The hash of the transaction that was broadcasted bytes32 txHash; // Represent the type of transaction among CALL, CREATE, CREATE2 BroadcastTxType txType; // The address of the contract that was called or created. // This is address of the contract that is created if the txType is CREATE or CREATE2. address contractAddress; // The block number the transaction landed in. uint64 blockNumber; // Status of the transaction, retrieved from the transaction receipt. bool success; } // ======== Crypto ======== /// Derives a private key from the name, labels the account with that name, and returns the wallet. function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); /// Generates a wallet from the private key and returns the wallet. function createWallet(uint256 privateKey) external returns (Wallet memory wallet); /// Generates a wallet from the private key, labels the account with that name, and returns the wallet. function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet); /// Derive a private key from a provided mnenomic string (or mnenomic file path) /// at the derivation path `m/44'/60'/0'/0/{index}`. function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey); /// Derive a private key from a provided mnenomic string (or mnenomic file path) /// at `{derivationPath}{index}`. function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index) external pure returns (uint256 privateKey); /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language /// at the derivation path `m/44'/60'/0'/0/{index}`. function deriveKey(string calldata mnemonic, uint32 index, string calldata language) external pure returns (uint256 privateKey); /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language /// at `{derivationPath}{index}`. function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) external pure returns (uint256 privateKey); /// Derives secp256r1 public key from the provided `privateKey`. function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY); /// Adds a private key to the local forge wallet and returns the address. function rememberKey(uint256 privateKey) external returns (address keyAddr); /// Derive a set number of wallets from a mnemonic at the derivation path `m/44'/60'/0'/0/{0..count}`. /// /// The respective private keys are saved to the local forge wallet for later use and their addresses are returned. function rememberKeys(string calldata mnemonic, string calldata derivationPath, uint32 count) external returns (address[] memory keyAddrs); /// Derive a set number of wallets from a mnemonic in the specified language at the derivation path `m/44'/60'/0'/0/{0..count}`. /// /// The respective private keys are saved to the local forge wallet for later use and their addresses are returned. function rememberKeys( string calldata mnemonic, string calldata derivationPath, string calldata language, uint32 count ) external returns (address[] memory keyAddrs); /// Signs data with a `Wallet`. /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the /// signature's `s` value, and the recovery id `v` in a single bytes32. /// This format reduces the signature size from 65 to 64 bytes. function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); /// Signs `digest` with `privateKey` using the secp256k1 curve. /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the /// signature's `s` value, and the recovery id `v` in a single bytes32. /// This format reduces the signature size from 65 to 64 bytes. function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); /// Signs `digest` with signer provided to script using the secp256k1 curve. /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the /// signature's `s` value, and the recovery id `v` in a single bytes32. /// This format reduces the signature size from 65 to 64 bytes. /// If `--sender` is provided, the signer with provided address is used, otherwise, /// if exactly one signer is provided to the script, that signer is used. /// Raises error if signer passed through `--sender` does not match any unlocked signers or /// if `--sender` is not provided and not exactly one signer is passed to the script. function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs); /// Signs `digest` with signer provided to script using the secp256k1 curve. /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the /// signature's `s` value, and the recovery id `v` in a single bytes32. /// This format reduces the signature size from 65 to 64 bytes. /// Raises error if none of the signers passed into the script have provided address. function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); /// Signs `digest` with `privateKey` using the secp256r1 curve. function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); /// Signs data with a `Wallet`. function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); /// Signs `digest` with `privateKey` using the secp256k1 curve. function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); /// Signs `digest` with signer provided to script using the secp256k1 curve. /// If `--sender` is provided, the signer with provided address is used, otherwise, /// if exactly one signer is provided to the script, that signer is used. /// Raises error if signer passed through `--sender` does not match any unlocked signers or /// if `--sender` is not provided and not exactly one signer is passed to the script. function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); /// Signs `digest` with signer provided to script using the secp256k1 curve. /// Raises error if none of the signers passed into the script have provided address. function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); // ======== Environment ======== /// Gets the environment variable `name` and parses it as `address`. /// Reverts if the variable was not found or could not be parsed. function envAddress(string calldata name) external view returns (address value); /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. /// Reverts if the variable was not found or could not be parsed. function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); /// Gets the environment variable `name` and parses it as `bool`. /// Reverts if the variable was not found or could not be parsed. function envBool(string calldata name) external view returns (bool value); /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. /// Reverts if the variable was not found or could not be parsed. function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value); /// Gets the environment variable `name` and parses it as `bytes32`. /// Reverts if the variable was not found or could not be parsed. function envBytes32(string calldata name) external view returns (bytes32 value); /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. /// Reverts if the variable was not found or could not be parsed. function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value); /// Gets the environment variable `name` and parses it as `bytes`. /// Reverts if the variable was not found or could not be parsed. function envBytes(string calldata name) external view returns (bytes memory value); /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. /// Reverts if the variable was not found or could not be parsed. function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value); /// Gets the environment variable `name` and returns true if it exists, else returns false. function envExists(string calldata name) external view returns (bool result); /// Gets the environment variable `name` and parses it as `int256`. /// Reverts if the variable was not found or could not be parsed. function envInt(string calldata name) external view returns (int256 value); /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. /// Reverts if the variable was not found or could not be parsed. function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value); /// Gets the environment variable `name` and parses it as `bool`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, bool defaultValue) external view returns (bool value); /// Gets the environment variable `name` and parses it as `uint256`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value); /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, string calldata delim, address[] calldata defaultValue) external view returns (address[] memory value); /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue) external view returns (bytes32[] memory value); /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, string calldata delim, string[] calldata defaultValue) external view returns (string[] memory value); /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue) external view returns (bytes[] memory value); /// Gets the environment variable `name` and parses it as `int256`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, int256 defaultValue) external view returns (int256 value); /// Gets the environment variable `name` and parses it as `address`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, address defaultValue) external view returns (address value); /// Gets the environment variable `name` and parses it as `bytes32`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value); /// Gets the environment variable `name` and parses it as `string`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value); /// Gets the environment variable `name` and parses it as `bytes`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value); /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue) external view returns (bool[] memory value); /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue) external view returns (uint256[] memory value); /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. /// Reverts if the variable could not be parsed. /// Returns `defaultValue` if the variable was not found. function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue) external view returns (int256[] memory value); /// Gets the environment variable `name` and parses it as `string`. /// Reverts if the variable was not found or could not be parsed. function envString(string calldata name) external view returns (string memory value); /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. /// Reverts if the variable was not found or could not be parsed. function envString(string calldata name, string calldata delim) external view returns (string[] memory value); /// Gets the environment variable `name` and parses it as `uint256`. /// Reverts if the variable was not found or could not be parsed. function envUint(string calldata name) external view returns (uint256 value); /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. /// Reverts if the variable was not found or could not be parsed. function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value); /// Returns true if `forge` command was executed in given context. function isContext(ForgeContext context) external view returns (bool result); /// Sets environment variables. function setEnv(string calldata name, string calldata value) external; // ======== EVM ======== /// Gets all accessed reads and write slot from a `vm.record` session, for a given address. function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots); /// Gets the address for a given private key. function addr(uint256 privateKey) external pure returns (address keyAddr); /// Gets all the logs according to specified filter. function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics) external returns (EthGetLogs[] memory logs); /// Gets the current `block.blobbasefee`. /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction, /// and as a result will get optimized out by the compiler. /// See https://github.com/foundry-rs/foundry/issues/6180 function getBlobBaseFee() external view returns (uint256 blobBaseFee); /// Gets the current `block.number`. /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction, /// and as a result will get optimized out by the compiler. /// See https://github.com/foundry-rs/foundry/issues/6180 function getBlockNumber() external view returns (uint256 height); /// Gets the current `block.timestamp`. /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction, /// and as a result will get optimized out by the compiler. /// See https://github.com/foundry-rs/foundry/issues/6180 function getBlockTimestamp() external view returns (uint256 timestamp); /// Gets the map key and parent of a mapping at a given slot, for a given address. function getMappingKeyAndParentOf(address target, bytes32 elementSlot) external returns (bool found, bytes32 key, bytes32 parent); /// Gets the number of elements in the mapping at the given slot, for a given address. function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length); /// Gets the elements at index idx of the mapping at the given slot, for a given address. The /// index must be less than the length of the mapping (i.e. the number of keys in the mapping). function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value); /// Gets the nonce of an account. function getNonce(address account) external view returns (uint64 nonce); /// Get the nonce of a `Wallet`. function getNonce(Wallet calldata wallet) external returns (uint64 nonce); /// Gets all the recorded logs. function getRecordedLogs() external returns (Log[] memory logs); /// Gets the gas used in the last call from the callee perspective. function lastCallGas() external view returns (Gas memory gas); /// Loads a storage slot from an address. function load(address target, bytes32 slot) external view returns (bytes32 data); /// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused. function pauseGasMetering() external; /// Records all storage reads and writes. function record() external; /// Record all the transaction logs. function recordLogs() external; /// Reset gas metering (i.e. gas usage is set to gas limit). function resetGasMetering() external; /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on. function resumeGasMetering() external; /// Performs an Ethereum JSON-RPC request to the current fork URL. function rpc(string calldata method, string calldata params) external returns (bytes memory data); /// Performs an Ethereum JSON-RPC request to the given endpoint. function rpc(string calldata urlOrAlias, string calldata method, string calldata params) external returns (bytes memory data); /// Records the debug trace during the run. function startDebugTraceRecording() external; /// Starts recording all map SSTOREs for later retrieval. function startMappingRecording() external; /// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order, /// along with the context of the calls function startStateDiffRecording() external; /// Stop debug trace recording and returns the recorded debug trace. function stopAndReturnDebugTraceRecording() external returns (DebugStep[] memory step); /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session. function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses); /// Stops recording all map SSTOREs for later retrieval and clears the recorded data. function stopMappingRecording() external; // ======== Filesystem ======== /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine. /// `path` is relative to the project root. function closeFile(string calldata path) external; /// Copies the contents of one file to another. This function will **overwrite** the contents of `to`. /// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`. /// Both `from` and `to` are relative to the project root. function copyFile(string calldata from, string calldata to) external returns (uint64 copied); /// Creates a new, empty directory at the provided path. /// This cheatcode will revert in the following situations, but is not limited to just these cases: /// - User lacks permissions to modify `path`. /// - A parent of the given path doesn't exist and `recursive` is false. /// - `path` already exists and `recursive` is false. /// `path` is relative to the project root. function createDir(string calldata path, bool recursive) external; /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. function deployCode(string calldata artifactPath) external returns (address deployedAddress); /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. /// Additionally accepts abi-encoded constructor arguments. function deployCode(string calldata artifactPath, bytes calldata constructorArgs) external returns (address deployedAddress); /// Returns true if the given path points to an existing entity, else returns false. function exists(string calldata path) external returns (bool result); /// Performs a foreign function call via the terminal. function ffi(string[] calldata commandInput) external returns (bytes memory result); /// Given a path, query the file system to get information about a file, directory, etc. function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata); /// Gets the artifact path from code (aka. creation code). function getArtifactPathByCode(bytes calldata code) external view returns (string memory path); /// Gets the artifact path from deployed code (aka. runtime code). function getArtifactPathByDeployedCode(bytes calldata deployedCode) external view returns (string memory path); /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode); /// Returns true if the path exists on disk and is pointing at a directory, else returns false. function isDir(string calldata path) external returns (bool result); /// Returns true if the path exists on disk and is pointing at a regular file, else returns false. function isFile(string calldata path) external returns (bool result); /// Get the path of the current project root. function projectRoot() external view returns (string memory path); /// Prompts the user for a string value in the terminal. function prompt(string calldata promptText) external returns (string memory input); /// Prompts the user for an address in the terminal. function promptAddress(string calldata promptText) external returns (address); /// Prompts the user for a hidden string value in the terminal. function promptSecret(string calldata promptText) external returns (string memory input); /// Prompts the user for hidden uint256 in the terminal (usually pk). function promptSecretUint(string calldata promptText) external returns (uint256); /// Prompts the user for uint256 in the terminal. function promptUint(string calldata promptText) external returns (uint256); /// Reads the directory at the given path recursively, up to `maxDepth`. /// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned. /// Follows symbolic links if `followLinks` is true. function readDir(string calldata path) external view returns (DirEntry[] memory entries); /// See `readDir(string)`. function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries); /// See `readDir(string)`. function readDir(string calldata path, uint64 maxDepth, bool followLinks) external view returns (DirEntry[] memory entries); /// Reads the entire content of file to string. `path` is relative to the project root. function readFile(string calldata path) external view returns (string memory data); /// Reads the entire content of file as binary. `path` is relative to the project root. function readFileBinary(string calldata path) external view returns (bytes memory data); /// Reads next line of file to string. function readLine(string calldata path) external view returns (string memory line); /// Reads a symbolic link, returning the path that the link points to. /// This cheatcode will revert in the following situations, but is not limited to just these cases: /// - `path` is not a symbolic link. /// - `path` does not exist. function readLink(string calldata linkPath) external view returns (string memory targetPath); /// Removes a directory at the provided path. /// This cheatcode will revert in the following situations, but is not limited to just these cases: /// - `path` doesn't exist. /// - `path` isn't a directory. /// - User lacks permissions to modify `path`. /// - The directory is not empty and `recursive` is false. /// `path` is relative to the project root. function removeDir(string calldata path, bool recursive) external; /// Removes a file from the filesystem. /// This cheatcode will revert in the following situations, but is not limited to just these cases: /// - `path` points to a directory. /// - The file doesn't exist. /// - The user lacks permissions to remove the file. /// `path` is relative to the project root. function removeFile(string calldata path) external; /// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr. function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result); /// Returns the time since unix epoch in milliseconds. function unixTime() external returns (uint256 milliseconds); /// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does. /// `path` is relative to the project root. function writeFile(string calldata path, string calldata data) external; /// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does. /// `path` is relative to the project root. function writeFileBinary(string calldata path, bytes calldata data) external; /// Writes line to file, creating a file if it does not exist. /// `path` is relative to the project root. function writeLine(string calldata path, string calldata data) external; /// Returns the most recent broadcast for the given contract on `chainId` matching `txType`. /// /// For example: /// /// The most recent deployment can be fetched by passing `txType` as `CREATE` or `CREATE2`. /// /// The most recent call can be fetched by passing `txType` as `CALL`. function getBroadcast(string calldata contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary memory); /// Returns all broadcasts for the given contract on `chainId` with the specified `txType`. /// /// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber. function getBroadcasts(string calldata contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary[] memory); /// Returns all broadcasts for the given contract on `chainId`. /// /// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber. function getBroadcasts(string calldata contractName, uint64 chainId) external returns (BroadcastTxSummary[] memory); /// Returns the most recent deployment for the current `chainId`. function getDeployment(string calldata contractName) external returns (address deployedAddress); /// Returns the most recent deployment for the given contract on `chainId` function getDeployment(string calldata contractName, uint64 chainId) external returns (address deployedAddress); /// Returns all deployments for the given contract on `chainId` /// /// Sorted in descending order of deployment time i.e descending order of BroadcastTxSummary.blockNumber. /// /// The most recent deployment is the first element, and the oldest is the last. function getDeployments(string calldata contractName, uint64 chainId) external returns (address[] memory deployedAddresses); // ======== JSON ======== /// Checks if `key` exists in a JSON object. function keyExistsJson(string calldata json, string calldata key) external view returns (bool); /// Parses a string of JSON data at `key` and coerces it to `address`. function parseJsonAddress(string calldata json, string calldata key) external pure returns (address); /// Parses a string of JSON data at `key` and coerces it to `address[]`. function parseJsonAddressArray(string calldata json, string calldata key) external pure returns (address[] memory); /// Parses a string of JSON data at `key` and coerces it to `bool`. function parseJsonBool(string calldata json, string calldata key) external pure returns (bool); /// Parses a string of JSON data at `key` and coerces it to `bool[]`. function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory); /// Parses a string of JSON data at `key` and coerces it to `bytes`. function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory); /// Parses a string of JSON data at `key` and coerces it to `bytes32`. function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32); /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`. function parseJsonBytes32Array(string calldata json, string calldata key) external pure returns (bytes32[] memory); /// Parses a string of JSON data at `key` and coerces it to `bytes[]`. function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory); /// Parses a string of JSON data at `key` and coerces it to `int256`. function parseJsonInt(string calldata json, string calldata key) external pure returns (int256); /// Parses a string of JSON data at `key` and coerces it to `int256[]`. function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory); /// Returns an array of all the keys in a JSON object. function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys); /// Parses a string of JSON data at `key` and coerces it to `string`. function parseJsonString(string calldata json, string calldata key) external pure returns (string memory); /// Parses a string of JSON data at `key` and coerces it to `string[]`. function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory); /// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`. function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription) external pure returns (bytes memory); /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`. function parseJsonType(string calldata json, string calldata typeDescription) external pure returns (bytes memory); /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`. function parseJsonType(string calldata json, string calldata key, string calldata typeDescription) external pure returns (bytes memory); /// Parses a string of JSON data at `key` and coerces it to `uint256`. function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256); /// Parses a string of JSON data at `key` and coerces it to `uint256[]`. function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory); /// ABI-encodes a JSON object. function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData); /// ABI-encodes a JSON object at `key`. function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData); /// See `serializeJson`. function serializeAddress(string calldata objectKey, string calldata valueKey, address value) external returns (string memory json); /// See `serializeJson`. function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values) external returns (string memory json); /// See `serializeJson`. function serializeBool(string calldata objectKey, string calldata valueKey, bool value) external returns (string memory json); /// See `serializeJson`. function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values) external returns (string memory json); /// See `serializeJson`. function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value) external returns (string memory json); /// See `serializeJson`. function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values) external returns (string memory json); /// See `serializeJson`. function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value) external returns (string memory json); /// See `serializeJson`. function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values) external returns (string memory json); /// See `serializeJson`. function serializeInt(string calldata objectKey, string calldata valueKey, int256 value) external returns (string memory json); /// See `serializeJson`. function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values) external returns (string memory json); /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file. /// Returns the stringified version of the specific JSON file up to that moment. function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json); /// See `serializeJson`. function serializeJsonType(string calldata typeDescription, bytes calldata value) external pure returns (string memory json); /// See `serializeJson`. function serializeJsonType( string calldata objectKey, string calldata valueKey, string calldata typeDescription, bytes calldata value ) external returns (string memory json); /// See `serializeJson`. function serializeString(string calldata objectKey, string calldata valueKey, string calldata value) external returns (string memory json); /// See `serializeJson`. function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values) external returns (string memory json); /// See `serializeJson`. function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value) external returns (string memory json); /// See `serializeJson`. function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value) external returns (string memory json); /// See `serializeJson`. function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values) external returns (string memory json); /// Write a serialized JSON object to a file. If the file exists, it will be overwritten. function writeJson(string calldata json, string calldata path) external; /// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = <value_key.> /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing. function writeJson(string calldata json, string calldata path, string calldata valueKey) external; /// Checks if `key` exists in a JSON object /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. function keyExists(string calldata json, string calldata key) external view returns (bool); // ======== Scripting ======== /// Takes a signed transaction and broadcasts it to the network. function broadcastRawTransaction(bytes calldata data) external; /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain. /// Broadcasting address is determined by checking the following in order: /// 1. If `--sender` argument was provided, that address is used. /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. function broadcast() external; /// Has the next call (at this call depth only) create a transaction with the address provided /// as the sender that can later be signed and sent onchain. function broadcast(address signer) external; /// Has the next call (at this call depth only) create a transaction with the private key /// provided as the sender that can later be signed and sent onchain. function broadcast(uint256 privateKey) external; /// Returns addresses of available unlocked wallets in the script environment. function getScriptWallets() external returns (address[] memory wallets); /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain. /// Broadcasting address is determined by checking the following in order: /// 1. If `--sender` argument was provided, that address is used. /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. function startBroadcast() external; /// Has all subsequent calls (at this call depth only) create transactions with the address /// provided that can later be signed and sent onchain. function startBroadcast(address signer) external; /// Has all subsequent calls (at this call depth only) create transactions with the private key /// provided that can later be signed and sent onchain. function startBroadcast(uint256 privateKey) external; /// Stops collecting onchain transactions. function stopBroadcast() external; /// Returns addresses of available unlocked wallets in the script environment. function getWallets() external returns (address[] memory wallets); // ======== String ======== /// Returns the index of the first occurrence of a `key` in an `input` string. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found. /// Returns 0 in case of an empty `key`. function indexOf(string calldata input, string calldata key) external pure returns (uint256); /// Parses the given `string` into an `address`. function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue); /// Parses the given `string` into a `bool`. function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue); /// Parses the given `string` into `bytes`. function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue); /// Parses the given `string` into a `bytes32`. function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue); /// Parses the given `string` into a `int256`. function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue); /// Parses the given `string` into a `uint256`. function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue); /// Replaces occurrences of `from` in the given `string` with `to`. function replace(string calldata input, string calldata from, string calldata to) external pure returns (string memory output); /// Splits the given `string` into an array of strings divided by the `delimiter`. function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs); /// Converts the given `string` value to Lowercase. function toLowercase(string calldata input) external pure returns (string memory output); /// Converts the given value to a `string`. function toString(address value) external pure returns (string memory stringifiedValue); /// Converts the given value to a `string`. function toString(bytes calldata value) external pure returns (string memory stringifiedValue); /// Converts the given value to a `string`. function toString(bytes32 value) external pure returns (string memory stringifiedValue); /// Converts the given value to a `string`. function toString(bool value) external pure returns (string memory stringifiedValue); /// Converts the given value to a `string`. function toString(uint256 value) external pure returns (string memory stringifiedValue); /// Converts the given value to a `string`. function toString(int256 value) external pure returns (string memory stringifiedValue); /// Converts the given `string` value to Uppercase. function toUppercase(string calldata input) external pure returns (string memory output); /// Trims leading and trailing whitespace from the given `string` value. function trim(string calldata input) external pure returns (string memory output); // ======== Testing ======== /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. /// Formats values with decimals in failure message. function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure; /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertApproxEqAbsDecimal( uint256 left, uint256 right, uint256 maxDelta, uint256 decimals, string calldata error ) external pure; /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. /// Formats values with decimals in failure message. function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure; /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertApproxEqAbsDecimal( int256 left, int256 right, uint256 maxDelta, uint256 decimals, string calldata error ) external pure; /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure; /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. /// Includes error message into revert string on failure. function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure; /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. /// Includes error message into revert string on failure. function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Formats values with decimals in failure message. function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals) external pure; /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertApproxEqRelDecimal( uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals, string calldata error ) external pure; /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Formats values with decimals in failure message. function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals) external pure; /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertApproxEqRelDecimal( int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals, string calldata error ) external pure; /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure; /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Includes error message into revert string on failure. function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) external pure; /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure; /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% /// Includes error message into revert string on failure. function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) external pure; /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure; /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; /// Asserts that two `bool` values are equal. function assertEq(bool left, bool right) external pure; /// Asserts that two `bool` values are equal and includes error message into revert string on failure. function assertEq(bool left, bool right, string calldata error) external pure; /// Asserts that two `string` values are equal. function assertEq(string calldata left, string calldata right) external pure; /// Asserts that two `string` values are equal and includes error message into revert string on failure. function assertEq(string calldata left, string calldata right, string calldata error) external pure; /// Asserts that two `bytes` values are equal. function assertEq(bytes calldata left, bytes calldata right) external pure; /// Asserts that two `bytes` values are equal and includes error message into revert string on failure. function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; /// Asserts that two arrays of `bool` values are equal. function assertEq(bool[] calldata left, bool[] calldata right) external pure; /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure. function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `uint256 values are equal. function assertEq(uint256[] calldata left, uint256[] calldata right) external pure; /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure. function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `int256` values are equal. function assertEq(int256[] calldata left, int256[] calldata right) external pure; /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure. function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; /// Asserts that two `uint256` values are equal. function assertEq(uint256 left, uint256 right) external pure; /// Asserts that two arrays of `address` values are equal. function assertEq(address[] calldata left, address[] calldata right) external pure; /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure. function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `bytes32` values are equal. function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure; /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure. function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `string` values are equal. function assertEq(string[] calldata left, string[] calldata right) external pure; /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure. function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `bytes` values are equal. function assertEq(bytes[] calldata left, bytes[] calldata right) external pure; /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure. function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; /// Asserts that two `uint256` values are equal and includes error message into revert string on failure. function assertEq(uint256 left, uint256 right, string calldata error) external pure; /// Asserts that two `int256` values are equal. function assertEq(int256 left, int256 right) external pure; /// Asserts that two `int256` values are equal and includes error message into revert string on failure. function assertEq(int256 left, int256 right, string calldata error) external pure; /// Asserts that two `address` values are equal. function assertEq(address left, address right) external pure; /// Asserts that two `address` values are equal and includes error message into revert string on failure. function assertEq(address left, address right, string calldata error) external pure; /// Asserts that two `bytes32` values are equal. function assertEq(bytes32 left, bytes32 right) external pure; /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure. function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; /// Asserts that the given condition is false. function assertFalse(bool condition) external pure; /// Asserts that the given condition is false and includes error message into revert string on failure. function assertFalse(bool condition, string calldata error) external pure; /// Compares two `uint256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; /// Compares two `uint256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; /// Compares two `int256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure; /// Compares two `int256` values. Expects first value to be greater than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; /// Compares two `uint256` values. Expects first value to be greater than or equal to second. function assertGe(uint256 left, uint256 right) external pure; /// Compares two `uint256` values. Expects first value to be greater than or equal to second. /// Includes error message into revert string on failure. function assertGe(uint256 left, uint256 right, string calldata error) external pure; /// Compares two `int256` values. Expects first value to be greater than or equal to second. function assertGe(int256 left, int256 right) external pure; /// Compares two `int256` values. Expects first value to be greater than or equal to second. /// Includes error message into revert string on failure. function assertGe(int256 left, int256 right, string calldata error) external pure; /// Compares two `uint256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; /// Compares two `uint256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; /// Compares two `int256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure; /// Compares two `int256` values. Expects first value to be greater than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; /// Compares two `uint256` values. Expects first value to be greater than second. function assertGt(uint256 left, uint256 right) external pure; /// Compares two `uint256` values. Expects first value to be greater than second. /// Includes error message into revert string on failure. function assertGt(uint256 left, uint256 right, string calldata error) external pure; /// Compares two `int256` values. Expects first value to be greater than second. function assertGt(int256 left, int256 right) external pure; /// Compares two `int256` values. Expects first value to be greater than second. /// Includes error message into revert string on failure. function assertGt(int256 left, int256 right, string calldata error) external pure; /// Compares two `uint256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; /// Compares two `uint256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; /// Compares two `int256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure; /// Compares two `int256` values. Expects first value to be less than or equal to second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; /// Compares two `uint256` values. Expects first value to be less than or equal to second. function assertLe(uint256 left, uint256 right) external pure; /// Compares two `uint256` values. Expects first value to be less than or equal to second. /// Includes error message into revert string on failure. function assertLe(uint256 left, uint256 right, string calldata error) external pure; /// Compares two `int256` values. Expects first value to be less than or equal to second. function assertLe(int256 left, int256 right) external pure; /// Compares two `int256` values. Expects first value to be less than or equal to second. /// Includes error message into revert string on failure. function assertLe(int256 left, int256 right, string calldata error) external pure; /// Compares two `uint256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; /// Compares two `uint256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; /// Compares two `int256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure; /// Compares two `int256` values. Expects first value to be less than second. /// Formats values with decimals in failure message. Includes error message into revert string on failure. function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; /// Compares two `uint256` values. Expects first value to be less than second. function assertLt(uint256 left, uint256 right) external pure; /// Compares two `uint256` values. Expects first value to be less than second. /// Includes error message into revert string on failure. function assertLt(uint256 left, uint256 right, string calldata error) external pure; /// Compares two `int256` values. Expects first value to be less than second. function assertLt(int256 left, int256 right) external pure; /// Compares two `int256` values. Expects first value to be less than second. /// Includes error message into revert string on failure. function assertLt(int256 left, int256 right, string calldata error) external pure; /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure; /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. /// Includes error message into revert string on failure. function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; /// Asserts that two `bool` values are not equal. function assertNotEq(bool left, bool right) external pure; /// Asserts that two `bool` values are not equal and includes error message into revert string on failure. function assertNotEq(bool left, bool right, string calldata error) external pure; /// Asserts that two `string` values are not equal. function assertNotEq(string calldata left, string calldata right) external pure; /// Asserts that two `string` values are not equal and includes error message into revert string on failure. function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; /// Asserts that two `bytes` values are not equal. function assertNotEq(bytes calldata left, bytes calldata right) external pure; /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure. function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; /// Asserts that two arrays of `bool` values are not equal. function assertNotEq(bool[] calldata left, bool[] calldata right) external pure; /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure. function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `uint256` values are not equal. function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure; /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure. function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `int256` values are not equal. function assertNotEq(int256[] calldata left, int256[] calldata right) external pure; /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure. function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; /// Asserts that two `uint256` values are not equal. function assertNotEq(uint256 left, uint256 right) external pure; /// Asserts that two arrays of `address` values are not equal. function assertNotEq(address[] calldata left, address[] calldata right) external pure; /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure. function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `bytes32` values are not equal. function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure; /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure. function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `string` values are not equal. function assertNotEq(string[] calldata left, string[] calldata right) external pure; /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure. function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; /// Asserts that two arrays of `bytes` values are not equal. function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure; /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure. function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure. function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; /// Asserts that two `int256` values are not equal. function assertNotEq(int256 left, int256 right) external pure; /// Asserts that two `int256` values are not equal and includes error message into revert string on failure. function assertNotEq(int256 left, int256 right, string calldata error) external pure; /// Asserts that two `address` values are not equal. function assertNotEq(address left, address right) external pure; /// Asserts that two `address` values are not equal and includes error message into revert string on failure. function assertNotEq(address left, address right, string calldata error) external pure; /// Asserts that two `bytes32` values are not equal. function assertNotEq(bytes32 left, bytes32 right) external pure; /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure. function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; /// Asserts that the given condition is true. function assertTrue(bool condition) external pure; /// Asserts that the given condition is true and includes error message into revert string on failure. function assertTrue(bool condition, string calldata error) external pure; /// If the condition is false, discard this run's fuzz inputs and generate new ones. function assume(bool condition) external pure; /// Discard this run's fuzz inputs and generate new ones if next call reverted. function assumeNoRevert() external pure; /// Writes a breakpoint to jump to in the debugger. function breakpoint(string calldata char) external pure; /// Writes a conditional breakpoint to jump to in the debugger. function breakpoint(string calldata char, bool value) external pure; /// Returns the Foundry version. /// Format: <cargo_version>+<git_sha>+<build_timestamp> /// Sample output: 0.2.0+faa94c384+202407110019 /// Note: Build timestamps may vary slightly across platforms due to separate CI jobs. /// For reliable version comparisons, use YYYYMMDD0000 format (e.g., >= 202407110000) /// to compare timestamps while ignoring minor time differences. function getFoundryVersion() external view returns (string memory version); /// Returns the RPC url for the given alias. function rpcUrl(string calldata rpcAlias) external view returns (string memory json); /// Returns all rpc urls and their aliases as structs. function rpcUrlStructs() external view returns (Rpc[] memory urls); /// Returns all rpc urls and their aliases `[alias, url][]`. function rpcUrls() external view returns (string[2][] memory urls); /// Suspends execution of the main thread for `duration` milliseconds. function sleep(uint256 duration) external; // ======== Toml ======== /// Checks if `key` exists in a TOML table. function keyExistsToml(string calldata toml, string calldata key) external view returns (bool); /// Parses a string of TOML data at `key` and coerces it to `address`. function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address); /// Parses a string of TOML data at `key` and coerces it to `address[]`. function parseTomlAddressArray(string calldata toml, string calldata key) external pure returns (address[] memory); /// Parses a string of TOML data at `key` and coerces it to `bool`. function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool); /// Parses a string of TOML data at `key` and coerces it to `bool[]`. function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory); /// Parses a string of TOML data at `key` and coerces it to `bytes`. function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory); /// Parses a string of TOML data at `key` and coerces it to `bytes32`. function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32); /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`. function parseTomlBytes32Array(string calldata toml, string calldata key) external pure returns (bytes32[] memory); /// Parses a string of TOML data at `key` and coerces it to `bytes[]`. function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory); /// Parses a string of TOML data at `key` and coerces it to `int256`. function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256); /// Parses a string of TOML data at `key` and coerces it to `int256[]`. function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory); /// Returns an array of all the keys in a TOML table. function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys); /// Parses a string of TOML data at `key` and coerces it to `string`. function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory); /// Parses a string of TOML data at `key` and coerces it to `string[]`. function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory); /// Parses a string of TOML data at `key` and coerces it to type array corresponding to `typeDescription`. function parseTomlTypeArray(string calldata toml, string calldata key, string calldata typeDescription) external pure returns (bytes memory); /// Parses a string of TOML data and coerces it to type corresponding to `typeDescription`. function parseTomlType(string calldata toml, string calldata typeDescription) external pure returns (bytes memory); /// Parses a string of TOML data at `key` and coerces it to type corresponding to `typeDescription`. function parseTomlType(string calldata toml, string calldata key, string calldata typeDescription) external pure returns (bytes memory); /// Parses a string of TOML data at `key` and coerces it to `uint256`. function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256); /// Parses a string of TOML data at `key` and coerces it to `uint256[]`. function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory); /// ABI-encodes a TOML table. function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData); /// ABI-encodes a TOML table at `key`. function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData); /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file. function writeToml(string calldata json, string calldata path) external; /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = <value_key.> /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing. function writeToml(string calldata json, string calldata path, string calldata valueKey) external; // ======== Utilities ======== /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer. function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer) external pure returns (address); /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer. function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address); /// Compute the address a contract will be deployed at for a given deployer address and nonce. function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address); /// Utility cheatcode to copy storage of `from` contract to another `to` contract. function copyStorage(address from, address to) external; /// Returns ENS namehash for provided string. function ensNamehash(string calldata name) external pure returns (bytes32); /// Gets the label for the specified address. function getLabel(address account) external view returns (string memory currentLabel); /// Labels an address in call traces. function label(address account, string calldata newLabel) external; /// Pauses collection of call traces. Useful in cases when you want to skip tracing of /// complex calls which are not useful for debugging. function pauseTracing() external view; /// Returns a random `address`. function randomAddress() external returns (address); /// Returns a random `bool`. function randomBool() external view returns (bool); /// Returns a random byte array value of the given length. function randomBytes(uint256 len) external view returns (bytes memory); /// Returns a random fixed-size byte array of length 4. function randomBytes4() external view returns (bytes4); /// Returns a random fixed-size byte array of length 8. function randomBytes8() external view returns (bytes8); /// Returns a random `int256` value. function randomInt() external view returns (int256); /// Returns a random `int256` value of given bits. function randomInt(uint256 bits) external view returns (int256); /// Returns a random uint256 value. function randomUint() external returns (uint256); /// Returns random uint256 value between the provided range (=min..=max). function randomUint(uint256 min, uint256 max) external returns (uint256); /// Returns a random `uint256` value of given bits. function randomUint(uint256 bits) external view returns (uint256); /// Unpauses collection of call traces. function resumeTracing() external view; /// Utility cheatcode to set arbitrary storage for given target address. function setArbitraryStorage(address target) external; /// Encodes a `bytes` value to a base64url string. function toBase64URL(bytes calldata data) external pure returns (string memory); /// Encodes a `string` value to a base64url string. function toBase64URL(string calldata data) external pure returns (string memory); /// Encodes a `bytes` value to a base64 string. function toBase64(bytes calldata data) external pure returns (string memory); /// Encodes a `string` value to a base64 string. function toBase64(string calldata data) external pure returns (string memory); } /// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used /// in tests, but it is not recommended to use these cheats in scripts. interface Vm is VmSafe { // ======== EVM ======== /// Returns the identifier of the currently active fork. Reverts if no fork is currently active. function activeFork() external view returns (uint256 forkId); /// In forking mode, explicitly grant the given address cheatcode access. function allowCheatcodes(address account) external; /// Sets `block.blobbasefee` function blobBaseFee(uint256 newBlobBaseFee) external; /// Sets the blobhashes in the transaction. /// Not available on EVM versions before Cancun. /// If used on unsupported EVM versions it will revert. function blobhashes(bytes32[] calldata hashes) external; /// Sets `block.chainid`. function chainId(uint256 newChainId) external; /// Clears all mocked calls. function clearMockedCalls() external; /// Clones a source account code, state, balance and nonce to a target account and updates in-memory EVM state. function cloneAccount(address source, address target) external; /// Sets `block.coinbase`. function coinbase(address newCoinbase) external; /// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork. function createFork(string calldata urlOrAlias) external returns (uint256 forkId); /// Creates a new fork with the given endpoint and block and returns the identifier of the fork. function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); /// Creates a new fork with the given endpoint and at the block the given transaction was mined in, /// replays all transaction mined in the block before the transaction, and returns the identifier of the fork. function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); /// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork. function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId); /// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork. function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); /// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in, /// replays all transaction mined in the block before the transaction, returns the identifier of the fork. function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); /// Sets an address' balance. function deal(address account, uint256 newBalance) external; /// Removes the snapshot with the given ID created by `snapshot`. /// Takes the snapshot ID to delete. /// Returns `true` if the snapshot was successfully deleted. /// Returns `false` if the snapshot does not exist. function deleteStateSnapshot(uint256 snapshotId) external returns (bool success); /// Removes _all_ snapshots previously created by `snapshot`. function deleteStateSnapshots() external; /// Sets `block.difficulty`. /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead. /// Reverts if used on unsupported EVM versions. function difficulty(uint256 newDifficulty) external; /// Dump a genesis JSON file's `allocs` to disk. function dumpState(string calldata pathToStateJson) external; /// Sets an address' code. function etch(address target, bytes calldata newRuntimeBytecode) external; /// Sets `block.basefee`. function fee(uint256 newBasefee) external; /// Gets the blockhashes from the current transaction. /// Not available on EVM versions before Cancun. /// If used on unsupported EVM versions it will revert. function getBlobhashes() external view returns (bytes32[] memory hashes); /// Returns true if the account is marked as persistent. function isPersistent(address account) external view returns (bool persistent); /// Load a genesis JSON file's `allocs` into the in-memory EVM state. function loadAllocs(string calldata pathToAllocsJson) external; /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup /// Meaning, changes made to the state of this account will be kept when switching forks. function makePersistent(address account) external; /// See `makePersistent(address)`. function makePersistent(address account0, address account1) external; /// See `makePersistent(address)`. function makePersistent(address account0, address account1, address account2) external; /// See `makePersistent(address)`. function makePersistent(address[] calldata accounts) external; /// Reverts a call to an address with specified revert data. function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; /// Reverts a call to an address with a specific `msg.value`, with specified revert data. function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) external; /// Mocks a call to an address, returning specified data. /// Calldata can either be strict or a partial match, e.g. if you only /// pass a Solidity selector to the expected calldata, then the entire Solidity /// function will be mocked. function mockCall(address callee, bytes calldata data, bytes calldata returnData) external; /// Mocks a call to an address with a specific `msg.value`, returning specified data. /// Calldata match takes precedence over `msg.value` in case of ambiguity. function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; /// Mocks multiple calls to an address, returning specified data for each call. function mockCalls(address callee, bytes calldata data, bytes[] calldata returnData) external; /// Mocks multiple calls to an address with a specific `msg.value`, returning specified data for each call. function mockCalls(address callee, uint256 msgValue, bytes calldata data, bytes[] calldata returnData) external; /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls /// `target` with the same calldata. This functionality is similar to a delegate call made to /// `target` contract from `callee`. /// Can be used to substitute a call to a function with another implementation that captures /// the primary logic of the original function but is easier to reason about. /// If calldata is not a strict match then partial match by selector is attempted. function mockFunction(address callee, address target, bytes calldata data) external; /// Sets the *next* call's `msg.sender` to be the input address. function prank(address msgSender) external; /// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input. function prank(address msgSender, address txOrigin) external; /// Sets `block.prevrandao`. /// Not available on EVM versions before Paris. Use `difficulty` instead. /// If used on unsupported EVM versions it will revert. function prevrandao(bytes32 newPrevrandao) external; /// Sets `block.prevrandao`. /// Not available on EVM versions before Paris. Use `difficulty` instead. /// If used on unsupported EVM versions it will revert. function prevrandao(uint256 newPrevrandao) external; /// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification. function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin); /// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts. function resetNonce(address account) external; /// Revert the state of the EVM to a previous snapshot /// Takes the snapshot ID to revert to. /// Returns `true` if the snapshot was successfully reverted. /// Returns `false` if the snapshot does not exist. /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteStateSnapshot`. function revertToState(uint256 snapshotId) external returns (bool success); /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots /// Takes the snapshot ID to revert to. /// Returns `true` if the snapshot was successfully reverted and deleted. /// Returns `false` if the snapshot does not exist. function revertToStateAndDelete(uint256 snapshotId) external returns (bool success); /// Revokes persistent status from the address, previously added via `makePersistent`. function revokePersistent(address account) external; /// See `revokePersistent(address)`. function revokePersistent(address[] calldata accounts) external; /// Sets `block.height`. function roll(uint256 newHeight) external; /// Updates the currently active fork to given block number /// This is similar to `roll` but for the currently active fork. function rollFork(uint256 blockNumber) external; /// Updates the currently active fork to given transaction. This will `rollFork` with the number /// of the block the transaction was mined in and replays all transaction mined before it in the block. function rollFork(bytes32 txHash) external; /// Updates the given fork to given block number. function rollFork(uint256 forkId, uint256 blockNumber) external; /// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block. function rollFork(uint256 forkId, bytes32 txHash) external; /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active. function selectFork(uint256 forkId) external; /// Set blockhash for the current block. /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`. function setBlockhash(uint256 blockNumber, bytes32 blockHash) external; /// Sets the nonce of an account. Must be higher than the current nonce of the account. function setNonce(address account, uint64 newNonce) external; /// Sets the nonce of an account to an arbitrary value. function setNonceUnsafe(address account, uint64 newNonce) external; /// Snapshot capture the gas usage of the last call by name from the callee perspective. function snapshotGasLastCall(string calldata name) external returns (uint256 gasUsed); /// Snapshot capture the gas usage of the last call by name in a group from the callee perspective. function snapshotGasLastCall(string calldata group, string calldata name) external returns (uint256 gasUsed); /// Snapshot the current state of the evm. /// Returns the ID of the snapshot that was created. /// To revert a snapshot use `revertToState`. function snapshotState() external returns (uint256 snapshotId); /// Snapshot capture an arbitrary numerical value by name. /// The group name is derived from the contract name. function snapshotValue(string calldata name, uint256 value) external; /// Snapshot capture an arbitrary numerical value by name in a group. function snapshotValue(string calldata group, string calldata name, uint256 value) external; /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called. function startPrank(address msgSender) external; /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input. function startPrank(address msgSender, address txOrigin) external; /// Start a snapshot capture of the current gas usage by name. /// The group name is derived from the contract name. function startSnapshotGas(string calldata name) external; /// Start a snapshot capture of the current gas usage by name in a group. function startSnapshotGas(string calldata group, string calldata name) external; /// Resets subsequent calls' `msg.sender` to be `address(this)`. function stopPrank() external; /// Stop the snapshot capture of the current gas by latest snapshot name, capturing the gas used since the start. function stopSnapshotGas() external returns (uint256 gasUsed); /// Stop the snapshot capture of the current gas usage by name, capturing the gas used since the start. /// The group name is derived from the contract name. function stopSnapshotGas(string calldata name) external returns (uint256 gasUsed); /// Stop the snapshot capture of the current gas usage by name in a group, capturing the gas used since the start. function stopSnapshotGas(string calldata group, string calldata name) external returns (uint256 gasUsed); /// Stores a value to an address' storage slot. function store(address target, bytes32 slot, bytes32 value) external; /// Fetches the given transaction from the active fork and executes it on the current state. function transact(bytes32 txHash) external; /// Fetches the given transaction from the given fork and executes it on the current state. function transact(uint256 forkId, bytes32 txHash) external; /// Sets `tx.gasprice`. function txGasPrice(uint256 newGasPrice) external; /// Sets `block.timestamp`. function warp(uint256 newTimestamp) external; /// `deleteSnapshot` is being deprecated in favor of `deleteStateSnapshot`. It will be removed in future versions. function deleteSnapshot(uint256 snapshotId) external returns (bool success); /// `deleteSnapshots` is being deprecated in favor of `deleteStateSnapshots`. It will be removed in future versions. function deleteSnapshots() external; /// `revertToAndDelete` is being deprecated in favor of `revertToStateAndDelete`. It will be removed in future versions. function revertToAndDelete(uint256 snapshotId) external returns (bool success); /// `revertTo` is being deprecated in favor of `revertToState`. It will be removed in future versions. function revertTo(uint256 snapshotId) external returns (bool success); /// `snapshot` is being deprecated in favor of `snapshotState`. It will be removed in future versions. function snapshot() external returns (uint256 snapshotId); // ======== Testing ======== /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external; /// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count) external; /// Expects a call to an address with the specified calldata. /// Calldata can either be a strict or a partial match. function expectCall(address callee, bytes calldata data) external; /// Expects given number of calls to an address with the specified calldata. function expectCall(address callee, bytes calldata data, uint64 count) external; /// Expects a call to an address with the specified `msg.value` and calldata. function expectCall(address callee, uint256 msgValue, bytes calldata data) external; /// Expects given number of calls to an address with the specified `msg.value` and calldata. function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external; /// Expect a call to an address with the specified `msg.value`, gas, and calldata. function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external; /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata. function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external; /// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external; /// Same as the previous method, but also checks supplied address against emitting contract. function expectEmitAnonymous( bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter ) external; /// Prepare an expected anonymous log with all topic and data checks enabled. /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if /// logs were emitted in the expected order with the expected topics and data. function expectEmitAnonymous() external; /// Same as the previous method, but also checks supplied address against emitting contract. function expectEmitAnonymous(address emitter) external; /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). /// Call this function, then emit an event, then call a function. Internally after the call, we check if /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external; /// Same as the previous method, but also checks supplied address against emitting contract. function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter) external; /// Prepare an expected log with all topic and data checks enabled. /// Call this function, then emit an event, then call a function. Internally after the call, we check if /// logs were emitted in the expected order with the expected topics and data. function expectEmit() external; /// Same as the previous method, but also checks supplied address against emitting contract. function expectEmit(address emitter) external; /// Expects an error on next call that starts with the revert data. function expectPartialRevert(bytes4 revertData) external; /// Expects an error on next call to reverter address, that starts with the revert data. function expectPartialRevert(bytes4 revertData, address reverter) external; /// Expects an error on next call with any revert data. function expectRevert() external; /// Expects an error on next call that exactly matches the revert data. function expectRevert(bytes4 revertData) external; /// Expects an error on next call that exactly matches the revert data. function expectRevert(bytes calldata revertData) external; /// Expects an error with any revert data on next call to reverter address. function expectRevert(address reverter) external; /// Expects an error from reverter address on next call, with any revert data. function expectRevert(bytes4 revertData, address reverter) external; /// Expects an error from reverter address on next call, that exactly matches the revert data. function expectRevert(bytes calldata revertData, address reverter) external; /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set. function expectSafeMemory(uint64 min, uint64 max) external; /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext. /// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges /// to the set. function expectSafeMemoryCall(uint64 min, uint64 max) external; /// Marks a test as skipped. Must be called at the top level of a test. function skip(bool skipTest) external; /// Marks a test as skipped with a reason. Must be called at the top level of a test. function skip(bool skipTest, string calldata reason) external; /// Stops all safe memory expectation in the current subcontext. function stopExpectSafeMemory() external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; library console { address constant CONSOLE_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; function _sendLogPayloadImplementation(bytes memory payload) internal view { address consoleAddress = CONSOLE_ADDRESS; /// @solidity memory-safe-assembly assembly { pop( staticcall( gas(), consoleAddress, add(payload, 32), mload(payload), 0, 0 ) ) } } function _castToPure( function(bytes memory) internal view fnIn ) internal pure returns (function(bytes memory) pure fnOut) { assembly { fnOut := fnIn } } function _sendLogPayload(bytes memory payload) internal pure { _castToPure(_sendLogPayloadImplementation)(payload); } function log() internal pure { _sendLogPayload(abi.encodeWithSignature("log()")); } function logInt(int256 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); } function logUint(uint256 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } function logString(string memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function logBool(bool p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function logAddress(address p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function logBytes(bytes memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); } function logBytes1(bytes1 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); } function logBytes2(bytes2 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); } function logBytes3(bytes3 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); } function logBytes4(bytes4 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); } function logBytes5(bytes5 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); } function logBytes6(bytes6 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); } function logBytes7(bytes7 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); } function logBytes8(bytes8 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); } function logBytes9(bytes9 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); } function logBytes10(bytes10 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); } function logBytes11(bytes11 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); } function logBytes12(bytes12 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); } function logBytes13(bytes13 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); } function logBytes14(bytes14 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); } function logBytes15(bytes15 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); } function logBytes16(bytes16 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); } function logBytes17(bytes17 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); } function logBytes18(bytes18 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); } function logBytes19(bytes19 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); } function logBytes20(bytes20 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); } function logBytes21(bytes21 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); } function logBytes22(bytes22 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); } function logBytes23(bytes23 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); } function logBytes24(bytes24 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); } function logBytes25(bytes25 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); } function logBytes26(bytes26 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); } function logBytes27(bytes27 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); } function logBytes28(bytes28 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); } function logBytes29(bytes29 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); } function logBytes30(bytes30 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); } function logBytes31(bytes31 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); } function logBytes32(bytes32 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); } function log(uint256 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } function log(int256 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); } function log(string memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function log(bool p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function log(address p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function log(uint256 p0, uint256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); } function log(uint256 p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); } function log(uint256 p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); } function log(uint256 p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); } function log(string memory p0, uint256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); } function log(string memory p0, int256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); } function log(string memory p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } function log(string memory p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); } function log(string memory p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); } function log(bool p0, uint256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); } function log(bool p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); } function log(bool p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); } function log(bool p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); } function log(address p0, uint256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); } function log(address p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); } function log(address p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); } function log(address p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); } function log(uint256 p0, uint256 p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); } function log(uint256 p0, string memory p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); } function log(uint256 p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); } function log(uint256 p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); } function log(uint256 p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); } function log(uint256 p0, bool p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); } function log(uint256 p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); } function log(uint256 p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); } function log(uint256 p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); } function log(uint256 p0, address p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); } function log(uint256 p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); } function log(uint256 p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); } function log(uint256 p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); } function log(string memory p0, uint256 p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); } function log(string memory p0, uint256 p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); } function log(string memory p0, uint256 p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); } function log(string memory p0, uint256 p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); } function log(string memory p0, string memory p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); } function log(string memory p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); } function log(string memory p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); } function log(string memory p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); } function log(string memory p0, bool p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); } function log(string memory p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); } function log(string memory p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); } function log(string memory p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); } function log(string memory p0, address p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); } function log(string memory p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); } function log(string memory p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); } function log(string memory p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); } function log(bool p0, uint256 p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); } function log(bool p0, uint256 p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); } function log(bool p0, uint256 p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); } function log(bool p0, uint256 p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); } function log(bool p0, string memory p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); } function log(bool p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); } function log(bool p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); } function log(bool p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); } function log(bool p0, bool p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); } function log(bool p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); } function log(bool p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); } function log(bool p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); } function log(bool p0, address p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); } function log(bool p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); } function log(bool p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); } function log(bool p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); } function log(address p0, uint256 p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); } function log(address p0, uint256 p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); } function log(address p0, uint256 p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); } function log(address p0, uint256 p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); } function log(address p0, string memory p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); } function log(address p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); } function log(address p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); } function log(address p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); } function log(address p0, bool p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); } function log(address p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); } function log(address p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); } function log(address p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); } function log(address p0, address p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); } function log(address p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); } function log(address p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); } function log(address p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; import {console as console2} from "./console.sol";
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; interface IERC165 { /// @notice Query if a contract implements an interface /// @param interfaceID The interface identifier, as specified in ERC-165 /// @dev Interface identification is specified in ERC-165. This function /// uses less than 30,000 gas. /// @return `true` if the contract implements `interfaceID` and /// `interfaceID` is not 0xffffffff, `false` otherwise function supportsInterface(bytes4 interfaceID) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /// @dev Interface of the ERC20 standard as defined in the EIP. /// @dev This includes the optional name, symbol, and decimals metadata. interface IERC20 { /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`). event Transfer(address indexed from, address indexed to, uint256 value); /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value` /// is the new allowance. event Approval(address indexed owner, address indexed spender, uint256 value); /// @notice Returns the amount of tokens in existence. function totalSupply() external view returns (uint256); /// @notice Returns the amount of tokens owned by `account`. function balanceOf(address account) external view returns (uint256); /// @notice Moves `amount` tokens from the caller's account to `to`. function transfer(address to, uint256 amount) external returns (bool); /// @notice Returns the remaining number of tokens that `spender` is allowed /// to spend on behalf of `owner` function allowance(address owner, address spender) external view returns (uint256); /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens. /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 function approve(address spender, uint256 amount) external returns (bool); /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism. /// `amount` is then deducted from the caller's allowance. function transferFrom(address from, address to, uint256 amount) external returns (bool); /// @notice Returns the name of the token. function name() external view returns (string memory); /// @notice Returns the symbol of the token. function symbol() external view returns (string memory); /// @notice Returns the decimals places of the token. function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import "./IERC165.sol"; /// @title ERC-721 Non-Fungible Token Standard /// @dev See https://eips.ethereum.org/EIPS/eip-721 /// Note: the ERC-165 identifier for this interface is 0x80ac58cd. interface IERC721 is IERC165 { /// @dev This emits when ownership of any NFT changes by any mechanism. /// This event emits when NFTs are created (`from` == 0) and destroyed /// (`to` == 0). Exception: during contract creation, any number of NFTs /// may be created and assigned without emitting Transfer. At the time of /// any transfer, the approved address for that NFT (if any) is reset to none. event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); /// @dev This emits when the approved address for an NFT is changed or /// reaffirmed. The zero address indicates there is no approved address. /// When a Transfer event emits, this also indicates that the approved /// address for that NFT (if any) is reset to none. event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); /// @dev This emits when an operator is enabled or disabled for an owner. /// The operator can manage all NFTs of the owner. event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); /// @notice Count all NFTs assigned to an owner /// @dev NFTs assigned to the zero address are considered invalid, and this /// function throws for queries about the zero address. /// @param _owner An address for whom to query the balance /// @return The number of NFTs owned by `_owner`, possibly zero function balanceOf(address _owner) external view returns (uint256); /// @notice Find the owner of an NFT /// @dev NFTs assigned to zero address are considered invalid, and queries /// about them do throw. /// @param _tokenId The identifier for an NFT /// @return The address of the owner of the NFT function ownerOf(uint256 _tokenId) external view returns (address); /// @notice Transfers the ownership of an NFT from one address to another address /// @dev Throws unless `msg.sender` is the current owner, an authorized /// operator, or the approved address for this NFT. Throws if `_from` is /// not the current owner. Throws if `_to` is the zero address. Throws if /// `_tokenId` is not a valid NFT. When transfer is complete, this function /// checks if `_to` is a smart contract (code size > 0). If so, it calls /// `onERC721Received` on `_to` and throws if the return value is not /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer /// @param data Additional data with no specified format, sent in call to `_to` function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; /// @notice Transfers the ownership of an NFT from one address to another address /// @dev This works identically to the other function with an extra data parameter, /// except this function just sets data to "". /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE /// THEY MAY BE PERMANENTLY LOST /// @dev Throws unless `msg.sender` is the current owner, an authorized /// operator, or the approved address for this NFT. Throws if `_from` is /// not the current owner. Throws if `_to` is the zero address. Throws if /// `_tokenId` is not a valid NFT. /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer function transferFrom(address _from, address _to, uint256 _tokenId) external payable; /// @notice Change or reaffirm the approved address for an NFT /// @dev The zero address indicates there is no approved address. /// Throws unless `msg.sender` is the current NFT owner, or an authorized /// operator of the current owner. /// @param _approved The new approved NFT controller /// @param _tokenId The NFT to approve function approve(address _approved, uint256 _tokenId) external payable; /// @notice Enable or disable approval for a third party ("operator") to manage /// all of `msg.sender`'s assets /// @dev Emits the ApprovalForAll event. The contract MUST allow /// multiple operators per owner. /// @param _operator Address to add to the set of authorized operators /// @param _approved True if the operator is approved, false to revoke approval function setApprovalForAll(address _operator, bool _approved) external; /// @notice Get the approved address for a single NFT /// @dev Throws if `_tokenId` is not a valid NFT. /// @param _tokenId The NFT to find the approved address for /// @return The approved address for this NFT, or the zero address if there is none function getApproved(uint256 _tokenId) external view returns (address); /// @notice Query if an address is an authorized operator for another address /// @param _owner The address that owns the NFTs /// @param _operator The address that acts on behalf of the owner /// @return True if `_operator` is an approved operator for `_owner`, false otherwise function isApprovedForAll(address _owner, address _operator) external view returns (bool); } /// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. interface IERC721TokenReceiver { /// @notice Handle the receipt of an NFT /// @dev The ERC721 smart contract calls this function on the recipient /// after a `transfer`. This function MAY throw to revert and reject the /// transfer. Return of other than the magic value MUST result in the /// transaction being reverted. /// Note: the contract address is always the message sender. /// @param _operator The address which called `safeTransferFrom` function /// @param _from The address which previously owned the token /// @param _tokenId The NFT identifier which is being transferred /// @param _data Additional data with no specified format /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` /// unless throwing function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns (bytes4); } /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension /// @dev See https://eips.ethereum.org/EIPS/eip-721 /// Note: the ERC-165 identifier for this interface is 0x5b5e139f. interface IERC721Metadata is IERC721 { /// @notice A descriptive name for a collection of NFTs in this contract function name() external view returns (string memory _name); /// @notice An abbreviated name for NFTs in this contract function symbol() external view returns (string memory _symbol); /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC /// 3986. The URI may point to a JSON file that conforms to the "ERC721 /// Metadata JSON Schema". function tokenURI(uint256 _tokenId) external view returns (string memory); } /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension /// @dev See https://eips.ethereum.org/EIPS/eip-721 /// Note: the ERC-165 identifier for this interface is 0x780e9d63. interface IERC721Enumerable is IERC721 { /// @notice Count NFTs tracked by this contract /// @return A count of valid NFTs tracked by this contract, where each one of /// them has an assigned and queryable owner not equal to the zero address function totalSupply() external view returns (uint256); /// @notice Enumerate valid NFTs /// @dev Throws if `_index` >= `totalSupply()`. /// @param _index A counter less than `totalSupply()` /// @return The token identifier for the `_index`th NFT, /// (sort order not specified) function tokenByIndex(uint256 _index) external view returns (uint256); /// @notice Enumerate NFTs assigned to an owner /// @dev Throws if `_index` >= `balanceOf(_owner)` or if /// `_owner` is the zero address, representing invalid NFTs. /// @param _owner An address where we are interested in NFTs owned by them /// @param _index A counter less than `balanceOf(_owner)` /// @return The token identifier for the `_index`th NFT assigned to `_owner`, /// (sort order not specified) function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; pragma experimental ABIEncoderV2; interface IMulticall3 { struct Call { address target; bytes callData; } struct Call3 { address target; bool allowFailure; bytes callData; } struct Call3Value { address target; bool allowFailure; uint256 value; bytes callData; } struct Result { bool success; bytes returnData; } function aggregate(Call[] calldata calls) external payable returns (uint256 blockNumber, bytes[] memory returnData); function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData); function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData); function blockAndAggregate(Call[] calldata calls) external payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); function getBasefee() external view returns (uint256 basefee); function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash); function getBlockNumber() external view returns (uint256 blockNumber); function getChainId() external view returns (uint256 chainid); function getCurrentBlockCoinbase() external view returns (address coinbase); function getCurrentBlockDifficulty() external view returns (uint256 difficulty); function getCurrentBlockGasLimit() external view returns (uint256 gaslimit); function getCurrentBlockTimestamp() external view returns (uint256 timestamp); function getEthBalance(address addr) external view returns (uint256 balance); function getLastBlockHash() external view returns (bytes32 blockHash); function tryAggregate(bool requireSuccess, Call[] calldata calls) external payable returns (Result[] memory returnData); function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) external payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; import {IERC20} from "../interfaces/IERC20.sol"; /// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production. /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol contract MockERC20 is IERC20 { /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string internal _name; string internal _symbol; uint8 internal _decimals; function name() external view override returns (string memory) { return _name; } function symbol() external view override returns (string memory) { return _symbol; } function decimals() external view override returns (uint8) { return _decimals; } /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal _totalSupply; mapping(address => uint256) internal _balanceOf; mapping(address => mapping(address => uint256)) internal _allowance; function totalSupply() external view override returns (uint256) { return _totalSupply; } function balanceOf(address owner) external view override returns (uint256) { return _balanceOf[owner]; } function allowance(address owner, address spender) external view override returns (uint256) { return _allowance[owner][spender]; } /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal INITIAL_CHAIN_ID; bytes32 internal INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// INITIALIZE //////////////////////////////////////////////////////////////*/ /// @dev A bool to track whether the contract has been initialized. bool private initialized; /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and /// syntaxes, we add an initialization function that can be called only once. function initialize(string memory name_, string memory symbol_, uint8 decimals_) public { require(!initialized, "ALREADY_INITIALIZED"); _name = name_; _symbol = symbol_; _decimals = decimals_; INITIAL_CHAIN_ID = _pureChainId(); INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); initialized = true; } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual override returns (bool) { _allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual override returns (bool) { _balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount); _balanceOf[to] = _add(_balanceOf[to], amount); emit Transfer(msg.sender, to, amount); return true; } function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != ~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount); _balanceOf[from] = _sub(_balanceOf[from], amount); _balanceOf[to] = _add(_balanceOf[to], amount); emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); _allowance[recoveredAddress][spender] = value; emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(_name)), keccak256("1"), _pureChainId(), address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { _totalSupply = _add(_totalSupply, amount); _balanceOf[to] = _add(_balanceOf[to], amount); emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { _balanceOf[from] = _sub(_balanceOf[from], amount); _totalSupply = _sub(_totalSupply, amount); emit Transfer(from, address(0), amount); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MATH LOGIC //////////////////////////////////////////////////////////////*/ function _add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "ERC20: addition overflow"); return c; } function _sub(uint256 a, uint256 b) internal pure returns (uint256) { require(a >= b, "ERC20: subtraction underflow"); return a - b; } /*////////////////////////////////////////////////////////////// HELPERS //////////////////////////////////////////////////////////////*/ // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We // can't simply access the chain ID in a normal view or pure function because the solc View Pure // Checker changed `chainid` from pure to view in 0.8.0. function _viewChainId() private view returns (uint256 chainId) { // Assembly required since `block.chainid` was introduced in 0.8.0. assembly { chainId := chainid() } address(this); // Silence warnings in older Solc versions. } function _pureChainId() private pure returns (uint256 chainId) { function() internal view returns (uint256) fnIn = _viewChainId; function() internal pure returns (uint256) pureChainId; assembly { pureChainId := fnIn } chainId = pureChainId(); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; import {IERC721Metadata, IERC721TokenReceiver} from "../interfaces/IERC721.sol"; /// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production. /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol contract MockERC721 is IERC721Metadata { /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string internal _name; string internal _symbol; function name() external view override returns (string memory) { return _name; } function symbol() external view override returns (string memory) { return _symbol; } function tokenURI(uint256 id) public view virtual override returns (string memory) {} /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual override returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _getApproved; mapping(address => mapping(address => bool)) internal _isApprovedForAll; function getApproved(uint256 id) public view virtual override returns (address) { return _getApproved[id]; } function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _isApprovedForAll[owner][operator]; } /*////////////////////////////////////////////////////////////// INITIALIZE //////////////////////////////////////////////////////////////*/ /// @dev A bool to track whether the contract has been initialized. bool private initialized; /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and /// syntaxes, we add an initialization function that can be called only once. function initialize(string memory name_, string memory symbol_) public { require(!initialized, "ALREADY_INITIALIZED"); _name = name_; _symbol = symbol_; initialized = true; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public payable virtual override { address owner = _ownerOf[id]; require(msg.sender == owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); _getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual override { _isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom(address from, address to, uint256 id) public payable virtual override { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || _isApprovedForAll[from][msg.sender] || msg.sender == _getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. _balanceOf[from]--; _balanceOf[to]++; _ownerOf[id] = to; delete _getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom(address from, address to, uint256 id) public payable virtual override { transferFrom(from, to, id); require( !_isContract(to) || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == IERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom(address from, address to, uint256 id, bytes memory data) public payable virtual override { transferFrom(from, to, id); require( !_isContract(to) || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == IERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721 || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. _balanceOf[to]++; _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); _balanceOf[owner]--; delete _ownerOf[id]; delete _getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( !_isContract(to) || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == IERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint(address to, uint256 id, bytes memory data) internal virtual { _mint(to, id); require( !_isContract(to) || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == IERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// HELPERS //////////////////////////////////////////////////////////////*/ function _isContract(address _addr) private view returns (bool) { uint256 codeLength; // Assembly required for versions < 0.8.0 to check extcodesize. assembly { codeLength := extcodesize(_addr) } return codeLength > 0; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; /// @author philogy <https://github.com/philogy> /// @dev Code generated automatically by script. library safeconsole { uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67; // Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374) // for the view-to-pure log trick. function _sendLogPayload(uint256 offset, uint256 size) private pure { function(uint256, uint256) internal view fnIn = _sendLogPayloadView; function(uint256, uint256) internal pure pureSendLogPayload; /// @solidity memory-safe-assembly assembly { pureSendLogPayload := fnIn } pureSendLogPayload(offset, size); } function _sendLogPayloadView(uint256 offset, uint256 size) private view { /// @solidity memory-safe-assembly assembly { pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0)) } } function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure { function(uint256, uint256, uint256) internal view fnIn = _memcopyView; function(uint256, uint256, uint256) internal pure pureMemcopy; /// @solidity memory-safe-assembly assembly { pureMemcopy := fnIn } pureMemcopy(fromOffset, toOffset, length); } function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view { /// @solidity memory-safe-assembly assembly { pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length)) } } function logMemory(uint256 offset, uint256 length) internal pure { if (offset >= 0x60) { // Sufficient memory before slice to prepare call header. bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(sub(offset, 0x60)) m1 := mload(sub(offset, 0x40)) m2 := mload(sub(offset, 0x20)) // Selector of `log(bytes)`. mstore(sub(offset, 0x60), 0x0be77f56) mstore(sub(offset, 0x40), 0x20) mstore(sub(offset, 0x20), length) } _sendLogPayload(offset - 0x44, length + 0x44); /// @solidity memory-safe-assembly assembly { mstore(sub(offset, 0x60), m0) mstore(sub(offset, 0x40), m1) mstore(sub(offset, 0x20), m2) } } else { // Insufficient space, so copy slice forward, add header and reverse. bytes32 m0; bytes32 m1; bytes32 m2; uint256 endOffset = offset + length; /// @solidity memory-safe-assembly assembly { m0 := mload(add(endOffset, 0x00)) m1 := mload(add(endOffset, 0x20)) m2 := mload(add(endOffset, 0x40)) } _memcopy(offset, offset + 0x60, length); /// @solidity memory-safe-assembly assembly { // Selector of `log(bytes)`. mstore(add(offset, 0x00), 0x0be77f56) mstore(add(offset, 0x20), 0x20) mstore(add(offset, 0x40), length) } _sendLogPayload(offset + 0x1c, length + 0x44); _memcopy(offset + 0x60, offset, length); /// @solidity memory-safe-assembly assembly { mstore(add(endOffset, 0x00), m0) mstore(add(endOffset, 0x20), m1) mstore(add(endOffset, 0x40), m2) } } } function log(address p0) internal pure { bytes32 m0; bytes32 m1; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) // Selector of `log(address)`. mstore(0x00, 0x2c2ecbc2) mstore(0x20, p0) } _sendLogPayload(0x1c, 0x24); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) } } function log(bool p0) internal pure { bytes32 m0; bytes32 m1; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) // Selector of `log(bool)`. mstore(0x00, 0x32458eed) mstore(0x20, p0) } _sendLogPayload(0x1c, 0x24); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) } } function log(uint256 p0) internal pure { bytes32 m0; bytes32 m1; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) // Selector of `log(uint256)`. mstore(0x00, 0xf82c50f1) mstore(0x20, p0) } _sendLogPayload(0x1c, 0x24); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) } } function log(bytes32 p0) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(string)`. mstore(0x00, 0x41304fac) mstore(0x20, 0x20) writeString(0x40, p0) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, address p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) // Selector of `log(address,address)`. mstore(0x00, 0xdaf0d4aa) mstore(0x20, p0) mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) } } function log(address p0, bool p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) // Selector of `log(address,bool)`. mstore(0x00, 0x75b605d3) mstore(0x20, p0) mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) } } function log(address p0, uint256 p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) // Selector of `log(address,uint256)`. mstore(0x00, 0x8309e8a8) mstore(0x20, p0) mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) } } function log(address p0, bytes32 p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,string)`. mstore(0x00, 0x759f86bb) mstore(0x20, p0) mstore(0x40, 0x40) writeString(0x60, p1) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) // Selector of `log(bool,address)`. mstore(0x00, 0x853c4849) mstore(0x20, p0) mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) } } function log(bool p0, bool p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) // Selector of `log(bool,bool)`. mstore(0x00, 0x2a110e83) mstore(0x20, p0) mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) } } function log(bool p0, uint256 p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) // Selector of `log(bool,uint256)`. mstore(0x00, 0x399174d3) mstore(0x20, p0) mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) } } function log(bool p0, bytes32 p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,string)`. mstore(0x00, 0x8feac525) mstore(0x20, p0) mstore(0x40, 0x40) writeString(0x60, p1) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) // Selector of `log(uint256,address)`. mstore(0x00, 0x69276c86) mstore(0x20, p0) mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) } } function log(uint256 p0, bool p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) // Selector of `log(uint256,bool)`. mstore(0x00, 0x1c9d7eb3) mstore(0x20, p0) mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) } } function log(uint256 p0, uint256 p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) // Selector of `log(uint256,uint256)`. mstore(0x00, 0xf666715a) mstore(0x20, p0) mstore(0x40, p1) } _sendLogPayload(0x1c, 0x44); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) } } function log(uint256 p0, bytes32 p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,string)`. mstore(0x00, 0x643fd0df) mstore(0x20, p0) mstore(0x40, 0x40) writeString(0x60, p1) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bytes32 p0, address p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(string,address)`. mstore(0x00, 0x319af333) mstore(0x20, 0x40) mstore(0x40, p1) writeString(0x60, p0) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bytes32 p0, bool p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(string,bool)`. mstore(0x00, 0xc3b55635) mstore(0x20, 0x40) mstore(0x40, p1) writeString(0x60, p0) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bytes32 p0, uint256 p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(string,uint256)`. mstore(0x00, 0xb60e72cc) mstore(0x20, 0x40) mstore(0x40, p1) writeString(0x60, p0) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bytes32 p0, bytes32 p1) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,string)`. mstore(0x00, 0x4b5c4277) mstore(0x20, 0x40) mstore(0x40, 0x80) writeString(0x60, p0) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, address p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(address,address,address)`. mstore(0x00, 0x018c84c2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, address p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(address,address,bool)`. mstore(0x00, 0xf2a66286) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, address p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(address,address,uint256)`. mstore(0x00, 0x17fe6185) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, address p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(address,address,string)`. mstore(0x00, 0x007150be) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x60) writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(address p0, bool p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(address,bool,address)`. mstore(0x00, 0xf11699ed) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, bool p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(address,bool,bool)`. mstore(0x00, 0xeb830c92) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, bool p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(address,bool,uint256)`. mstore(0x00, 0x9c4f99fb) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, bool p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(address,bool,string)`. mstore(0x00, 0x212255cc) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x60) writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(address p0, uint256 p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(address,uint256,address)`. mstore(0x00, 0x7bc0d848) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, uint256 p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(address,uint256,bool)`. mstore(0x00, 0x678209a8) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, uint256 p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(address,uint256,uint256)`. mstore(0x00, 0xb69bcaf6) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(address p0, uint256 p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(address,uint256,string)`. mstore(0x00, 0xa1f2e8aa) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x60) writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(address p0, bytes32 p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(address,string,address)`. mstore(0x00, 0xf08744e8) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, p2) writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(address p0, bytes32 p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(address,string,bool)`. mstore(0x00, 0xcf020fb1) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, p2) writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(address p0, bytes32 p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(address,string,uint256)`. mstore(0x00, 0x67dd6ff1) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, p2) writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(address p0, bytes32 p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) // Selector of `log(address,string,string)`. mstore(0x00, 0xfb772265) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, 0xa0) writeString(0x80, p1) writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) } } function log(bool p0, address p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(bool,address,address)`. mstore(0x00, 0xd2763667) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(bool p0, address p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(bool,address,bool)`. mstore(0x00, 0x18c9c746) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(bool p0, address p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(bool,address,uint256)`. mstore(0x00, 0x5f7b9afb) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(bool p0, address p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(bool,address,string)`. mstore(0x00, 0xde9a9270) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x60) writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bool p0, bool p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(bool,bool,address)`. mstore(0x00, 0x1078f68d) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(bool p0, bool p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(bool,bool,bool)`. mstore(0x00, 0x50709698) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(bool p0, bool p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(bool,bool,uint256)`. mstore(0x00, 0x12f21602) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(bool p0, bool p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(bool,bool,string)`. mstore(0x00, 0x2555fa46) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x60) writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bool p0, uint256 p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(bool,uint256,address)`. mstore(0x00, 0x088ef9d2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(bool p0, uint256 p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(bool,uint256,bool)`. mstore(0x00, 0xe8defba9) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(bool p0, uint256 p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(bool,uint256,uint256)`. mstore(0x00, 0x37103367) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(bool p0, uint256 p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(bool,uint256,string)`. mstore(0x00, 0xc3fc3970) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x60) writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bool p0, bytes32 p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(bool,string,address)`. mstore(0x00, 0x9591b953) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, p2) writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bool p0, bytes32 p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(bool,string,bool)`. mstore(0x00, 0xdbb4c247) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, p2) writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bool p0, bytes32 p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(bool,string,uint256)`. mstore(0x00, 0x1093ee11) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, p2) writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bool p0, bytes32 p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) // Selector of `log(bool,string,string)`. mstore(0x00, 0xb076847f) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, 0xa0) writeString(0x80, p1) writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) } } function log(uint256 p0, address p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(uint256,address,address)`. mstore(0x00, 0xbcfd9be0) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(uint256 p0, address p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(uint256,address,bool)`. mstore(0x00, 0x9b6ec042) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(uint256 p0, address p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(uint256,address,uint256)`. mstore(0x00, 0x5a9b5ed5) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(uint256 p0, address p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(uint256,address,string)`. mstore(0x00, 0x63cb41f9) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x60) writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(uint256 p0, bool p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(uint256,bool,address)`. mstore(0x00, 0x35085f7b) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(uint256 p0, bool p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(uint256,bool,bool)`. mstore(0x00, 0x20718650) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(uint256 p0, bool p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(uint256,bool,uint256)`. mstore(0x00, 0x20098014) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(uint256 p0, bool p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(uint256,bool,string)`. mstore(0x00, 0x85775021) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x60) writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(uint256 p0, uint256 p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(uint256,uint256,address)`. mstore(0x00, 0x5c96b331) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(uint256 p0, uint256 p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(uint256,uint256,bool)`. mstore(0x00, 0x4766da72) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(uint256 p0, uint256 p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) // Selector of `log(uint256,uint256,uint256)`. mstore(0x00, 0xd1ed7a3c) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) } _sendLogPayload(0x1c, 0x64); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) } } function log(uint256 p0, uint256 p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(uint256,uint256,string)`. mstore(0x00, 0x71d04af2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x60) writeString(0x80, p2) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(uint256 p0, bytes32 p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(uint256,string,address)`. mstore(0x00, 0x7afac959) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, p2) writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(uint256 p0, bytes32 p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(uint256,string,bool)`. mstore(0x00, 0x4ceda75a) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, p2) writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(uint256 p0, bytes32 p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(uint256,string,uint256)`. mstore(0x00, 0x37aa7d4c) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, p2) writeString(0x80, p1) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) // Selector of `log(uint256,string,string)`. mstore(0x00, 0xb115611f) mstore(0x20, p0) mstore(0x40, 0x60) mstore(0x60, 0xa0) writeString(0x80, p1) writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) } } function log(bytes32 p0, address p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(string,address,address)`. mstore(0x00, 0xfcec75e0) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, p2) writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bytes32 p0, address p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(string,address,bool)`. mstore(0x00, 0xc91d5ed4) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, p2) writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bytes32 p0, address p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(string,address,uint256)`. mstore(0x00, 0x0d26b925) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, p2) writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bytes32 p0, address p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) // Selector of `log(string,address,string)`. mstore(0x00, 0xe0e9ad4f) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, 0xa0) writeString(0x80, p0) writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) } } function log(bytes32 p0, bool p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(string,bool,address)`. mstore(0x00, 0x932bbb38) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, p2) writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bytes32 p0, bool p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(string,bool,bool)`. mstore(0x00, 0x850b7ad6) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, p2) writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bytes32 p0, bool p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(string,bool,uint256)`. mstore(0x00, 0xc95958d6) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, p2) writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bytes32 p0, bool p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) // Selector of `log(string,bool,string)`. mstore(0x00, 0xe298f47d) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, 0xa0) writeString(0x80, p0) writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) } } function log(bytes32 p0, uint256 p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(string,uint256,address)`. mstore(0x00, 0x1c7ec448) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, p2) writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bytes32 p0, uint256 p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(string,uint256,bool)`. mstore(0x00, 0xca7733b1) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, p2) writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bytes32 p0, uint256 p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) // Selector of `log(string,uint256,uint256)`. mstore(0x00, 0xca47c4eb) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, p2) writeString(0x80, p0) } _sendLogPayload(0x1c, 0xa4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) } } function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) // Selector of `log(string,uint256,string)`. mstore(0x00, 0x5970e089) mstore(0x20, 0x60) mstore(0x40, p1) mstore(0x60, 0xa0) writeString(0x80, p0) writeString(0xc0, p2) } _sendLogPayload(0x1c, 0xe4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) } } function log(bytes32 p0, bytes32 p1, address p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) // Selector of `log(string,string,address)`. mstore(0x00, 0x95ed0195) mstore(0x20, 0x60) mstore(0x40, 0xa0) mstore(0x60, p2) writeString(0x80, p0) writeString(0xc0, p1) } _sendLogPayload(0x1c, 0xe4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) } } function log(bytes32 p0, bytes32 p1, bool p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) // Selector of `log(string,string,bool)`. mstore(0x00, 0xb0e0f9b5) mstore(0x20, 0x60) mstore(0x40, 0xa0) mstore(0x60, p2) writeString(0x80, p0) writeString(0xc0, p1) } _sendLogPayload(0x1c, 0xe4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) } } function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) // Selector of `log(string,string,uint256)`. mstore(0x00, 0x5821efa1) mstore(0x20, 0x60) mstore(0x40, 0xa0) mstore(0x60, p2) writeString(0x80, p0) writeString(0xc0, p1) } _sendLogPayload(0x1c, 0xe4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) } } function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) // Selector of `log(string,string,string)`. mstore(0x00, 0x2ced7cef) mstore(0x20, 0x60) mstore(0x40, 0xa0) mstore(0x60, 0xe0) writeString(0x80, p0) writeString(0xc0, p1) writeString(0x100, p2) } _sendLogPayload(0x1c, 0x124); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) } } function log(address p0, address p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,address,address,address)`. mstore(0x00, 0x665bf134) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, address p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,address,address,bool)`. mstore(0x00, 0x0e378994) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, address p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,address,address,uint256)`. mstore(0x00, 0x94250d77) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, address p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,address,address,string)`. mstore(0x00, 0xf808da20) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, address p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,address,bool,address)`. mstore(0x00, 0x9f1bc36e) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, address p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,address,bool,bool)`. mstore(0x00, 0x2cd4134a) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, address p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,address,bool,uint256)`. mstore(0x00, 0x3971e78c) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, address p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,address,bool,string)`. mstore(0x00, 0xaa6540c8) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, address p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,address,uint256,address)`. mstore(0x00, 0x8da6def5) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, address p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,address,uint256,bool)`. mstore(0x00, 0x9b4254e2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,address,uint256,uint256)`. mstore(0x00, 0xbe553481) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,address,uint256,string)`. mstore(0x00, 0xfdb4f990) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, address p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,address,string,address)`. mstore(0x00, 0x8f736d16) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, address p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,address,string,bool)`. mstore(0x00, 0x6f1a594e) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,address,string,uint256)`. mstore(0x00, 0xef1cefe7) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(address,address,string,string)`. mstore(0x00, 0x21bdaf25) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, 0xc0) writeString(0xa0, p2) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(address p0, bool p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,bool,address,address)`. mstore(0x00, 0x660375dd) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, bool p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,bool,address,bool)`. mstore(0x00, 0xa6f50b0f) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, bool p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,bool,address,uint256)`. mstore(0x00, 0xa75c59de) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, bool p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,bool,address,string)`. mstore(0x00, 0x2dd778e6) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bool p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,bool,bool,address)`. mstore(0x00, 0xcf394485) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, bool p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,bool,bool,bool)`. mstore(0x00, 0xcac43479) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, bool p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,bool,bool,uint256)`. mstore(0x00, 0x8c4e5de6) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, bool p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,bool,bool,string)`. mstore(0x00, 0xdfc4a2e8) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bool p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,bool,uint256,address)`. mstore(0x00, 0xccf790a1) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, bool p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,bool,uint256,bool)`. mstore(0x00, 0xc4643e20) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,bool,uint256,uint256)`. mstore(0x00, 0x386ff5f4) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,bool,uint256,string)`. mstore(0x00, 0x0aa6cfad) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bool p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,bool,string,address)`. mstore(0x00, 0x19fd4956) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bool p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,bool,string,bool)`. mstore(0x00, 0x50ad461d) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,bool,string,uint256)`. mstore(0x00, 0x80e6a20b) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(address,bool,string,string)`. mstore(0x00, 0x475c5c33) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, 0xc0) writeString(0xa0, p2) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(address p0, uint256 p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,uint256,address,address)`. mstore(0x00, 0x478d1c62) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, uint256 p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,uint256,address,bool)`. mstore(0x00, 0xa1bcc9b3) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,uint256,address,uint256)`. mstore(0x00, 0x100f650e) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,uint256,address,string)`. mstore(0x00, 0x1da986ea) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, uint256 p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,uint256,bool,address)`. mstore(0x00, 0xa31bfdcc) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, uint256 p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,uint256,bool,bool)`. mstore(0x00, 0x3bf5e537) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,uint256,bool,uint256)`. mstore(0x00, 0x22f6b999) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,uint256,bool,string)`. mstore(0x00, 0xc5ad85f9) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,uint256,uint256,address)`. mstore(0x00, 0x20e3984d) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,uint256,uint256,bool)`. mstore(0x00, 0x66f1bc67) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(address,uint256,uint256,uint256)`. mstore(0x00, 0x34f0e636) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,uint256,uint256,string)`. mstore(0x00, 0x4a28c017) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,uint256,string,address)`. mstore(0x00, 0x5c430d47) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,uint256,string,bool)`. mstore(0x00, 0xcf18105c) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,uint256,string,uint256)`. mstore(0x00, 0xbf01f891) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(address,uint256,string,string)`. mstore(0x00, 0x88a8c406) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, 0xc0) writeString(0xa0, p2) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(address p0, bytes32 p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,string,address,address)`. mstore(0x00, 0x0d36fa20) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bytes32 p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,string,address,bool)`. mstore(0x00, 0x0df12b76) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,string,address,uint256)`. mstore(0x00, 0x457fe3cf) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(address,string,address,string)`. mstore(0x00, 0xf7e36245) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p1) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(address p0, bytes32 p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,string,bool,address)`. mstore(0x00, 0x205871c2) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bytes32 p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,string,bool,bool)`. mstore(0x00, 0x5f1d5c9f) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,string,bool,uint256)`. mstore(0x00, 0x515e38b6) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(address,string,bool,string)`. mstore(0x00, 0xbc0b61fe) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p1) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,string,uint256,address)`. mstore(0x00, 0x63183678) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,string,uint256,bool)`. mstore(0x00, 0x0ef7e050) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(address,string,uint256,uint256)`. mstore(0x00, 0x1dc8e1b8) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(address,string,uint256,string)`. mstore(0x00, 0x448830a8) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p1) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(address,string,string,address)`. mstore(0x00, 0xa04e2f87) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p1) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(address,string,string,bool)`. mstore(0x00, 0x35a5071f) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p1) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(address,string,string,uint256)`. mstore(0x00, 0x159f8927) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p1) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(address,string,string,string)`. mstore(0x00, 0x5d02c50b) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, 0x100) writeString(0xa0, p1) writeString(0xe0, p2) writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bool p0, address p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,address,address,address)`. mstore(0x00, 0x1d14d001) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,address,address,bool)`. mstore(0x00, 0x46600be0) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,address,address,uint256)`. mstore(0x00, 0x0c66d1be) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,address,address,string)`. mstore(0x00, 0xd812a167) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, address p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,address,bool,address)`. mstore(0x00, 0x1c41a336) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,address,bool,bool)`. mstore(0x00, 0x6a9c478b) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,address,bool,uint256)`. mstore(0x00, 0x07831502) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,address,bool,string)`. mstore(0x00, 0x4a66cb34) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, address p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,address,uint256,address)`. mstore(0x00, 0x136b05dd) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,address,uint256,bool)`. mstore(0x00, 0xd6019f1c) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,address,uint256,uint256)`. mstore(0x00, 0x7bf181a1) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,address,uint256,string)`. mstore(0x00, 0x51f09ff8) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, address p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,address,string,address)`. mstore(0x00, 0x6f7c603e) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, address p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,address,string,bool)`. mstore(0x00, 0xe2bfd60b) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,address,string,uint256)`. mstore(0x00, 0xc21f64c7) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(bool,address,string,string)`. mstore(0x00, 0xa73c1db6) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, 0xc0) writeString(0xa0, p2) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bool p0, bool p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,bool,address,address)`. mstore(0x00, 0xf4880ea4) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, bool p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,bool,address,bool)`. mstore(0x00, 0xc0a302d8) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, bool p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,bool,address,uint256)`. mstore(0x00, 0x4c123d57) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, bool p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,bool,address,string)`. mstore(0x00, 0xa0a47963) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bool p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,bool,bool,address)`. mstore(0x00, 0x8c329b1a) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, bool p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,bool,bool,bool)`. mstore(0x00, 0x3b2a5ce0) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,bool,bool,uint256)`. mstore(0x00, 0x6d7045c1) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,bool,bool,string)`. mstore(0x00, 0x2ae408d4) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bool p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,bool,uint256,address)`. mstore(0x00, 0x54a7a9a0) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,bool,uint256,bool)`. mstore(0x00, 0x619e4d0e) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,bool,uint256,uint256)`. mstore(0x00, 0x0bb00eab) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,bool,uint256,string)`. mstore(0x00, 0x7dd4d0e0) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bool p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,bool,string,address)`. mstore(0x00, 0xf9ad2b89) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,bool,string,bool)`. mstore(0x00, 0xb857163a) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,bool,string,uint256)`. mstore(0x00, 0xe3a9ca2f) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(bool,bool,string,string)`. mstore(0x00, 0x6d1e8751) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, 0xc0) writeString(0xa0, p2) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bool p0, uint256 p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,uint256,address,address)`. mstore(0x00, 0x26f560a8) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, uint256 p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,uint256,address,bool)`. mstore(0x00, 0xb4c314ff) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,uint256,address,uint256)`. mstore(0x00, 0x1537dc87) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,uint256,address,string)`. mstore(0x00, 0x1bb3b09a) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, uint256 p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,uint256,bool,address)`. mstore(0x00, 0x9acd3616) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,uint256,bool,bool)`. mstore(0x00, 0xceb5f4d7) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,uint256,bool,uint256)`. mstore(0x00, 0x7f9bbca2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,uint256,bool,string)`. mstore(0x00, 0x9143dbb1) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,uint256,uint256,address)`. mstore(0x00, 0x00dd87b9) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,uint256,uint256,bool)`. mstore(0x00, 0xbe984353) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(bool,uint256,uint256,uint256)`. mstore(0x00, 0x374bb4b2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,uint256,uint256,string)`. mstore(0x00, 0x8e69fb5d) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,uint256,string,address)`. mstore(0x00, 0xfedd1fff) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,uint256,string,bool)`. mstore(0x00, 0xe5e70b2b) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,uint256,string,uint256)`. mstore(0x00, 0x6a1199e2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(bool,uint256,string,string)`. mstore(0x00, 0xf5bc2249) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, 0xc0) writeString(0xa0, p2) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bool p0, bytes32 p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,string,address,address)`. mstore(0x00, 0x2b2b18dc) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bytes32 p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,string,address,bool)`. mstore(0x00, 0x6dd434ca) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,string,address,uint256)`. mstore(0x00, 0xa5cada94) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(bool,string,address,string)`. mstore(0x00, 0x12d6c788) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p1) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bool p0, bytes32 p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,string,bool,address)`. mstore(0x00, 0x538e06ab) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,string,bool,bool)`. mstore(0x00, 0xdc5e935b) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,string,bool,uint256)`. mstore(0x00, 0x1606a393) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(bool,string,bool,string)`. mstore(0x00, 0x483d0416) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p1) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,string,uint256,address)`. mstore(0x00, 0x1596a1ce) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,string,uint256,bool)`. mstore(0x00, 0x6b0e5d53) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(bool,string,uint256,uint256)`. mstore(0x00, 0x28863fcb) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(bool,string,uint256,string)`. mstore(0x00, 0x1ad96de6) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p1) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(bool,string,string,address)`. mstore(0x00, 0x97d394d8) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p1) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(bool,string,string,bool)`. mstore(0x00, 0x1e4b87e5) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p1) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(bool,string,string,uint256)`. mstore(0x00, 0x7be0c3eb) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p1) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(bool,string,string,string)`. mstore(0x00, 0x1762e32a) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, 0x100) writeString(0xa0, p1) writeString(0xe0, p2) writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(uint256 p0, address p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,address,address,address)`. mstore(0x00, 0x2488b414) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,address,address,bool)`. mstore(0x00, 0x091ffaf5) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,address,address,uint256)`. mstore(0x00, 0x736efbb6) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,address,address,string)`. mstore(0x00, 0x031c6f73) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, address p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,address,bool,address)`. mstore(0x00, 0xef72c513) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,address,bool,bool)`. mstore(0x00, 0xe351140f) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,address,bool,uint256)`. mstore(0x00, 0x5abd992a) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,address,bool,string)`. mstore(0x00, 0x90fb06aa) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,address,uint256,address)`. mstore(0x00, 0x15c127b5) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,address,uint256,bool)`. mstore(0x00, 0x5f743a7c) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,address,uint256,uint256)`. mstore(0x00, 0x0c9cd9c1) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,address,uint256,string)`. mstore(0x00, 0xddb06521) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,address,string,address)`. mstore(0x00, 0x9cba8fff) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,address,string,bool)`. mstore(0x00, 0xcc32ab07) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,address,string,uint256)`. mstore(0x00, 0x46826b5d) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(uint256,address,string,string)`. mstore(0x00, 0x3e128ca3) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, 0xc0) writeString(0xa0, p2) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(uint256 p0, bool p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,bool,address,address)`. mstore(0x00, 0xa1ef4cbb) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, bool p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,bool,address,bool)`. mstore(0x00, 0x454d54a5) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,bool,address,uint256)`. mstore(0x00, 0x078287f5) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,bool,address,string)`. mstore(0x00, 0xade052c7) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bool p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,bool,bool,address)`. mstore(0x00, 0x69640b59) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,bool,bool,bool)`. mstore(0x00, 0xb6f577a1) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,bool,bool,uint256)`. mstore(0x00, 0x7464ce23) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,bool,bool,string)`. mstore(0x00, 0xdddb9561) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,bool,uint256,address)`. mstore(0x00, 0x88cb6041) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,bool,uint256,bool)`. mstore(0x00, 0x91a02e2a) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,bool,uint256,uint256)`. mstore(0x00, 0xc6acc7a8) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,bool,uint256,string)`. mstore(0x00, 0xde03e774) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,bool,string,address)`. mstore(0x00, 0xef529018) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,bool,string,bool)`. mstore(0x00, 0xeb928d7f) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,bool,string,uint256)`. mstore(0x00, 0x2c1d0746) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(uint256,bool,string,string)`. mstore(0x00, 0x68c8b8bd) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, 0xc0) writeString(0xa0, p2) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,uint256,address,address)`. mstore(0x00, 0x56a5d1b1) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,uint256,address,bool)`. mstore(0x00, 0x15cac476) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,uint256,address,uint256)`. mstore(0x00, 0x88f6e4b2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,uint256,address,string)`. mstore(0x00, 0x6cde40b8) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,uint256,bool,address)`. mstore(0x00, 0x9a816a83) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,uint256,bool,bool)`. mstore(0x00, 0xab085ae6) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,uint256,bool,uint256)`. mstore(0x00, 0xeb7f6fd2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,uint256,bool,string)`. mstore(0x00, 0xa5b4fc99) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,uint256,uint256,address)`. mstore(0x00, 0xfa8185af) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,uint256,uint256,bool)`. mstore(0x00, 0xc598d185) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; /// @solidity memory-safe-assembly assembly { m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) // Selector of `log(uint256,uint256,uint256,uint256)`. mstore(0x00, 0x193fb800) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) } _sendLogPayload(0x1c, 0x84); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) } } function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,uint256,uint256,string)`. mstore(0x00, 0x59cfcbe3) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0x80) writeString(0xa0, p3) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,uint256,string,address)`. mstore(0x00, 0x42d21db7) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,uint256,string,bool)`. mstore(0x00, 0x7af6ab25) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,uint256,string,uint256)`. mstore(0x00, 0x5da297eb) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, p3) writeString(0xa0, p2) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(uint256,uint256,string,string)`. mstore(0x00, 0x27d8afd2) mstore(0x20, p0) mstore(0x40, p1) mstore(0x60, 0x80) mstore(0x80, 0xc0) writeString(0xa0, p2) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,string,address,address)`. mstore(0x00, 0x6168ed61) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,string,address,bool)`. mstore(0x00, 0x90c30a56) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,string,address,uint256)`. mstore(0x00, 0xe8d3018d) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(uint256,string,address,string)`. mstore(0x00, 0x9c3adfa1) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p1) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,string,bool,address)`. mstore(0x00, 0xae2ec581) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,string,bool,bool)`. mstore(0x00, 0xba535d9c) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,string,bool,uint256)`. mstore(0x00, 0xcf009880) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(uint256,string,bool,string)`. mstore(0x00, 0xd2d423cd) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p1) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,string,uint256,address)`. mstore(0x00, 0x3b2279b4) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,string,uint256,bool)`. mstore(0x00, 0x691a8f74) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(uint256,string,uint256,uint256)`. mstore(0x00, 0x82c25b74) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p1) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(uint256,string,uint256,string)`. mstore(0x00, 0xb7b914ca) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p1) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(uint256,string,string,address)`. mstore(0x00, 0xd583c602) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p1) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(uint256,string,string,bool)`. mstore(0x00, 0xb3a6b6bd) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p1) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(uint256,string,string,uint256)`. mstore(0x00, 0xb028c9bd) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p1) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(uint256,string,string,string)`. mstore(0x00, 0x21ad0683) mstore(0x20, p0) mstore(0x40, 0x80) mstore(0x60, 0xc0) mstore(0x80, 0x100) writeString(0xa0, p1) writeString(0xe0, p2) writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, address p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,address,address,address)`. mstore(0x00, 0xed8f28f6) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, address p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,address,address,bool)`. mstore(0x00, 0xb59dbd60) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,address,address,uint256)`. mstore(0x00, 0x8ef3f399) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,address,address,string)`. mstore(0x00, 0x800a1c67) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p0) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, address p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,address,bool,address)`. mstore(0x00, 0x223603bd) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, address p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,address,bool,bool)`. mstore(0x00, 0x79884c2b) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,address,bool,uint256)`. mstore(0x00, 0x3e9f866a) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,address,bool,string)`. mstore(0x00, 0x0454c079) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p0) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,address,uint256,address)`. mstore(0x00, 0x63fb8bc5) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,address,uint256,bool)`. mstore(0x00, 0xfc4845f0) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,address,uint256,uint256)`. mstore(0x00, 0xf8f51b1e) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,address,uint256,string)`. mstore(0x00, 0x5a477632) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p0) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,address,string,address)`. mstore(0x00, 0xaabc9a31) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,address,string,bool)`. mstore(0x00, 0x5f15d28c) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,address,string,uint256)`. mstore(0x00, 0x91d1112e) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(string,address,string,string)`. mstore(0x00, 0x245986f2) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, 0x100) writeString(0xa0, p0) writeString(0xe0, p2) writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, bool p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,bool,address,address)`. mstore(0x00, 0x33e9dd1d) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, bool p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,bool,address,bool)`. mstore(0x00, 0x958c28c6) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,bool,address,uint256)`. mstore(0x00, 0x5d08bb05) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,bool,address,string)`. mstore(0x00, 0x2d8e33a4) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p0) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bool p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,bool,bool,address)`. mstore(0x00, 0x7190a529) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,bool,bool,bool)`. mstore(0x00, 0x895af8c5) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,bool,bool,uint256)`. mstore(0x00, 0x8e3f78a9) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,bool,bool,string)`. mstore(0x00, 0x9d22d5dd) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p0) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,bool,uint256,address)`. mstore(0x00, 0x935e09bf) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,bool,uint256,bool)`. mstore(0x00, 0x8af7cf8a) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,bool,uint256,uint256)`. mstore(0x00, 0x64b5bb67) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,bool,uint256,string)`. mstore(0x00, 0x742d6ee7) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p0) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,bool,string,address)`. mstore(0x00, 0xe0625b29) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,bool,string,bool)`. mstore(0x00, 0x3f8a701d) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,bool,string,uint256)`. mstore(0x00, 0x24f91465) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(string,bool,string,string)`. mstore(0x00, 0xa826caeb) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, 0x100) writeString(0xa0, p0) writeString(0xe0, p2) writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,uint256,address,address)`. mstore(0x00, 0x5ea2b7ae) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,uint256,address,bool)`. mstore(0x00, 0x82112a42) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,uint256,address,uint256)`. mstore(0x00, 0x4f04fdc6) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,uint256,address,string)`. mstore(0x00, 0x9ffb2f93) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p0) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,uint256,bool,address)`. mstore(0x00, 0xe0e95b98) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,uint256,bool,bool)`. mstore(0x00, 0x354c36d6) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,uint256,bool,uint256)`. mstore(0x00, 0xe41b6f6f) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,uint256,bool,string)`. mstore(0x00, 0xabf73a98) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p0) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,uint256,uint256,address)`. mstore(0x00, 0xe21de278) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,uint256,uint256,bool)`. mstore(0x00, 0x7626db92) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) // Selector of `log(string,uint256,uint256,uint256)`. mstore(0x00, 0xa7a87853) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) } _sendLogPayload(0x1c, 0xc4); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) } } function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,uint256,uint256,string)`. mstore(0x00, 0x854b3496) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, p2) mstore(0x80, 0xc0) writeString(0xa0, p0) writeString(0xe0, p3) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,uint256,string,address)`. mstore(0x00, 0x7c4632a4) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,uint256,string,bool)`. mstore(0x00, 0x7d24491d) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,uint256,string,uint256)`. mstore(0x00, 0xc67ea9d1) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p2) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(string,uint256,string,string)`. mstore(0x00, 0x5ab84e1f) mstore(0x20, 0x80) mstore(0x40, p1) mstore(0x60, 0xc0) mstore(0x80, 0x100) writeString(0xa0, p0) writeString(0xe0, p2) writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,string,address,address)`. mstore(0x00, 0x439c7bef) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,string,address,bool)`. mstore(0x00, 0x5ccd4e37) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,string,address,uint256)`. mstore(0x00, 0x7cc3c607) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(string,string,address,string)`. mstore(0x00, 0xeb1bff80) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, 0x100) writeString(0xa0, p0) writeString(0xe0, p1) writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,string,bool,address)`. mstore(0x00, 0xc371c7db) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,string,bool,bool)`. mstore(0x00, 0x40785869) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,string,bool,uint256)`. mstore(0x00, 0xd6aefad2) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(string,string,bool,string)`. mstore(0x00, 0x5e84b0ea) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, 0x100) writeString(0xa0, p0) writeString(0xe0, p1) writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,string,uint256,address)`. mstore(0x00, 0x1023f7b2) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,string,uint256,bool)`. mstore(0x00, 0xc3a8a654) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) // Selector of `log(string,string,uint256,uint256)`. mstore(0x00, 0xf45d7d2c) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) } _sendLogPayload(0x1c, 0x104); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) } } function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(string,string,uint256,string)`. mstore(0x00, 0x5d1a971a) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, p2) mstore(0x80, 0x100) writeString(0xa0, p0) writeString(0xe0, p1) writeString(0x120, p3) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(string,string,string,address)`. mstore(0x00, 0x6d572f44) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, 0x100) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) writeString(0x120, p2) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(string,string,string,bool)`. mstore(0x00, 0x2c1754ed) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, 0x100) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) writeString(0x120, p2) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) // Selector of `log(string,string,string,uint256)`. mstore(0x00, 0x8eafb02b) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, 0x100) mstore(0x80, p3) writeString(0xa0, p0) writeString(0xe0, p1) writeString(0x120, p2) } _sendLogPayload(0x1c, 0x144); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) } } function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { bytes32 m0; bytes32 m1; bytes32 m2; bytes32 m3; bytes32 m4; bytes32 m5; bytes32 m6; bytes32 m7; bytes32 m8; bytes32 m9; bytes32 m10; bytes32 m11; bytes32 m12; /// @solidity memory-safe-assembly assembly { function writeString(pos, w) { let length := 0 for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } mstore(pos, length) let shift := sub(256, shl(3, length)) mstore(add(pos, 0x20), shl(shift, shr(shift, w))) } m0 := mload(0x00) m1 := mload(0x20) m2 := mload(0x40) m3 := mload(0x60) m4 := mload(0x80) m5 := mload(0xa0) m6 := mload(0xc0) m7 := mload(0xe0) m8 := mload(0x100) m9 := mload(0x120) m10 := mload(0x140) m11 := mload(0x160) m12 := mload(0x180) // Selector of `log(string,string,string,string)`. mstore(0x00, 0xde68f20a) mstore(0x20, 0x80) mstore(0x40, 0xc0) mstore(0x60, 0x100) mstore(0x80, 0x140) writeString(0xa0, p0) writeString(0xe0, p1) writeString(0x120, p2) writeString(0x160, p3) } _sendLogPayload(0x1c, 0x184); /// @solidity memory-safe-assembly assembly { mstore(0x00, m0) mstore(0x20, m1) mstore(0x40, m2) mstore(0x60, m3) mstore(0x80, m4) mstore(0xa0, m5) mstore(0xc0, m6) mstore(0xe0, m7) mstore(0x100, m8) mstore(0x120, m9) mstore(0x140, m10) mstore(0x160, m11) mstore(0x180, m12) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.20; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.20; import {Proxy} from "../Proxy.sol"; import {ERC1967Utils} from "./ERC1967Utils.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy { /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`. * * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. * * Requirements: * * - If `data` is empty, `msg.value` must be zero. */ constructor(address implementation, bytes memory _data) payable { ERC1967Utils.upgradeToAndCall(implementation, _data); } /** * @dev Returns the current implementation address. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function _implementation() internal view virtual override returns (address) { return ERC1967Utils.getImplementation(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.20; import {IBeacon} from "../beacon/IBeacon.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. */ library ERC1967Utils { // We re-declare ERC-1967 events here because they can't be used directly from IERC1967. // This will be fixed in Solidity 0.8.21. At that point we should remove these events. /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol) pragma solidity ^0.8.20; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback * function and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/ProxyAdmin.sol) pragma solidity ^0.8.20; import {ITransparentUpgradeableProxy} from "./TransparentUpgradeableProxy.sol"; import {Ownable} from "../../access/Ownable.sol"; /** * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. */ contract ProxyAdmin is Ownable { /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgrade(address)` * and `upgradeAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev Sets the initial owner who can perform upgrades. */ constructor(address initialOwner) Ownable(initialOwner) {} /** * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. * See {TransparentUpgradeableProxy-_dispatchUpgradeToAndCall}. * * Requirements: * * - This contract must be the admin of `proxy`. * - If `data` is empty, `msg.value` must be zero. */ function upgradeAndCall( ITransparentUpgradeableProxy proxy, address implementation, bytes memory data ) public payable virtual onlyOwner { proxy.upgradeToAndCall{value: msg.value}(implementation, data); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.26; import {IPermit2, Permit2Deployer} from '../../src/briefcase/deployers/permit2/Permit2Deployer.sol'; import {SwapRouter02Deployer} from '../../src/briefcase/deployers/swap-router-contracts/SwapRouter02Deployer.sol'; import {UniversalRouterDeployer} from '../../src/briefcase/deployers/universal-router/UniversalRouterDeployer.sol'; import {FeeCollectorDeployer} from '../../src/briefcase/deployers/util-contracts/FeeCollectorDeployer.sol'; import {FeeOnTransferDetectorDeployer} from '../../src/briefcase/deployers/util-contracts/FeeOnTransferDetectorDeployer.sol'; import {UniswapV2FactoryDeployer} from '../../src/briefcase/deployers/v2-core/UniswapV2FactoryDeployer.sol'; import {UniswapV2Router02Deployer} from '../../src/briefcase/deployers/v2-periphery/UniswapV2Router02Deployer.sol'; import { IUniswapV3Factory, UniswapV3FactoryDeployer } from '../../src/briefcase/deployers/v3-core/UniswapV3FactoryDeployer.sol'; import {NonfungiblePositionManagerDeployer} from '../../src/briefcase/deployers/v3-periphery/NonfungiblePositionManagerDeployer.sol'; import {NonfungibleTokenPositionDescriptorDeployer} from '../../src/briefcase/deployers/v3-periphery/NonfungibleTokenPositionDescriptorDeployer.sol'; import {NonfungibleTokenPositionDescriptorDeployer} from '../../src/briefcase/deployers/v3-periphery/NonfungibleTokenPositionDescriptorDeployer.sol'; import {QuoterV2Deployer} from '../../src/briefcase/deployers/v3-periphery/QuoterV2Deployer.sol'; import {SwapRouterDeployer} from '../../src/briefcase/deployers/v3-periphery/SwapRouterDeployer.sol'; import {TickLensDeployer} from '../../src/briefcase/deployers/v3-periphery/TickLensDeployer.sol'; import {UniswapInterfaceMulticallDeployer} from '../../src/briefcase/deployers/v3-periphery/UniswapInterfaceMulticallDeployer.sol'; import {V3MigratorDeployer} from '../../src/briefcase/deployers/v3-periphery/V3MigratorDeployer.sol'; import {QuoterDeployer} from '../../src/briefcase/deployers/view-quoter-v3/QuoterDeployer.sol'; import {TransparentUpgradeableProxy} from 'lib/v4-core/lib/openzeppelin-contracts/contracts/proxy/transparent/TransparentUpgradeableProxy.sol'; import {PoolManagerDeployer} from '../../src/briefcase/deployers/v4-core/PoolManagerDeployer.sol'; import {PositionDescriptorDeployer} from '../../src/briefcase/deployers/v4-periphery/PositionDescriptorDeployer.sol'; import {PositionManagerDeployer} from '../../src/briefcase/deployers/v4-periphery/PositionManagerDeployer.sol'; import {StateViewDeployer} from '../../src/briefcase/deployers/v4-periphery/StateViewDeployer.sol'; import {V4QuoterDeployer} from '../../src/briefcase/deployers/v4-periphery/V4QuoterDeployer.sol'; import {Script, console2 as console, stdJson} from 'forge-std/Script.sol'; import {VmSafe} from 'forge-std/Vm.sol'; contract Deploy is Script { using stdJson for string; address _weth; string config; address permit2; address v2Factory; address v3Factory; address nonfungiblePositionManager; address poolManager; address positionManager; address universalRouter; function run() public { config = vm.readFile(string.concat('./script/deploy/tasks/', vm.toString(block.chainid), '/task-pending.json')); vm.startBroadcast(); deployPermit2(); deployV2Contracts(); deployV3Contracts(); deployV4Contracts(); deployViewQuoterV3(); deploySwapRouters(); deployUniversalRouter(); deployUtilsContracts(); vm.stopBroadcast(); if (vm.isContext(VmSafe.ForgeContext.ScriptBroadcast) && config.readBool('.rename')) { uint256 timestamp = vm.getBlockTimestamp(); string memory output_filename = string.concat( './script/deploy/tasks/', vm.toString(block.chainid), '/task-', vm.toString(timestamp), '.json' ); vm.writeFile(output_filename, config); } } function deployV2Contracts() private { if (!config.readBoolOr('.protocols.v2.deploy', false)) return; bool deployUniswapV2Factory = config.readBoolOr('.protocols.v2.contracts.UniswapV2Factory.deploy', false); bool deployUniswapV2Router02 = config.readBoolOr('.protocols.v2.contracts.UniswapV2Router02.deploy', false); // Params address feeToSetter; if (deployUniswapV2Factory) { feeToSetter = config.readAddress('.protocols.v2.contracts.UniswapV2Factory.params.feeToSetter.value'); console.log('deploying Uniswap v2 Factory'); v2Factory = address(UniswapV2FactoryDeployer.deploy(feeToSetter)); } if (deployUniswapV2Router02) { if (!deployUniswapV2Factory) { v2Factory = config.readAddress('.protocols.v2.contracts.UniswapV2Factory.address'); } console.log('deploying Uniswap v2 Router 02'); UniswapV2Router02Deployer.deploy(v2Factory, weth()); } } function deployV3Contracts() private { if (!config.readBoolOr('.protocols.v3.deploy', false)) return; bool deployUniswapV3Factory = config.readBoolOr('.protocols.v3.contracts.UniswapV3Factory.deploy', false); bool deployUniswapInterfaceMulticall = config.readBoolOr('.protocols.v3.contracts.UniswapInterfaceMulticall.deploy', false); bool deployQuoterV2 = config.readBoolOr('.protocols.v3.contracts.QuoterV2.deploy', false); bool deployTickLens = config.readBoolOr('.protocols.v3.contracts.TickLens.deploy', false); bool deployNonfungibleTokenPositionDescriptor = config.readBoolOr('.protocols.v3.contracts.NonfungibleTokenPositionDescriptor.deploy', false); bool deployNonfungiblePositionManager = config.readBoolOr('.protocols.v3.contracts.NonfungiblePositionManager.deploy', false); bool deployV3Migrator = config.readBoolOr('.protocols.v3.contracts.V3Migrator.deploy', false); bool deploySwapRouter = config.readBoolOr('.protocols.v3.contracts.SwapRouter.deploy', false); // Params address nftDescriptor; if (deployUniswapV3Factory) { address initialOwner = config.readAddress('.protocols.v3.contracts.UniswapV3Factory.params.initialOwner.value'); console.log('deploying Uniswap v3 Factory'); IUniswapV3Factory v3Factory_ = UniswapV3FactoryDeployer.deploy(); v3Factory_.enableFeeAmount(100, 1); v3Factory_.setOwner(initialOwner); v3Factory = address(v3Factory_); } if (deployUniswapInterfaceMulticall) { console.log('deploying Uniswap Interface Multicall'); UniswapInterfaceMulticallDeployer.deploy(); } if (deployQuoterV2) { if (!deployUniswapV3Factory) { v3Factory = config.readAddress('.protocols.v3.contracts.UniswapV3Factory.address'); } console.log('deploying Quoter V2'); QuoterV2Deployer.deploy(v3Factory, weth()); } if (deployTickLens) { console.log('deploying Tick Lens'); TickLensDeployer.deploy(); } if (deployNonfungibleTokenPositionDescriptor) { string memory nativeCurrencyLabel = config.readString( '.protocols.v3.contracts.NonfungibleTokenPositionDescriptor.params.nativeCurrencyLabel.value' ); bytes32 nativeCurrencyLabelBytes; assembly { nativeCurrencyLabelBytes := mload(add(nativeCurrencyLabel, 32)) } address proxyAdminOwner = config.readAddress( '.protocols.v3.contracts.NonfungibleTokenPositionDescriptor.params.proxyAdminOwner.value' ); address nftDescriptorImplementation = address(NonfungibleTokenPositionDescriptorDeployer.deploy(weth(), nativeCurrencyLabelBytes)); nftDescriptor = address(new TransparentUpgradeableProxy(nftDescriptorImplementation, proxyAdminOwner, '')); } if (deployNonfungiblePositionManager) { if (!deployNonfungibleTokenPositionDescriptor) { nftDescriptor = config.readAddress('.protocols.v3.contracts.NonfungibleTokenPositionDescriptor.address'); } if (!deployUniswapV3Factory) { v3Factory = config.readAddress('.protocols.v3.contracts.UniswapV3Factory.address'); } console.log('deploying Nonfungible Position Manager'); nonfungiblePositionManager = address(NonfungiblePositionManagerDeployer.deploy(v3Factory, weth(), nftDescriptor)); } if (deployV3Migrator) { if (!deployUniswapV3Factory) { v3Factory = config.readAddress('.protocols.v3.contracts.UniswapV3Factory.address'); } if (!deployNonfungiblePositionManager) { nonfungiblePositionManager = config.readAddress('.protocols.v3.contracts.NonfungiblePositionManager.address'); } console.log('deploying V3 Migrator'); V3MigratorDeployer.deploy(v3Factory, weth(), nonfungiblePositionManager); } if (deploySwapRouter) { if (!deployUniswapV3Factory) { console.log('deploying Swap Router'); v3Factory = config.readAddress('.protocols.v3.contracts.UniswapV3Factory.address'); } SwapRouterDeployer.deploy(v3Factory, weth()); } } function deployV4Contracts() private { if (!config.readBoolOr('.protocols.v4.deploy', false)) return; bool deployPoolManager = config.readBoolOr('.protocols.v4.contracts.PoolManager.deploy', false); bool deployPositionDescriptor = config.readBoolOr('.protocols.v4.contracts.PositionDescriptor.deploy', false); bool deployPositionManager = config.readBoolOr('.protocols.v4.contracts.PositionManager.deploy', false); bool deployV4Quoter = config.readBoolOr('.protocols.v4.contracts.V4Quoter.deploy', false); bool deployStateView = config.readBoolOr('.protocols.v4.contracts.StateView.deploy', false); address positionDescriptor; if (deployPoolManager) { address initialOwner = config.readAddress('.protocols.v4.contracts.PoolManager.params.initialOwner.value'); console.log('deploying Pool Manager'); poolManager = address(PoolManagerDeployer.deploy(initialOwner)); } if (deployPositionDescriptor) { string memory nativeCurrencyLabel = config.readString('.protocols.v4.contracts.PositionDescriptor.params.nativeCurrencyLabel.value'); bytes32 nativeCurrencyLabelBytes; assembly { nativeCurrencyLabelBytes := mload(add(nativeCurrencyLabel, 32)) } address proxyAdminOwner = config.readAddress('.protocols.v4.contracts.PositionDescriptor.params.proxyAdminOwner.value'); if (!deployPoolManager) { poolManager = config.readAddress('.protocols.v4.contracts.PoolManager.address'); } console.log('deploying Position Descriptor'); address positionDescriptorImplementation = address(PositionDescriptorDeployer.deploy(poolManager, weth(), nativeCurrencyLabelBytes)); positionDescriptor = address( new TransparentUpgradeableProxy{salt: hex'00'}(positionDescriptorImplementation, proxyAdminOwner, '') ); } if (deployPositionManager) { if (!deployPoolManager) { poolManager = config.readAddress('.protocols.v4.contracts.PoolManager.address'); } if (permit2 == address(0)) { permit2 = config.readAddress('.protocols.permit2.contracts.Permit2.address'); } uint256 unsubscribeGasLimit = config.readUint('.protocols.v4.contracts.PositionManager.params.unsubscribeGasLimit.value'); if (!deployPositionDescriptor) { positionDescriptor = config.readAddress('.protocols.v4.contracts.PositionDescriptor.address'); } console.log('deploying Position Manager'); positionManager = address( PositionManagerDeployer.deploy(poolManager, permit2, unsubscribeGasLimit, positionDescriptor, weth()) ); } if (deployV4Quoter) { if (!deployPoolManager) { poolManager = config.readAddress('.protocols.v4.contracts.PoolManager.address'); } console.log('deploying V4 Quoter'); V4QuoterDeployer.deploy(poolManager); } if (deployStateView) { if (!deployPoolManager) { poolManager = config.readAddress('.protocols.v4.contracts.PoolManager.address'); } console.log('deploying State View'); StateViewDeployer.deploy(poolManager); } } function deployPermit2() private { // TODO: handle permit2 more like WETH, get code at default address and check whether it's already deployed, if not, deploy it if (!config.readBoolOr('.protocols.permit2.deploy', false)) return; address deterministicProxy = 0x4e59b44847b379578588920cA78FbF26c0B4956C; if (deterministicProxy.code.length == 0) { console.log('Deterministic deployment proxy not deployed, deploying'); address deployerSigner = 0x3fAB184622Dc19b6109349B94811493BF2a45362; if (deployerSigner.balance < 0.01 ether) { console.log('Deployer signer balance is less than 0.01 ether, funding...'); // fund the deployer signer to deploy the deterministic proxy (bool success,) = deployerSigner.call{value: 0.01 ether - deployerSigner.balance}(''); require(success, 'Failed to fund deployer signer'); } // send the deployment transaction from the deployer signer: vm.broadcastRawTransaction( hex'f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222' ); } bytes32 salt = config.readBytes32('.protocols.permit2.contracts.Permit2.params.salt.value'); console.log('deploying Permit2'); (bool result,) = deterministicProxy.call(abi.encodePacked(salt, Permit2Deployer.initcode())); require(result, 'Failed to deploy permit2'); address computedAddress = computeAddress(deterministicProxy, salt, keccak256(abi.encodePacked(Permit2Deployer.initcode()))); console.log('Computed permit2 address:', computedAddress); permit2 = computedAddress; } function deployViewQuoterV3() private { if (!config.readBoolOr('.protocols.view-quoter-v3.deploy', false)) return; if (v3Factory == address(0)) { v3Factory = config.readAddress('.protocols.v3.contracts.UniswapV3Factory.address'); } console.log('deploying View Quoter v3'); QuoterDeployer.deploy(v3Factory); } function deploySwapRouters() private { if (!config.readBoolOr('.protocols.swap-router-contracts.deploy', false)) return; if (v2Factory == address(0)) { v2Factory = config.readAddress('.protocols.v2.contracts.UniswapV2Factory.address'); } if (v3Factory == address(0)) { v3Factory = config.readAddress('.protocols.v3.contracts.UniswapV3Factory.address'); } if (nonfungiblePositionManager == address(0)) { nonfungiblePositionManager = config.readAddress('.protocols.v3.contracts.NonfungiblePositionManager.address'); } console.log('deploying Swap Router 02'); SwapRouter02Deployer.deploy(v2Factory, v3Factory, nonfungiblePositionManager, weth()); } function deployUtilsContracts() private { if (!config.readBoolOr('.protocols.util-contracts.deploy', false)) return; bool deployFeeCollector = config.readBoolOr('.protocols.util-contracts.contracts.FeeCollector.deploy', false); bool deployFeeOnTransferDetector = config.readBoolOr('.protocols.util-contracts.contracts.FeeOnTransferDetector.deploy', false); if (deployFeeOnTransferDetector) { if (v2Factory == address(0)) { v2Factory = config.readAddress('.protocols.v2.contracts.UniswapV2Factory.address'); } console.log('deploying Fee On Transfer Detector'); FeeOnTransferDetectorDeployer.deploy(v2Factory); } if (deployFeeCollector) { address owner = config.readAddress('.protocols.util-contracts.contracts.FeeCollector.params.owner.value'); address feeToken = config.readAddress('.protocols.util-contracts.contracts.FeeCollector.params.feeToken.value'); if (universalRouter == address(0)) { universalRouter = config.readAddress('.protocols.universal-router.contracts.UniversalRouter.address'); } if (permit2 == address(0)) { permit2 = config.readAddress('.protocols.permit2.contracts.Permit2.address'); } console.log('deploying Fee Collector'); FeeCollectorDeployer.deploy(owner, universalRouter, permit2, feeToken); } } function deployUniversalRouter() private { if (!config.readBoolOr('.protocols.universal-router.deploy', false)) return; if (permit2 == address(0)) { permit2 = config.readAddress('.protocols.permit2.contracts.Permit2.address'); } if (v2Factory == address(0)) { v2Factory = config.readAddress('.protocols.v2.contracts.UniswapV2Factory.address'); } if (v3Factory == address(0)) { v3Factory = config.readAddress('.protocols.v3.contracts.UniswapV3Factory.address'); } bytes32 v2PairInitCodeHash = config.readBytes32('.protocols.universal-router.contracts.UniversalRouter.params.v2PairInitCodeHash.value'); bytes32 v3PoolInitCodeHash = config.readBytes32('.protocols.universal-router.contracts.UniversalRouter.params.v3PoolInitCodeHash.value'); if (poolManager == address(0)) { poolManager = config.readAddress('.protocols.v4.contracts.PoolManager.address'); } if (nonfungiblePositionManager == address(0)) { nonfungiblePositionManager = config.readAddress('.protocols.v3.contracts.NonfungiblePositionManager.address'); } if (positionManager == address(0)) { positionManager = config.readAddress('.protocols.v4.contracts.PositionManager.address'); } console.log('deploying Universal Router'); universalRouter = address( UniversalRouterDeployer.deploy( permit2, weth(), v2Factory, v3Factory, v2PairInitCodeHash, v3PoolInitCodeHash, poolManager, nonfungiblePositionManager, positionManager ) ); } function weth() internal returns (address) { if (_weth == address(0)) { _weth = config.readAddress('.dependencies.weth.value'); } return _weth; } } function computeAddress(address deployer, bytes32 salt, bytes32 creationCodeHash) pure returns (address addr) { assembly { let ptr := mload(0x40) mstore(add(ptr, 0x40), creationCodeHash) mstore(add(ptr, 0x20), salt) mstore(ptr, deployer) let start := add(ptr, 0x0b) mstore8(start, 0xff) addr := keccak256(start, 85) } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.0; import {IPermit2} from '../../protocols/permit2/interfaces/IPermit2.sol'; library Permit2Deployer { function deploy() internal returns (IPermit2 permit2) { bytes memory initcode_ = abi.encodePacked(initcode()); address permit2Address; assembly { permit2Address := create(0, add(initcode_, 32), mload(initcode_)) } permit2 = IPermit2(permit2Address); } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/permit2/src/Permit2.sol */ function initcode() internal pure returns (bytes memory) { return hex'60c0346100bb574660a052602081017f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681527f9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a60408301524660608301523060808301526080825260a082019180831060018060401b038411176100a557826040525190206080526123c090816100c1823960805181611b47015260a05181611b210152f35b634e487b7160e01b600052604160045260246000fd5b600080fdfe6040608081526004908136101561001557600080fd5b600090813560e01c80630d58b1db1461126c578063137c29fe146110755780632a2d80d114610db75780632b67b57014610bde57806330f28b7a14610ade5780633644e51514610a9d57806336c7851614610a285780633ff9dcb1146109a85780634fe02b441461093f57806365d9723c146107ac57806387517c451461067a578063927da105146105c3578063cc53287f146104a3578063edd9444b1461033a5763fe8ec1a7146100c657600080fd5b346103365760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff833581811161033257610114903690860161164b565b60243582811161032e5761012b903690870161161a565b6101336114e6565b9160843585811161032a5761014b9036908a016115c1565b98909560a43590811161032657610164913691016115c1565b969095815190610173826113ff565b606b82527f5065726d697442617463685769746e6573735472616e7366657246726f6d285460208301527f6f6b656e5065726d697373696f6e735b5d207065726d69747465642c61646472838301527f657373207370656e6465722c75696e74323536206e6f6e63652c75696e74323560608301527f3620646561646c696e652c000000000000000000000000000000000000000000608083015282519a8b9181610222602085018096611f93565b918237018a8152039961025b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09b8c8101835282611437565b5190209085515161026b81611ebb565b908a5b8181106102f95750506102f6999a6102ed9183516102a081610294602082018095611f66565b03848101835282611437565b519020602089810151858b015195519182019687526040820192909252336060820152608081019190915260a081019390935260643560c08401528260e081015b03908101835282611437565b51902093611cf7565b80f35b8061031161030b610321938c5161175e565b51612054565b61031b828661175e565b52611f0a565b61026e565b8880fd5b8780fd5b8480fd5b8380fd5b5080fd5b5091346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff9080358281116103325761038b903690830161164b565b60243583811161032e576103a2903690840161161a565b9390926103ad6114e6565b9160643590811161049f576103c4913691016115c1565b949093835151976103d489611ebb565b98885b81811061047d5750506102f697988151610425816103f9602082018095611f66565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611437565b5190206020860151828701519083519260208401947ffcf35f5ac6a2c28868dc44c302166470266239195f02b0ee408334829333b7668652840152336060840152608083015260a082015260a081526102ed8161141b565b808b61031b8261049461030b61049a968d5161175e565b9261175e565b6103d7565b8680fd5b5082346105bf57602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103325780359067ffffffffffffffff821161032e576104f49136910161161a565b929091845b848110610504578580f35b8061051a610515600193888861196c565b61197c565b61052f84610529848a8a61196c565b0161197c565b3389528385528589209173ffffffffffffffffffffffffffffffffffffffff80911692838b528652868a20911690818a5285528589207fffffffffffffffffffffffff000000000000000000000000000000000000000081541690558551918252848201527f89b1add15eff56b3dfe299ad94e01f2b52fbcb80ae1a3baea6ae8c04cb2b98a4853392a2016104f9565b8280fd5b50346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610676816105ff6114a0565b936106086114c3565b6106106114e6565b73ffffffffffffffffffffffffffffffffffffffff968716835260016020908152848420928816845291825283832090871683528152919020549251938316845260a083901c65ffffffffffff169084015260d09190911c604083015281906060820190565b0390f35b50346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336576106b26114a0565b906106bb6114c3565b916106c46114e6565b65ffffffffffff926064358481169081810361032a5779ffffffffffff0000000000000000000000000000000000000000947fda9fa7c1b00402c17d0161b249b1ab8bbec047c5a52207b9c112deffd817036b94338a5260016020527fffffffffffff0000000000000000000000000000000000000000000000000000858b209873ffffffffffffffffffffffffffffffffffffffff809416998a8d5260205283878d209b169a8b8d52602052868c209486156000146107a457504216925b8454921697889360a01b16911617179055815193845260208401523392a480f35b905092610783565b5082346105bf5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576107e56114a0565b906107ee6114c3565b9265ffffffffffff604435818116939084810361032a57338852602091600183528489209673ffffffffffffffffffffffffffffffffffffffff80911697888b528452858a20981697888a5283528489205460d01c93848711156109175761ffff9085840316116108f05750907f55eb90d810e1700b35a8e7e25395ff7f2b2259abd7415ca2284dfb1c246418f393929133895260018252838920878a528252838920888a5282528389209079ffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffff000000000000000000000000000000000000000000000000000083549260d01b16911617905582519485528401523392a480f35b84517f24d35a26000000000000000000000000000000000000000000000000000000008152fd5b5084517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b503461033657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336578060209273ffffffffffffffffffffffffffffffffffffffff61098f6114a0565b1681528084528181206024358252845220549051908152f35b5082346105bf57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf577f3704902f963766a4e561bbaab6e6cdc1b1dd12f6e9e99648da8843b3f46b918d90359160243533855284602052818520848652602052818520818154179055815193845260208401523392a280f35b8234610a9a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a9a57610a606114a0565b610a686114c3565b610a706114e6565b6064359173ffffffffffffffffffffffffffffffffffffffff8316830361032e576102f6936117a1565b80fd5b503461033657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657602090610ad7611b1e565b9051908152f35b508290346105bf576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf57610b1a3661152a565b90807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c36011261033257610b4c611478565b9160e43567ffffffffffffffff8111610bda576102f694610b6f913691016115c1565b939092610b7c8351612054565b6020840151828501519083519260208401947f939c21a48a8dbe3a9a2404a1d46691e4d39f6583d6ec6b35714604c986d801068652840152336060840152608083015260a082015260a08152610bd18161141b565b51902091611c25565b8580fd5b509134610336576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610c186114a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc360160c08112610332576080855191610c51836113e3565b1261033257845190610c6282611398565b73ffffffffffffffffffffffffffffffffffffffff91602435838116810361049f578152604435838116810361049f57602082015265ffffffffffff606435818116810361032a5788830152608435908116810361049f576060820152815260a435938285168503610bda576020820194855260c4359087830182815260e43567ffffffffffffffff811161032657610cfe90369084016115c1565b929093804211610d88575050918591610d786102f6999a610d7e95610d238851611fbe565b90898c511690519083519260208401947ff3841cd1ff0085026a6327b620b67997ce40f282c88a8e905a7a5626e310f3d086528401526060830152608082015260808152610d70816113ff565b519020611bd9565b916120c7565b519251169161199d565b602492508a51917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b5091346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc93818536011261033257610df36114a0565b9260249081359267ffffffffffffffff9788851161032a578590853603011261049f578051978589018981108282111761104a578252848301358181116103265785019036602383011215610326578382013591610e50836115ef565b90610e5d85519283611437565b838252602093878584019160071b83010191368311611046578801905b828210610fe9575050508a526044610e93868801611509565b96838c01978852013594838b0191868352604435908111610fe557610ebb90369087016115c1565b959096804211610fba575050508998995151610ed681611ebb565b908b5b818110610f9757505092889492610d7892610f6497958351610f02816103f98682018095611f66565b5190209073ffffffffffffffffffffffffffffffffffffffff9a8b8b51169151928551948501957faf1b0d30d2cab0380e68f0689007e3254993c596f2fdd0aaa7f4d04f794408638752850152830152608082015260808152610d70816113ff565b51169082515192845b848110610f78578580f35b80610f918585610f8b600195875161175e565b5161199d565b01610f6d565b80610311610fac8e9f9e93610fb2945161175e565b51611fbe565b9b9a9b610ed9565b8551917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b8a80fd5b6080823603126110465785608091885161100281611398565b61100b85611509565b8152611018838601611509565b838201526110278a8601611607565b8a8201528d611037818701611607565b90820152815201910190610e7a565b8c80fd5b84896041867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5082346105bf576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576110b03661152a565b91807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610332576110e2611478565b67ffffffffffffffff93906101043585811161049f5761110590369086016115c1565b90936101243596871161032a57611125610bd1966102f6983691016115c1565b969095825190611134826113ff565b606482527f5065726d69745769746e6573735472616e7366657246726f6d28546f6b656e5060208301527f65726d697373696f6e73207065726d69747465642c6164647265737320737065848301527f6e6465722c75696e74323536206e6f6e63652c75696e7432353620646561646c60608301527f696e652c0000000000000000000000000000000000000000000000000000000060808301528351948591816111e3602085018096611f93565b918237018b8152039361121c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe095868101835282611437565b5190209261122a8651612054565b6020878101518589015195519182019687526040820192909252336060820152608081019190915260a081019390935260e43560c08401528260e081016102e1565b5082346105bf576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033257813567ffffffffffffffff92838211610bda5736602383011215610bda5781013592831161032e576024906007368386831b8401011161049f57865b8581106112e5578780f35b80821b83019060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83360301126103265761139288876001946060835161132c81611398565b611368608461133c8d8601611509565b9485845261134c60448201611509565b809785015261135d60648201611509565b809885015201611509565b918291015273ffffffffffffffffffffffffffffffffffffffff80808093169516931691166117a1565b016112da565b6080810190811067ffffffffffffffff8211176113b457604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176113b457604052565b60a0810190811067ffffffffffffffff8211176113b457604052565b60c0810190811067ffffffffffffffff8211176113b457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176113b457604052565b60c4359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b600080fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6044359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01906080821261149b576040805190611563826113e3565b8082941261149b57805181810181811067ffffffffffffffff8211176113b457825260043573ffffffffffffffffffffffffffffffffffffffff8116810361149b578152602435602082015282526044356020830152606435910152565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020838186019501011161149b57565b67ffffffffffffffff81116113b45760051b60200190565b359065ffffffffffff8216820361149b57565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020808501948460061b01011161149b57565b91909160608184031261149b576040805191611666836113e3565b8294813567ffffffffffffffff9081811161149b57830182601f8201121561149b578035611693816115ef565b926116a087519485611437565b818452602094858086019360061b8501019381851161149b579086899897969594939201925b8484106116e3575050505050855280820135908501520135910152565b90919293949596978483031261149b578851908982019082821085831117611730578a928992845261171487611509565b81528287013583820152815201930191908897969594936116c6565b602460007f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b80518210156117725760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b92919273ffffffffffffffffffffffffffffffffffffffff604060008284168152600160205282828220961695868252602052818120338252602052209485549565ffffffffffff8760a01c16804211611884575082871696838803611812575b5050611810955016926118b5565b565b878484161160001461184f57602488604051907ff96fb0710000000000000000000000000000000000000000000000000000000082526004820152fd5b7fffffffffffffffffffffffff000000000000000000000000000000000000000084846118109a031691161790553880611802565b602490604051907fd81b2f2e0000000000000000000000000000000000000000000000000000000082526004820152fd5b9060006064926020958295604051947f23b872dd0000000000000000000000000000000000000000000000000000000086526004860152602485015260448401525af13d15601f3d116001600051141617161561190e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b91908110156117725760061b0190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361149b5790565b9065ffffffffffff908160608401511673ffffffffffffffffffffffffffffffffffffffff908185511694826020820151169280866040809401511695169560009187835260016020528383208984526020528383209916988983526020528282209184835460d01c03611af5579185611ace94927fc6a377bfc4eb120024a8ac08eef205be16b817020812c73223e81d1bdb9708ec98979694508715600014611ad35779ffffffffffff00000000000000000000000000000000000000009042165b60a01b167fffffffffffff00000000000000000000000000000000000000000000000000006001860160d01b1617179055519384938491604091949373ffffffffffffffffffffffffffffffffffffffff606085019616845265ffffffffffff809216602085015216910152565b0390a4565b5079ffffffffffff000000000000000000000000000000000000000087611a60565b600484517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b467f000000000000000000000000000000000000000000000000000000000000000003611b69577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86682527f9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a604082015246606082015230608082015260808152611bd3816113ff565b51902090565b611be1611b1e565b906040519060208201927f190100000000000000000000000000000000000000000000000000000000000084526022830152604282015260428152611bd381611398565b9192909360a435936040840151804211611cc65750602084510151808611611c955750918591610d78611c6594611c60602088015186611e47565b611bd9565b73ffffffffffffffffffffffffffffffffffffffff809151511692608435918216820361149b57611810936118b5565b602490604051907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b959093958051519560409283830151804211611e175750848803611dee57611d2e918691610d7860209b611c608d88015186611e47565b60005b868110611d42575050505050505050565b611d4d81835161175e565b5188611d5a83878a61196c565b01359089810151808311611dbe575091818888886001968596611d84575b50505050505001611d31565b611db395611dad9273ffffffffffffffffffffffffffffffffffffffff6105159351169561196c565b916118b5565b803888888883611d78565b6024908651907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b600484517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b6024908551907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff600160ff83161b9216600052600060205260406000209060081c6000526020526040600020818154188091551615611e9157565b60046040517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b90611ec5826115ef565b611ed26040519182611437565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611f0082946115ef565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611f375760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b805160208092019160005b828110611f7f575050505090565b835185529381019392810192600101611f71565b9081519160005b838110611fab575050016000815290565b8060208092840101518185015201611f9a565b60405160208101917f65626cad6cb96493bf6f5ebea28756c966f023ab9e8a83a7101849d5573b3678835273ffffffffffffffffffffffffffffffffffffffff8082511660408401526020820151166060830152606065ffffffffffff9182604082015116608085015201511660a082015260a0815260c0810181811067ffffffffffffffff8211176113b45760405251902090565b6040516020808201927f618358ac3db8dc274f0cd8829da7e234bd48cd73c4a740aede1adec9846d06a1845273ffffffffffffffffffffffffffffffffffffffff81511660408401520151606082015260608152611bd381611398565b919082604091031261149b576020823592013590565b6000843b61222e5750604182036121ac576120e4828201826120b1565b939092604010156117725760209360009360ff6040608095013560f81c5b60405194855216868401526040830152606082015282805260015afa156121a05773ffffffffffffffffffffffffffffffffffffffff806000511691821561217657160361214c57565b60046040517f815e1d64000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d6000823e3d90fd5b60408203612204576121c0918101906120b1565b91601b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84169360ff1c019060ff8211611f375760209360009360ff608094612102565b60046040517f4be6321b000000000000000000000000000000000000000000000000000000008152fd5b929391601f928173ffffffffffffffffffffffffffffffffffffffff60646020957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0604051988997889687947f1626ba7e000000000000000000000000000000000000000000000000000000009e8f8752600487015260406024870152816044870152868601378b85828601015201168101030192165afa9081156123a857829161232a575b507fffffffff000000000000000000000000000000000000000000000000000000009150160361230057565b60046040517fb0669cbc000000000000000000000000000000000000000000000000000000008152fd5b90506020813d82116123a0575b8161234460209383611437565b810103126103365751907fffffffff0000000000000000000000000000000000000000000000000000000082168203610a9a57507fffffffff0000000000000000000000000000000000000000000000000000000090386122d4565b3d9150612337565b6040513d84823e3d90fdfea164736f6c6343000811000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {ISwapRouter02} from '../../protocols/swap-router-contracts/interfaces/ISwapRouter02.sol'; library SwapRouter02Deployer { function deploy(address factoryV2, address factoryV3, address positionManager, address weth) internal returns (ISwapRouter02 router) { bytes memory args = abi.encode(factoryV2, factoryV3, positionManager, weth); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { router := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/swap-router-contracts/contracts/SwapRouter02.sol */ function initcode() internal pure returns (bytes memory) { return hex'6101006040526000196000553480156200001857600080fd5b5060405162006135380380620061358339810160408190526200003b9162000087565b6001600160601b0319606094851b811660805291841b821660a05291831b811660c052911b1660e052620000e3565b80516001600160a01b03811681146200008257600080fd5b919050565b600080600080608085870312156200009d578384fd5b620000a8856200006a565b9350620000b8602086016200006a565b9250620000c8604086016200006a565b9150620000d8606086016200006a565b905092959194509250565b60805160601c60a05160601c60c05160601c60e05160601c615fb162000184600039806102c15280610b3c52806112ad52806113d7528061147e52806116af52806117d95280612d8f5280612def5280612e70525080611e4c52806124df5280613cdb52508061166f5280611b1a5280611e9c52806132a6525080610c625280610d365280610fe2528061164b5280612fc252806131855250615fb16000f3fe6080604052600436106102a45760003560e01c80639b2c0a371161016e578063dee00f35116100cb578063f100b2051161007f578063f2d5d56b11610064578063f2d5d56b1461066e578063f3995c6714610681578063fa461e33146106945761034f565b8063f100b2051461063b578063f25801a71461064e5761034f565b8063e0e189a0116100b0578063e0e189a0146105f5578063e90a182f14610608578063efdeed8e1461061b5761034f565b8063dee00f35146105b5578063df2ab5bb146105e25761034f565b8063b858183f11610122578063c45a015511610107578063c45a01551461057a578063cab372ce1461058f578063d4ef38de146105a25761034f565b8063b858183f14610554578063c2e3140a146105675761034f565b8063ab3fdd5011610153578063ab3fdd501461051b578063ac9650d81461052e578063b3a2af13146105415761034f565b80639b2c0a37146104f5578063a4a78f0c146105085761034f565b8063472b43f31161021c578063571ac8b0116101d0578063639d71a9116101b5578063639d71a9146104b857806368e0d4e1146104cb578063791b98bc146104e05761034f565b8063571ac8b0146104925780635ae401dc146104a55761034f565b80634961699711610201578063496169971461044a5780634aa4a4fc1461045d5780635023b4df1461047f5761034f565b8063472b43f31461042457806349404b7c146104375761034f565b80631c58db4f116102735780633068c554116102585780633068c554146103eb57806342712a67146103fe5780634659a494146104115761034f565b80631c58db4f146103b85780631f0464d1146103cb5761034f565b806304e45aaf1461035457806309b813461461037d57806311ed56c91461039057806312210e8a146103b05761034f565b3661034f573373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461034d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4e6f742057455448390000000000000000000000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b610367610362366004615543565b6106b4565b6040516103749190615dfd565b60405180910390f35b61036761038b3660046155de565b61083c565b6103a361039e366004615638565b61091c565b6040516103749190615b7a565b61034d610b28565b61034d6103c63660046157bb565b610b3a565b6103de6103d93660046152a7565b610bbe565b6040516103749190615afc565b61034d6103f93660046150d8565b610c48565b61036761040c366004615885565b610c5b565b61034d61041f366004615121565b610e35565b610367610432366004615885565b610ef5565b61034d6104453660046157eb565b6112a9565b61034d6104583660046157bb565b61146f565b34801561046957600080fd5b5061047261147c565b6040516103749190615a3c565b61036761048d366004615616565b6114a0565b61034d6104a0366004614feb565b611589565b6103de6104b33660046152a7565b6115bc565b61034d6104c6366004614feb565b611635565b3480156104d757600080fd5b50610472611649565b3480156104ec57600080fd5b5061047261166d565b61034d61050336600461581a565b611691565b61034d610516366004615121565b6118a7565b61034d610529366004614feb565b61197c565b6103de61053c36600461517c565b6119ba565b6103a361054f3660046152f1565b611b14565b61036761056236600461549d565b611bd2565b61034d610575366004615121565b611d95565b34801561058657600080fd5b50610472611e4a565b61034d61059d366004614feb565b611990565b61034d6105b0366004615858565b611e6e565b3480156105c157600080fd5b506105d56105d036600461500e565b611e7a565b6040516103749190615b8d565b61034d6105f0366004615039565b612027565b61034d61060336600461507a565b61213e565b61034d61061636600461500e565b6122a4565b34801561062757600080fd5b5061034d6106363660046151bc565b6122b3565b6103a3610649366004615627565b612305565b34801561065a57600080fd5b5061034d610669366004615324565b6123a5565b61034d61067c36600461500e565b6123f6565b61034d61068f366004615121565b612402565b3480156106a057600080fd5b5061034d6106af3660046153b8565b61249a565b600080600083608001511415610771575081516040517f70a0823100000000000000000000000000000000000000000000000000000000815260019173ffffffffffffffffffffffffffffffffffffffff16906370a082319061071b903090600401615a3c565b60206040518083038186803b15801561073357600080fd5b505afa158015610747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076b91906157d3565b60808401525b6107ed836080015184606001518560c001516040518060400160405280886000015189604001518a602001516040516020016107af939291906159aa565b6040516020818303038152906040528152602001866107ce57336107d0565b305b73ffffffffffffffffffffffffffffffffffffffff1690526125de565b91508260a00151821015610836576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615c7d565b60405180910390fd5b50919050565b60006108b0604083018035906108559060208601614feb565b604080518082019091526000908061086d8880615e41565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252503360209091015261278f565b505060005460608201358111156108f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615c0f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600055919050565b604080516101608101909152606090610b20907f8831645600000000000000000000000000000000000000000000000000000000908061095f6020870187614feb565b73ffffffffffffffffffffffffffffffffffffffff16815260200185602001602081019061098d9190614feb565b73ffffffffffffffffffffffffffffffffffffffff1681526020016109b860608701604088016157a1565b62ffffff1681526020016109d26080870160608801615379565b60020b81526020016109ea60a0870160808801615379565b60020b8152602090810190610a0a90610a0590880188614feb565b612976565b8152602001610a25866020016020810190610a059190614feb565b815260a0860135602082015260c08601356040820152606001610a4f610100870160e08801614feb565b73ffffffffffffffffffffffffffffffffffffffff1681526020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff815250604051602401610a9e9190615cf8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611b14565b90505b919050565b4715610b3857610b383347612a1b565b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015610ba257600080fd5b505af1158015610bb6573d6000803e3d6000fd5b505050505050565b60608380600143034014610c3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f426c6f636b686173680000000000000000000000000000000000000000000000604482015290519081900360640190fd5b610c3d84846119ba565b91505b509392505050565b610c55848433858561213e565b50505050565b6000610cbb7f000000000000000000000000000000000000000000000000000000000000000087868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612b6992505050565b600081518110610cc757fe5b6020026020010151905084811115610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615c0f565b610da484846000818110610d1b57fe5b9050602002016020810190610d309190614feb565b33610d9e7f000000000000000000000000000000000000000000000000000000000000000088886000818110610d6257fe5b9050602002016020810190610d779190614feb565b89896001818110610d8457fe5b9050602002016020810190610d999190614feb565b612ca2565b84612d8d565b73ffffffffffffffffffffffffffffffffffffffff821660011415610dcb57339150610dee565b73ffffffffffffffffffffffffffffffffffffffff821660021415610dee573091505b610e2c848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250869250612f6b915050565b95945050505050565b604080517f8fcbaf0c00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101879052606481018690526001608482015260ff851660a482015260c4810184905260e48101839052905173ffffffffffffffffffffffffffffffffffffffff881691638fcbaf0c9161010480830192600092919082900301818387803b158015610ed557600080fd5b505af1158015610ee9573d6000803e3d6000fd5b50505050505050505050565b60008086610fab575060018484600081610f0b57fe5b9050602002016020810190610f209190614feb565b73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f589190615a3c565b60206040518083038186803b158015610f7057600080fd5b505afa158015610f84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa891906157d3565b96505b61103685856000818110610fbb57fe5b9050602002016020810190610fd09190614feb565b82610fdb5733610fdd565b305b6110307f00000000000000000000000000000000000000000000000000000000000000008989600081811061100e57fe5b90506020020160208101906110239190614feb565b8a8a6001818110610d8457fe5b8a612d8d565b73ffffffffffffffffffffffffffffffffffffffff83166001141561105d57339250611080565b73ffffffffffffffffffffffffffffffffffffffff831660021415611080573092505b600085857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181106110b057fe5b90506020020160208101906110c59190614feb565b73ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b81526004016110fd9190615a3c565b60206040518083038186803b15801561111557600080fd5b505afa158015611129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114d91906157d3565b905061118d868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250612f6b915050565b6112628187877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181106111bf57fe5b90506020020160208101906111d49190614feb565b73ffffffffffffffffffffffffffffffffffffffff166370a08231876040518263ffffffff1660e01b815260040161120c9190615a3c565b60206040518083038186803b15801561122457600080fd5b505afa158015611238573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125c91906157d3565b90613270565b92508683101561129e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615c7d565b505095945050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561133257600080fd5b505afa158015611346573d6000803e3d6000fd5b505050506040513d602081101561135c57600080fd5b50519050828110156113cf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e742057455448390000000000000000000000000000604482015290519081900360640190fd5b801561146a577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561144857600080fd5b505af115801561145c573d6000803e3d6000fd5b5050505061146a8282612a1b565b505050565b61147981336112a9565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611549608083018035906114b99060608601614feb565b6114c960e0860160c08701614feb565b60405180604001604052808760200160208101906114e79190614feb565b6114f760608a0160408b016157a1565b61150460208b018b614feb565b604051602001611516939291906159aa565b60405160208183030381529060405281526020013373ffffffffffffffffffffffffffffffffffffffff1681525061278f565b90508160a001358111156108f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615c0f565b6115b3817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613280565b61147957600080fd5b606083806115c86133cc565b1115610c3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b611640816000613280565b61158957600080fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000821180156116a2575060648211155b6116ab57600080fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561173457600080fd5b505afa158015611748573d6000803e3d6000fd5b505050506040513d602081101561175e57600080fd5b50519050848110156117d157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e742057455448390000000000000000000000000000604482015290519081900360640190fd5b80156118a0577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561184a57600080fd5b505af115801561185e573d6000803e3d6000fd5b50505050600061271061187a85846133d090919063ffffffff16565b8161188157fe5b0490508015611894576118948382612a1b565b610bb685828403612a1b565b5050505050565b604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815233600482015230602482015290517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9173ffffffffffffffffffffffffffffffffffffffff89169163dd62ed3e91604480820192602092909190829003018186803b15801561193c57600080fd5b505afa158015611950573d6000803e3d6000fd5b505050506040513d602081101561196657600080fd5b50511015610bb657610bb6868686868686610e35565b611987816000613280565b61199057600080fd5b6115b3817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe613280565b60608167ffffffffffffffff811180156119d357600080fd5b50604051908082528060200260200182016040528015611a0757816020015b60608152602001906001900390816119f25790505b50905060005b82811015611b0d5760008030868685818110611a2557fe5b9050602002810190611a379190615e41565b604051611a45929190615a10565b600060405180830381855af49150503d8060008114611a80576040519150601f19603f3d011682016040523d82523d6000602084013e611a85565b606091505b509150915081611aeb57604481511015611a9e57600080fd5b60048101905080806020019051810190611ab89190615433565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d9190615b7a565b80848481518110611af857fe5b60209081029190910101525050600101611a0d565b5092915050565b606060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1683604051611b5d9190615a20565b6000604051808303816000865af19150503d8060008114611b9a576040519150601f19603f3d011682016040523d82523d6000602084013e611b9f565b606091505b50925090508061083657604482511015611bb857600080fd5b60048201915081806020019051810190611ab89190615433565b600080600083604001511415611ca357600190506000611bf584600001516133f4565b50506040517f70a0823100000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190611c4c903090600401615a3c565b60206040518083038186803b158015611c6457600080fd5b505afa158015611c78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9c91906157d3565b6040850152505b600081611cb05733611cb2565b305b90505b6000611cc48560000151613425565b9050611d1d856040015182611cdd578660200151611cdf565b305b60006040518060400160405280611cf98b6000015161342d565b81526020018773ffffffffffffffffffffffffffffffffffffffff168152506125de565b60408601528015611d3d578451309250611d369061343c565b8552611d4a565b8460400151935050611d50565b50611cb5565b8360600151831015611d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615c7d565b5050919050565b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523360048201523060248201529051869173ffffffffffffffffffffffffffffffffffffffff89169163dd62ed3e91604480820192602092909190829003018186803b158015611e0a57600080fd5b505afa158015611e1e573d6000803e3d6000fd5b505050506040513d6020811015611e3457600080fd5b50511015610bb657610bb6868686868686612402565b7f000000000000000000000000000000000000000000000000000000000000000081565b61146a83338484611691565b6000818373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e307f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401611ed8929190615a5d565b60206040518083038186803b158015611ef057600080fd5b505afa158015611f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2891906157d3565b10611f3557506000612021565b611f5f837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613280565b15611f6c57506001612021565b611f96837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe613280565b15611fa357506002612021565b611fae836000613280565b611fb757600080fd5b611fe1837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613280565b15611fee57506003612021565b612018837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe613280565b1561034f575060045b92915050565b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561209057600080fd5b505afa1580156120a4573d6000803e3d6000fd5b505050506040513d60208110156120ba57600080fd5b505190508281101561212d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e7420746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b8015610c5557610c55848383613471565b60008211801561214f575060648211155b61215857600080fd5b60008573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156121c157600080fd5b505afa1580156121d5573d6000803e3d6000fd5b505050506040513d60208110156121eb57600080fd5b505190508481101561225e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e73756666696369656e7420746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b8015610bb657600061271061227383866133d0565b8161227a57fe5b049050801561228e5761228e878483613471565b61229b8786838503613471565b50505050505050565b6122af828233612027565b5050565b6000806122c1868685613646565b915091508362ffffff1681830312610bb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615c46565b6060610b2063219f5d1760e01b6040518060c001604052808560400135815260200161233d866000016020810190610a059190614feb565b8152602001612358866020016020810190610a059190614feb565b815260200185606001358152602001856080013581526020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff815250604051602401610a9e9190615cb4565b6000806123b28584613859565b915091508362ffffff16818303126118a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615c46565b6122af82333084613ae1565b604080517fd505accf000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018790526064810186905260ff8516608482015260a4810184905260c48101839052905173ffffffffffffffffffffffffffffffffffffffff88169163d505accf9160e480830192600092919082900301818387803b158015610ed557600080fd5b60008413806124a95750600083135b6124b257600080fd5b60006124c08284018461564a565b905060008060006124d484600001516133f4565b9250925092506125067f0000000000000000000000000000000000000000000000000000000000000000848484613cbe565b5060008060008a13612547578473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161089612578565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16108a5b915091508115612597576125928587602001513384612d8d565b610ee9565b85516125a290613425565b156125c75785516125b29061343c565b86526125c1813360008961278f565b50610ee9565b80600081905550610ee98487602001513384612d8d565b600073ffffffffffffffffffffffffffffffffffffffff8416600114156126075733935061262a565b73ffffffffffffffffffffffffffffffffffffffff84166002141561262a573093505b600080600061263c85600001516133f4565b9194509250905073ffffffffffffffffffffffffffffffffffffffff8083169084161060008061266d868686613cd4565b73ffffffffffffffffffffffffffffffffffffffff1663128acb088b856126938f613d12565b73ffffffffffffffffffffffffffffffffffffffff8e16156126b5578d6126db565b876126d45773fffd8963efd1fc6a506488495d951d5263988d256126db565b6401000276a45b8d6040516020016126ec9190615da6565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161271b959493929190615a84565b6040805180830381600087803b15801561273457600080fd5b505af1158015612748573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061276c9190615395565b915091508261277b578161277d565b805b6000039b9a5050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8416600114156127b8573393506127db565b73ffffffffffffffffffffffffffffffffffffffff8416600214156127db573093505b60008060006127ed85600001516133f4565b9194509250905073ffffffffffffffffffffffffffffffffffffffff8084169083161060008061281e858786613cd4565b73ffffffffffffffffffffffffffffffffffffffff1663128acb088b856128448f613d12565b60000373ffffffffffffffffffffffffffffffffffffffff8e1615612869578d61288f565b876128885773fffd8963efd1fc6a506488495d951d5263988d2561288f565b6401000276a45b8d6040516020016128a09190615da6565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016128cf959493929190615a84565b6040805180830381600087803b1580156128e857600080fd5b505af11580156128fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129209190615395565b9150915060008361293557818360000361293b565b82826000035b909850905073ffffffffffffffffffffffffffffffffffffffff8a16612967578b811461296757600080fd5b50505050505050949350505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff8316906370a08231906129cb903090600401615a3c565b60206040518083038186803b1580156129e357600080fd5b505afa1580156129f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2091906157d3565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040518082805190602001908083835b60208310612a9257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101612a55565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114612af4576040519150601f19603f3d011682016040523d82523d6000602084013e612af9565b606091505b505090508061146a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f5354450000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6060600282511015612b7a57600080fd5b815167ffffffffffffffff81118015612b9257600080fd5b50604051908082528060200260200182016040528015612bbc578160200160208202803683370190505b5090508281600183510381518110612bd057fe5b602090810291909101015281517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b8015610c4057600080612c3d87866001860381518110612c1c57fe5b6020026020010151878681518110612c3057fe5b6020026020010151613d44565b91509150612c5f848481518110612c5057fe5b60200260200101518383613e2c565b846001850381518110612c6e57fe5b602090810291909101015250507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01612c00565b6000806000612cb18585613f02565b604080517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606094851b811660208084019190915293851b81166034830152825160288184030181526048830184528051908501207fff0000000000000000000000000000000000000000000000000000000000000060688401529a90941b9093166069840152607d8301989098527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f609d808401919091528851808403909101815260bd909201909752805196019590952095945050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148015612de85750804710155b15612f31577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612e5557600080fd5b505af1158015612e69573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015612eff57600080fd5b505af1158015612f13573d6000803e3d6000fd5b505050506040513d6020811015612f2957600080fd5b50610c559050565b73ffffffffffffffffffffffffffffffffffffffff8316301415612f5f57612f5a848383613471565b610c55565b610c5584848484613ae1565b60005b600183510381101561146a57600080848381518110612f8957fe5b6020026020010151858460010181518110612fa057fe5b6020026020010151915091506000612fb88383613f02565b5090506000612fe87f00000000000000000000000000000000000000000000000000000000000000008585612ca2565b90506000806000808473ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561303657600080fd5b505afa15801561304a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061306e91906156da565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000808773ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16146130d05782846130d3565b83835b91509150613114828b73ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b815260040161120c9190615a3c565b9550613121868383613fa7565b9450505050506000808573ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161461316557826000613169565b6000835b91509150600060028c51038a10613180578a6131c1565b6131c17f0000000000000000000000000000000000000000000000000000000000000000898e8d600201815181106131b457fe5b6020026020010151612ca2565b604080516000815260208101918290527f022c0d9f0000000000000000000000000000000000000000000000000000000090915290915073ffffffffffffffffffffffffffffffffffffffff87169063022c0d9f906132299086908690869060248101615e06565b600060405180830381600087803b15801561324357600080fd5b505af1158015613257573d6000803e3d6000fd5b50506001909b019a50612f6e9950505050505050505050565b8082038281111561202157600080fd5b60008060008473ffffffffffffffffffffffffffffffffffffffff1663095ea7b360e01b7f0000000000000000000000000000000000000000000000000000000000000000866040516024016132d7929190615ad6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516133609190615a20565b6000604051808303816000865af19150503d806000811461339d576040519150601f19603f3d011682016040523d82523d6000602084013e6133a2565b606091505b5091509150818015610e2c575080511580610e2c575080806020019051810190610e2c919061528d565b4290565b60008215806133eb575050818102818382816133e857fe5b04145b61202157600080fd5b60008080613402848261407d565b925061340f84601461417d565b905061341c84601761407d565b91509193909250565b516042111590565b6060610b20826000602b61426d565b8051606090610b209083906017907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe90161426d565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781529251825160009485949389169392918291908083835b6020831061354657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613509565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146135a8576040519150601f19603f3d011682016040523d82523d6000602084013e6135ad565b606091505b50915091508180156135db5750805115806135db57508080602001905160208110156135d857600080fd5b50515b6118a057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f5354000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600080835185511461365757600080fd5b6000855167ffffffffffffffff8111801561367157600080fd5b506040519080825280602002602001820160405280156136ab57816020015b613698614e34565b8152602001906001900390816136905790505b5090506000865167ffffffffffffffff811180156136c857600080fd5b5060405190808252806020026020018201604052801561370257816020015b6136ef614e34565b8152602001906001900390816136e75790505b50905060005b8751811015613832576000806137318a848151811061372357fe5b602002602001015189613859565b9150915061373e82614454565b85848151811061374a57fe5b60200260200101516000019060020b908160020b8152505061376b81614454565b84848151811061377757fe5b60200260200101516000019060020b908160020b8152505088838151811061379b57fe5b60200260200101518584815181106137af57fe5b6020026020010151602001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff16815250508883815181106137f157fe5b602002602001015184848151811061380557fe5b6020908102919091018101516fffffffffffffffffffffffffffffffff9092169101525050600101613708565b5061383c82614465565b60020b935061384a81614465565b60020b92505050935093915050565b6000806000806138688661454d565b90506000805b82811015613a865760008060006138848b6133f4565b9250925092506000613897848484613cd4565b905060008063ffffffff8d166138c0576138b083614578565b600291820b9350900b9050613962565b6138ca838e614810565b8160020b915050809250508273ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561391b57600080fd5b505afa15801561392f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139539190615715565b50505060029290920b93505050505b600189038714156139a3578473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161099506139b2565b6139ac8e61343c565b9d508597505b6000871580613a5357508673ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1610613a23578673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1610613a53565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16105b90508015613a68579b82019b9a81019a613a73565b828d039c50818c039b505b50506001909501945061386e9350505050565b5082613ad7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff850294507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff840293505b5050509250929050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000178152925182516000948594938a169392918291908083835b60208310613bbe57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613b81565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c20576040519150601f19603f3d011682016040523d82523d6000602084013e613c25565b606091505b5091509150818015613c53575080511580613c535750808060200190516020811015613c5057600080fd5b50515b610bb657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600360248201527f5354460000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000610e2c85613ccf868686614c41565b614cbe565b6000613d0a7f0000000000000000000000000000000000000000000000000000000000000000613d05868686614c41565b614cee565b949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210613d4057600080fd5b5090565b6000806000613d538585613f02565b509050600080613d64888888612ca2565b73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015613da957600080fd5b505afa158015613dbd573d6000803e3d6000fd5b505050506040513d6060811015613dd357600080fd5b5080516020909101516dffffffffffffffffffffffffffff918216935016905073ffffffffffffffffffffffffffffffffffffffff87811690841614613e1a578082613e1d565b81815b90999098509650505050505050565b6000808411613e9c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f494e53554646494349454e545f4f55545055545f414d4f554e54000000000000604482015290519081900360640190fd5b600083118015613eac5750600082115b613eb557600080fd5b6000613ecd6103e8613ec786886133d0565b906133d0565b90506000613ee16103e5613ec78689613270565b9050613ef86001828481613ef157fe5b0490614e24565b9695505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415613f3e57600080fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610613f78578284613f7b565b83835b909250905073ffffffffffffffffffffffffffffffffffffffff8216613fa057600080fd5b9250929050565b600080841161401757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f494e53554646494349454e545f494e5055545f414d4f554e5400000000000000604482015290519081900360640190fd5b6000831180156140275750600082115b61403057600080fd5b600061403e856103e56133d0565b9050600061404c82856133d0565b9050600061406683614060886103e86133d0565b90614e24565b905080828161407157fe5b04979650505050505050565b6000818260140110156140f157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b816014018351101561416457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b6000818260030110156141f157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b816003018351101561426457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b60608182601f0110156142e157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b82828401101561435257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b818301845110156143c457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b6060821580156143e3576040519150600082526020820160405261444b565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561441c578051835260209283019201614404565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b80600281900b8114610b2357600080fd5b6000806000805b84518110156144fa5784818151811061448157fe5b6020026020010151602001516fffffffffffffffffffffffffffffffff168582815181106144ab57fe5b60200260200101516000015160020b02830192508481815181106144cb57fe5b6020026020010151602001516fffffffffffffffffffffffffffffffff1682019150808060010191505061446c565b5080828161450457fe5b05925060008212801561451f575080828161451b57fe5b0715155b15611d8e5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01919050565b5160177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec9091010490565b6000806000808473ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b1580156145c457600080fd5b505afa1580156145d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145fc9190615715565b50939750919550935050600161ffff84161191506146489050576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615bd8565b6000808673ffffffffffffffffffffffffffffffffffffffff1663252c09d7856040518263ffffffff1660e01b81526004016146849190615dee565b60806040518083038186803b15801561469c57600080fd5b505afa1580156146b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146d491906158e0565b5050915091506146e26133cc565b63ffffffff168263ffffffff16146146fc57849550614807565b60008361ffff1660018561ffff168761ffff1601038161471857fe5b06905060008060008a73ffffffffffffffffffffffffffffffffffffffff1663252c09d7856040518263ffffffff1660e01b81526004016147599190615dfd565b60806040518083038186803b15801561477157600080fd5b505afa158015614785573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147a991906158e0565b93505092509250806147e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082d90615ba1565b82860363ffffffff811683870360060b816147fe57fe5b059a5050505050505b50505050915091565b60008063ffffffff831661488557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600260248201527f4250000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60408051600280825260608201835260009260208301908036833701905050905083816000815181106148b457fe5b602002602001019063ffffffff16908163ffffffff16815250506000816001815181106148dd57fe5b63ffffffff9092166020928302919091018201526040517f883bdbfd00000000000000000000000000000000000000000000000000000000815260048101828152835160248301528351600093849373ffffffffffffffffffffffffffffffffffffffff8b169363883bdbfd9388939192839260449091019185820191028083838b5b83811015614978578181015183820152602001614960565b505050509050019250505060006040518083038186803b15801561499b57600080fd5b505afa1580156149af573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160409081528110156149f657600080fd5b8101908080516040519392919084640100000000821115614a1657600080fd5b908301906020820185811115614a2b57600080fd5b8251866020820283011164010000000082111715614a4857600080fd5b82525081516020918201928201910280838360005b83811015614a75578181015183820152602001614a5d565b5050505090500160405260200180516040519392919084640100000000821115614a9e57600080fd5b908301906020820185811115614ab357600080fd5b8251866020820283011164010000000082111715614ad057600080fd5b82525081516020918201928201910280838360005b83811015614afd578181015183820152602001614ae5565b5050505090500160405250505091509150600082600081518110614b1d57fe5b602002602001015183600181518110614b3257fe5b6020026020010151039050600082600081518110614b4c57fe5b602002602001015183600181518110614b6157fe5b60200260200101510390508763ffffffff168260060b81614b7e57fe5b05965060008260060b128015614ba857508763ffffffff168260060b81614ba157fe5b0760060b15155b15614bd3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909601955b63ffffffff881673ffffffffffffffffffffffffffffffffffffffff0277ffffffffffffffffffffffffffffffffffffffff00000000602083901b1677ffffffffffffffffffffffffffffffffffffffffffffffff821681614c3157fe5b0496505050505050509250929050565b614c49614e4b565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161115614c81579192915b506040805160608101825273ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015262ffffff169181019190915290565b6000614cca8383614cee565b90503373ffffffffffffffffffffffffffffffffffffffff82161461202157600080fd5b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff1610614d3057600080fd5b508051602080830151604093840151845173ffffffffffffffffffffffffffffffffffffffff94851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b8082018281101561202157600080fd5b604080518082019091526000808252602082015290565b604080516060810182526000808252602082018190529181019190915290565b8035610b2381615f52565b60008083601f840112614e87578182fd5b50813567ffffffffffffffff811115614e9e578182fd5b6020830191508360208083028501011115613fa057600080fd5b600082601f830112614ec8578081fd5b81356020614edd614ed883615ec8565b615ea4565b8281528181019085830183850287018401881015614ef9578586fd5b855b85811015614f345781356fffffffffffffffffffffffffffffffff81168114614f22578788fd5b84529284019290840190600101614efb565b5090979650505050505050565b80518015158114610b2357600080fd5b600082601f830112614f61578081fd5b8135614f6f614ed882615ee6565b818152846020838601011115614f83578283fd5b816020850160208301379081016020019190915292915050565b80516dffffffffffffffffffffffffffff81168114610b2357600080fd5b805161ffff81168114610b2357600080fd5b803562ffffff81168114610b2357600080fd5b8035610b2381615f83565b600060208284031215614ffc578081fd5b813561500781615f52565b9392505050565b60008060408385031215615020578081fd5b823561502b81615f52565b946020939093013593505050565b60008060006060848603121561504d578081fd5b833561505881615f52565b925060208401359150604084013561506f81615f52565b809150509250925092565b600080600080600060a08688031215615091578283fd5b853561509c81615f52565b94506020860135935060408601356150b381615f52565b92506060860135915060808601356150ca81615f52565b809150509295509295909350565b600080600080608085870312156150ed578182fd5b84356150f881615f52565b93506020850135925060408501359150606085013561511681615f52565b939692955090935050565b60008060008060008060c08789031215615139578384fd5b863561514481615f52565b95506020870135945060408701359350606087013561516281615f95565b9598949750929560808101359460a0909101359350915050565b6000806020838503121561518e578182fd5b823567ffffffffffffffff8111156151a4578283fd5b6151b085828601614e76565b90969095509350505050565b600080600080608085870312156151d1578182fd5b843567ffffffffffffffff808211156151e8578384fd5b818701915087601f8301126151fb578384fd5b8135602061520b614ed883615ec8565b82815281810190858301885b858110156152405761522e8e8684358b0101614f51565b84529284019290840190600101615217565b50909950505088013592505080821115615258578384fd5b5061526587828801614eb8565b93505061527460408601614fcd565b915061528260608601614fe0565b905092959194509250565b60006020828403121561529e578081fd5b61500782614f41565b6000806000604084860312156152bb578081fd5b83359250602084013567ffffffffffffffff8111156152d8578182fd5b6152e486828701614e76565b9497909650939450505050565b600060208284031215615302578081fd5b813567ffffffffffffffff811115615318578182fd5b613d0a84828501614f51565b600080600060608486031215615338578081fd5b833567ffffffffffffffff81111561534e578182fd5b61535a86828701614f51565b93505061536960208501614fcd565b9150604084013561506f81615f83565b60006020828403121561538a578081fd5b813561500781615f74565b600080604083850312156153a7578182fd5b505080516020909101519092909150565b600080600080606085870312156153cd578182fd5b8435935060208501359250604085013567ffffffffffffffff808211156153f2578384fd5b818701915087601f830112615405578384fd5b813581811115615413578485fd5b886020828501011115615424578485fd5b95989497505060200194505050565b600060208284031215615444578081fd5b815167ffffffffffffffff81111561545a578182fd5b8201601f8101841361546a578182fd5b8051615478614ed882615ee6565b81815285602083850101111561548c578384fd5b610e2c826020830160208601615f26565b6000602082840312156154ae578081fd5b813567ffffffffffffffff808211156154c5578283fd5b90830190608082860312156154d8578283fd5b6040516080810181811083821117156154ed57fe5b6040528235828111156154fe578485fd5b61550a87828601614f51565b8252506020830135915061551d82615f52565b816020820152604083013560408201526060830135606082015280935050505092915050565b600060e08284031215615554578081fd5b60405160e0810181811067ffffffffffffffff8211171561557157fe5b60405261557d83614e6b565b815261558b60208401614e6b565b602082015261559c60408401614fcd565b60408201526155ad60608401614e6b565b60608201526080830135608082015260a083013560a08201526155d260c08401614e6b565b60c08201529392505050565b6000602082840312156155ef578081fd5b813567ffffffffffffffff811115615605578182fd5b820160808185031215615007578182fd5b600060e08284031215610836578081fd5b600060a08284031215610836578081fd5b60006101008284031215610836578081fd5b60006020828403121561565b578081fd5b813567ffffffffffffffff80821115615672578283fd5b9083019060408286031215615685578283fd5b60405160408101818110838211171561569a57fe5b6040528235828111156156ab578485fd5b6156b787828601614f51565b825250602083013592506156ca83615f52565b6020810192909252509392505050565b6000806000606084860312156156ee578081fd5b6156f784614f9d565b925061570560208501614f9d565b9150604084015161506f81615f83565b600080600080600080600060e0888a03121561572f578485fd5b875161573a81615f52565b602089015190975061574b81615f74565b955061575960408901614fbb565b945061576760608901614fbb565b935061577560808901614fbb565b925060a088015161578581615f95565b915061579360c08901614f41565b905092959891949750929550565b6000602082840312156157b2578081fd5b61500782614fcd565b6000602082840312156157cc578081fd5b5035919050565b6000602082840312156157e4578081fd5b5051919050565b600080604083850312156157fd578182fd5b82359150602083013561580f81615f52565b809150509250929050565b6000806000806080858703121561582f578182fd5b84359350602085013561584181615f52565b925060408501359150606085013561511681615f52565b60008060006060848603121561586c578081fd5b8335925060208401359150604084013561506f81615f52565b60008060008060006080868803121561589c578283fd5b8535945060208601359350604086013567ffffffffffffffff8111156158c0578384fd5b6158cc88828901614e76565b90945092505060608601356150ca81615f52565b600080600080608085870312156158f5578182fd5b845161590081615f83565b8094505060208501518060060b8114615917578283fd5b604086015190935061592881615f52565b915061528260608601614f41565b73ffffffffffffffffffffffffffffffffffffffff169052565b60008151808452615968816020860160208601615f26565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60020b9052565b62ffffff169052565b606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b6000828483379101908152919050565b60008251615a32818460208701615f26565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a06080830152615acb60a0830184615950565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015615b6d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452615b5b858351615950565b94509285019290850190600101615b21565b5092979650505050505050565b6000602082526150076020830184615950565b6020810160058310615b9b57fe5b91905290565b60208082526003908201527f4f4e490000000000000000000000000000000000000000000000000000000000604082015260600190565b60208082526003908201527f4e454f0000000000000000000000000000000000000000000000000000000000604082015260600190565b60208082526012908201527f546f6f206d756368207265717565737465640000000000000000000000000000604082015260600190565b60208082526002908201527f5444000000000000000000000000000000000000000000000000000000000000604082015260600190565b60208082526013908201527f546f6f206c6974746c6520726563656976656400000000000000000000000000604082015260600190565b600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b600061016082019050615d0c828451615936565b6020830151615d1e6020840182615936565b506040830151615d3160408401826159a1565b506060830151615d44606084018261599a565b506080830151615d57608084018261599a565b5060a083015160a083015260c083015160c083015260e083015160e083015261010080840151818401525061012080840151615d9582850182615936565b505061014092830151919092015290565b600060208252825160406020840152615dc26060840182615950565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401528091505092915050565b61ffff91909116815260200190565b90815260200190565b600085825284602083015273ffffffffffffffffffffffffffffffffffffffff8416604083015260806060830152613ef86080830184615950565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615e75578283fd5b83018035915067ffffffffffffffff821115615e8f578283fd5b602001915036819003821315613fa057600080fd5b60405181810167ffffffffffffffff81118282101715615ec057fe5b604052919050565b600067ffffffffffffffff821115615edc57fe5b5060209081020190565b600067ffffffffffffffff821115615efa57fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b83811015615f41578181015183820152602001615f29565b83811115610c555750506000910152565b73ffffffffffffffffffffffffffffffffffffffff8116811461147957600080fd5b8060020b811461147957600080fd5b63ffffffff8116811461147957600080fd5b60ff8116811461147957600080fdfea164736f6c6343000706000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.0; import {IUniversalRouter} from '../../protocols/universal-router/interfaces/IUniversalRouter.sol'; import {RouterParameters} from '../../protocols/universal-router/types/RouterParameters.sol'; library UniversalRouterDeployer { function deploy( address permit2, address weth9, address v2Factory, address v3Factory, bytes32 v2PairInitCodeHash, bytes32 v3PoolInitCodeHash, address v4PoolManager, address v3NFTPositionManager, address v4PositionManager ) internal returns (IUniversalRouter router) { RouterParameters memory params = RouterParameters({ permit2: permit2, weth9: weth9, v2Factory: v2Factory, v3Factory: v3Factory, pairInitCodeHash: v2PairInitCodeHash, poolInitCodeHash: v3PoolInitCodeHash, v4PoolManager: v4PoolManager, v3NFTPositionManager: v3NFTPositionManager, v4PositionManager: v4PositionManager }); bytes memory initcode_ = abi.encodePacked(initcode(), abi.encode(params)); assembly { router := create2(0, add(initcode_, 32), mload(initcode_), hex'00') } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/universal-router/contracts/UniversalRouter.sol */ function initcode() internal pure returns (bytes memory) { return hex'6101a0604052346102d657604051601f614f3938819003918201601f19168301916001600160401b038311848410176102c257808492610120946040528339810103126102d6576040519061012082016001600160401b038111838210176102c25760405261006d816102f9565b825261007b602082016102f9565b6020830190815261008e604083016102f9565b604084019081526100a1606084016102f9565b93606081019485526080840151946080820195865260a08501519560a083019687526100cf60c087016102f9565b9660c084019788526100f66101006100e960e08a016102f9565b988960e0880152016102f9565b97886101008601526101066102da565b6001600160a01b03988916815298881660208a0190815290519451965190989796871696908116959416936101396102da565b968752602087019586525192519151905160405190936001600160a01b0393841693169060808101906001600160401b038211818310176102c257604091825282815260208101948552808201938452606001948552608091909152905160a05290516001600160a01b0390811660c052915160e052610100929092529151821661012052915181166101405291518216610160529151166101805251614c2b908161030e82396080518181816115d90152818161182701526137e4015260a0518181816115b80152818161184901526137c3015260c05181612ee6015260e05181612f39015261010051818181609e01528181610449015281816105b1015281816123240152818161288d0152818161431b015281816143ac015281816144b4015281816146350152614a45015261012051818181602f01528181611cb40152611e270152610140518181816112450152818161206201526133610152610160518181816106e301528181612458015261255101526101805181818161052701526129860152f35b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b60408051919082016001600160401b038111838210176102c257604052565b51906001600160a01b03821682036102d65756fe60c060405260043610156100c6575b3615610018575f80fd5b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633141580610086575b61005e57005b7f38bbd576000000000000000000000000000000000000000000000000000000005f5260045ffd5b5073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016331415610058565b5f3560e01c806324856bc3146108685780633593564c14610707578063817122dc1461069957806391dd73461461054b578063d0c9f6cb146104dd578063d737d0c71461046d578063dc4c90d3146103ff5763fa461e330361000e57346102e05760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102e05760243560043560443567ffffffffffffffff81116102e057610177903690600401610942565b5f8313918215806103f5575b6103cd578181016040828203126102e057813567ffffffffffffffff81116102e057820181601f820112156102e05780356101bd81612c69565b926101cb6040519485612c28565b818452602082840101116102e0575f928160208094018483013701015260208101359173ffffffffffffffffffffffffffffffffffffffff83168093036102e05761021591612e12565b90601790602b83106103a5578035968760601c9561024362ffffff8585013560601c9a60481c168a89612e65565b73ffffffffffffffffffffffffffffffffffffffff3391160361037d571561037357508685105b156102805750505061027e93503391612f86565b005b91935091939482602b0180602b116103465784106102e457508282116102e05781019103907f80000000000000000000000000000000000000000000000000000000000000008410156102e05761027e936102db3391612ca3565b613018565b5f80fd5b925050507faf28d9864a81dfdf71cab65f4e5d79a0cf9b083905fb8971425e6cb581b3f6929291925c821161031e5761027e923391612f86565b7f739dbe52000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b955084871061026a565b7f32b13d91000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f3b99b53d000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f316cf0eb000000000000000000000000000000000000000000000000000000005f5260045ffd5b505f851315610183565b346102e0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102e057602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102e0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102e05760207f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b346102e0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102e057602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102e05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102e05760043567ffffffffffffffff81116102e05761059a903690600401610942565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163303610671576105e091613404565b90818303610649575f5b83811061061d57610619604051610602602082612c28565b5f81526040519182916020835260208301906109a1565b0390f35b8061064361062e60019387896109e4565b3560f81c61063d838787610a6e565b91613ac3565b016105ea565b7faaad13f7000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fae18210a000000000000000000000000000000000000000000000000000000005f5260045ffd5b346102e0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102e057602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102e05760043567ffffffffffffffff81116102e057610751903690600401610942565b60243567ffffffffffffffff81116102e057610771903690600401610970565b916044354211610840573330146108375773ffffffffffffffffffffffffffffffffffffffff7f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c1661080f576107ea93337f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085d610a89565b5f7f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085d005b7f6f5ffb7e000000000000000000000000000000000000000000000000000000005f5260045ffd5b61027e93610a89565b7f5bf6f916000000000000000000000000000000000000000000000000000000005f5260045ffd5b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102e05760043567ffffffffffffffff81116102e0576108b2903690600401610942565b60243567ffffffffffffffff81116102e0576108d2903690600401610970565b913330146108375773ffffffffffffffffffffffffffffffffffffffff7f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c1661080f576107ea93337f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085d610a89565b9181601f840112156102e05782359167ffffffffffffffff83116102e057602083818601950101116102e057565b9181601f840112156102e05782359167ffffffffffffffff83116102e0576020808501948460051b0101116102e057565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b908210156109f0570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156102e0570180359067ffffffffffffffff82116102e0576020019181360383136102e057565b908210156109f057610a859160051b810190610a1d565b9091565b9290808203612bb7579291905f915b848310610aa6575050505050565b9091929394610ab68487876109e4565b3592610ac3858285610a6e565b979092606097603f8760f81c1695600196602181105f14612a1c5760108110156122b15760088110156115245780610eeb5750610b0560208701359b87612e3a565b9590608088013515610ee4577f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c9c5b610b3f89356131e2565b9d9188816080527f80000000000000000000000000000000000000000000000000000000000000008314610e58575b50505b604260a052602b7f80000000000000000000000000000000000000000000000000000000000000008210156102e05760a0518f908a10610e52575030915b8982116102e05760409173ffffffffffffffffffffffffffffffffffffffff5f6080513595610cb2610c2b610c5d85610c018b60601c6017608051013560601c62ffffff8183109e60481c1691612e65565b16968a8614610e37576401000276a49b5b878b519485938d60208601526060850190608051612ccf565b91168b830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c28565b8488519a8b98899788967f128acb080000000000000000000000000000000000000000000000000000000088521660048701528b6024870152604486015216606484015260a0608484015260a48301906109a1565b03925af1908115610e2c575f905f92610df0575b610cd6935015610de95750612ca3565b60a0519096908110610d1d573090806017116102e0576080805160170190527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe90196610b71565b50979396929a50979490989360409091013511610dc1575b159081610d96575b50610d4f575060010191909392610a98565b90610d926040519283927f2c4029e900000000000000000000000000000000000000000000000000000000845260048401526040602484015260448301906109a1565b0390fd5b7f8000000000000000000000000000000000000000000000000000000000000000915016155f610d3d565b7f39d35496000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050612ca3565b9150506040823d8211610e24575b81610e0b60409383612c28565b810103126102e057816020610cd6935191015191610cc6565b3d9150610dfe565b6040513d5f823e3d90fd5b73fffd8963efd1fc6a506488495d951d5263988d259b610c12565b91610baf565b6014919250106103a5576020602491604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301523560601c5afa908115610e2c575f91610eb3575b505f80610b6e565b90506020813d8211610edc575b81610ecd60209383612c28565b810103126102e057515f610eab565b3d9150610ec0565b309c610b35565b6001819c929a97939b96999598949c145f14611024575090610f1260208201359282612e3a565b60808301351561101d577f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c915b6040610f4c85356131e2565b9401357faf28d9864a81dfdf71cab65f4e5d79a0cf9b083905fb8971425e6cb581b3f6925d7f80000000000000000000000000000000000000000000000000000000000000008510156102e057610fa6936102db86612ca3565b9091901561100e5750610fb890612ca3565b03610fe6575f7faf28d9864a81dfdf71cab65f4e5d79a0cf9b083905fb8971425e6cb581b3f6925d5b610d35565b7fd4e0248e000000000000000000000000000000000000000000000000000000005f5260045ffd5b6110189150612ca3565b610fb8565b3091610f40565b6002810361106e5750610fe191604081013591507f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c61106760208301356131e2565b9135613348565b93949193909290600381036112a1575050508135820163ffffffff60208401351683019163ffffffff83351693602080850194860101910110611294577f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c926040519273ffffffffffffffffffffffffffffffffffffffff60208501957f2a2d80d10000000000000000000000000000000000000000000000000000000087521660248501526060604485015260e484019280357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156102e05781016020813591019467ffffffffffffffff82116102e0578160071b360386136102e05781906060608489015252610104860194905f905b80821061127657505050936111ff5f9694829461122b9460408973ffffffffffffffffffffffffffffffffffffffff6111c360208e9d01612d3c565b1660a4880152013560c48601527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc858403016064860152612ccf565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c28565b51908273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af190611270612d0d565b91610d35565b909195608080826112896001948b612d9d565b019701920190611187565b633b99b53d5f526004601cfd5b91949390925090600481036113fa57506112be60208201356131e2565b9073ffffffffffffffffffffffffffffffffffffffff8060408301351691351680155f1461133457504790811061130c57806112fc575b5050610d35565b611305916134c8565b5f806112f5565b7f6a12f104000000000000000000000000000000000000000000000000000000005f5260045ffd5b91604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481875afa928315610e2c575f936113c7575b50821061139f578161138e575b505050610d35565b61139792613a14565b5f8080611386565b7f675cae38000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092506020813d82116113f2575b816113e260209383612c28565b810103126102e05751915f611379565b3d91506113d5565b600581036114215750806040610fe19201359061141a60208201356131e2565b903561326c565b600681036114f9575060408101359073ffffffffffffffffffffffffffffffffffffffff61145260208301356131e2565b9135168061146e5750611468610fe192476139d2565b906134c8565b906040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481865afa908115610e2c575f916114c6575b50610fe1936114c0916139d2565b91613a14565b90506020813d82116114f1575b816114e060209383612c28565b810103126102e05751610fe16114b2565b3d91506114d3565b7fd76a1e9e000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b6008819c929a97939b96999598949c145f146117d9575061154a6020830135918361319d565b906080840135156117d2577f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c915b61158385356131e2565b9282156109f057611593826131c1565b83600110156109f0576115b56115fd916115af602086016131c1565b906141ee565b907f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614226565b9485816117b8575b5050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82018281116103465761165a61165573ffffffffffffffffffffffffffffffffffffffff92858561324f565b6131c1565b1693604051927f70a0823100000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff8516928360048601526020856024818a5afa948515610e2c575f9561177b575b50946116c8929160209596613586565b6024604051809581937f70a0823100000000000000000000000000000000000000000000000000000000835260048301525afa918215610e2c575f92611747575b506040611719929301359261325f565b1015610d35577f849eaf98000000000000000000000000000000000000000000000000000000005f5260045ffd5b91506020823d8211611773575b8161176160209383612c28565b810103126102e0579051906040611709565b3d9150611754565b92919450946020833d82116117b0575b8161179860209383612c28565b810103126102e05791519194919390916116c86116b8565b3d915061178b565b6117ca926117c5856131c1565b612f86565b5f8085611605565b3091611579565b60098103611b4357506117ec908261319d565b608083013515611b3c577f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c915b61182484356131e2565b917f0000000000000000000000000000000000000000000000000000000000000000937f0000000000000000000000000000000000000000000000000000000000000000955f9560028510611b14576020820135977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8601868111610346579190825b6118fd575050506040013586116118d55782156109f057610fe195856118d0926117c5856131c1565b613586565b7f8ab0bc16000000000000000000000000000000000000000000000000000000005f5260045ffd5b90919897507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8901978989116103465761193e6116556119609a898961324f565b61195561194f6116558d8b8b61324f565b826141ee565b8185879d939d614226565b90604051907f0902f1ac00000000000000000000000000000000000000000000000000000000825260608260048173ffffffffffffffffffffffffffffffffffffffff87165afa918215610e2c575f905f93611ab7575b5073ffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8082931694169d169116145f14611ab15799905b9980158015611aa9575b611a815782611a0891613988565b916103e88302928084046103e8149015171561034657611a279161325f565b6103e58102908082046103e5149015171561034657611a459161399b565b6001810180911161034657988015610346577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019190826118a7565b7f7b9c8916000000000000000000000000000000000000000000000000000000005f5260045ffd5b5081156119fa565b906119f0565b6dffffffffffffffffffffffffffff80945073ffffffffffffffffffffffffffffffffffffffff9250611b01839260603d8111611b0d575b611af98183612c28565b810190613550565b509590935050506119b7565b503d611aef565b7f20db8267000000000000000000000000000000000000000000000000000000005f5260045ffd5b309161181a565b93949193909290600a8103611c445750505063ffffffff60c08301351682019063ffffffff82351690836020808501948401019101106112945760a061122b5f946111ff86957f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c9560405195869473ffffffffffffffffffffffffffffffffffffffff60208701997f2b67b570000000000000000000000000000000000000000000000000000000008b52166024870152611c026044870182612d9d565b73ffffffffffffffffffffffffffffffffffffffff611c2360808301612d3c565b1660c4870152013560e4850152610100610104850152610124840191612ccf565b91949390929091600b8103611dfb575050611c64602082013591356131e2565b90807f80000000000000000000000000000000000000000000000000000000000000008103611dcc575050475b80611c9d575050610d35565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691823b156102e057604051907fd0e30db00000000000000000000000000000000000000000000000000000000082525f8260048186885af1918215610e2c5773ffffffffffffffffffffffffffffffffffffffff92611dbc575b501690308203611d3f575b506112f5565b60446020925f60405195869485937fa9059cbb000000000000000000000000000000000000000000000000000000008552600485015260248401525af18015610e2c57611d8e575b8080611d39565b611dae9060203d8111611db5575b611da68183612c28565b810190613237565b505f611d87565b503d611d9c565b5f611dc691612c28565b5f611d2e565b471015611c91577f6a12f104000000000000000000000000000000000000000000000000000000005f5260045ffd5b600c8103611f65575050611e0f81356131e2565b9073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481855afa928315610e2c575f93611f31575b5060200135821061130c5781611ea357505050610d35565b803b156102e0575f80916024604051809481937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528760048401525af18015610e2c57611f21575b503073ffffffffffffffffffffffffffffffffffffffff831603611f11575b80611386565b611f1a916134c8565b5f80611f0b565b5f611f2b91612c28565b5f611eec565b9092506020813d8211611f5d575b81611f4c60209383612c28565b810103126102e05751916020611e8b565b3d9150611f3f565b600d819c939c9b929597989b99949699145f146121ac57508a358b0198893594611f976020808d019e8d030187612f79565b116103a55773ffffffffffffffffffffffffffffffffffffffff7f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c169a935f5b8681101561203d578c73ffffffffffffffffffffffffffffffffffffffff61200760208f8560071b01016131c1565b160361201557600101611fd8565b7fe7002877000000000000000000000000000000000000000000000000000000005f5260045ffd5b50989593979694929b919a50985073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690813b156102e0576040517f0d58b1db000000000000000000000000000000000000000000000000000000008152602060048201526024810184905292839160448301915f905b8082106120fe5750505091815f81819503925af18015610e2c576120ee575b50610d35565b5f6120f891612c28565b5f6120e8565b9193509160808060019273ffffffffffffffffffffffffffffffffffffffff61212688612d3c565b16815273ffffffffffffffffffffffffffffffffffffffff61214a60208901612d3c565b16602082015273ffffffffffffffffffffffffffffffffffffffff61217160408901612d3c565b16604082015273ffffffffffffffffffffffffffffffffffffffff61219860608901612d3c565b1660608201520194019201859392916120c9565b80929b93989550600e919a97969450145f146114f95750604051907f70a0823100000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff813516600483015260208260248173ffffffffffffffffffffffffffffffffffffffff84860135165afa918215610e2c575f9261227d575b5060400135111580610fe15791506040517fa328167200000000000000000000000000000000000000000000000000000000602082015260048152611270602482612c28565b9091506020813d82116122a9575b8161229860209383612c28565b810103126102e05751906040612237565b3d915061228b565b6010819c929a97939b96999598949c145f146123cc575061230a915f9160405193849283927f48c89491000000000000000000000000000000000000000000000000000000008452602060048501526024840191612ccf565b03818373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af18015610e2c576123565750610d35565b3d805f833e6123658183612c28565b8101906020818303126102e05780519067ffffffffffffffff82116102e0570181601f820112156102e057805161239b81612c69565b926123a96040519485612c28565b818452602082840101116102e0575f928160208094018483015e0101525f6120e8565b80929495506011919350145f146124ae5750907fffffffff000000000000000000000000000000000000000000000000000000008135167f7ac2ff7b0000000000000000000000000000000000000000000000000000000081036124835750815f929183926040519283928337810183815203908273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af190611270612d0d565b7ff801e525000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b601281036127ad57507f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c917fffffffff000000000000000000000000000000000000000000000000000000008135167f0c49ccbe0000000000000000000000000000000000000000000000000000000081148015612784575b801561275b575b156124835750600481013573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016936040517f6352211e000000000000000000000000000000000000000000000000000000008152826004820152602081602481895afa908115610e2c5773ffffffffffffffffffffffffffffffffffffffff9182915f9161273d575b50169116908082149182156126a9575b8215612638575b50501561260d575091815f809481946040519384928337810182815203925af190611270612d0d565b7fbb25d4c5000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b909150604051917fe985e9c500000000000000000000000000000000000000000000000000000000835260048301526024820152602081604481885afa908115610e2c575f9161268b575b505f806125e4565b6126a3915060203d8111611db557611da68183612c28565b5f612683565b91506040517f081812fc0000000000000000000000000000000000000000000000000000000081528360048201526020816024818a5afa908115610e2c57839173ffffffffffffffffffffffffffffffffffffffff915f9161270f575b501614916125dd565b612730915060203d8111612736575b6127288183612c28565b81019061349c565b5f612706565b503d61271e565b612755915060203d8111612736576127288183612c28565b5f6125cd565b507f42966c6800000000000000000000000000000000000000000000000000000000811461252f565b507ffc6f7865000000000000000000000000000000000000000000000000000000008114612528565b601381036128b85750505f809160405173ffffffffffffffffffffffffffffffffffffffff60a060208301937f6276cbbe0000000000000000000000000000000000000000000000000000000085528261280682612d3c565b1660248501528261281960208301612d3c565b16604485015262ffffff61282f60408301612d5d565b16606485015261284160608201612d6d565b60020b60848501528261285660808301612d3c565b1660a485015201351660c482015260c4815261287360e482612c28565b51908273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af190611270612d0d565b601481036114f957507fffffffff000000000000000000000000000000000000000000000000000000008235167fdd46508f0000000000000000000000000000000000000000000000000000000081036124835750806004116102e05761294d6129477ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc830160048501612e12565b90612e12565b5f5b8181106129b1575050505f91829147918160405192839283378101848152039173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af190611270612d0d565b6129bc8183856109e4565b3560f81c8015908115612a11575b8115612a06575b506129de5760010161294f565b7f5d1d0f9f000000000000000000000000000000000000000000000000000000005f5260045ffd5b60039150145f6129d1565b6001811491506129ca565b9098959199506021819b939b989598979497145f146114f9575090612a4091613404565b612a836040959395519460208601967f24856bc3000000000000000000000000000000000000000000000000000000008852604060248801526064870191612ccf565b927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc858503016044860152818452602084019160208160051b86010194845f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603015b848310612b3d5750505050505050509181612b2e5f94938594037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612c28565b519082305af190611270612d0d565b90919293949596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08582030188528835828112156102e0578301906020823592019167ffffffffffffffff81116102e05780360383136102e057612ba760209283928b95612ccf565b9a01980196959493019190612ae9565b7fff633a38000000000000000000000000000000000000000000000000000000005f5260045ffd5b60a0810190811067ffffffffffffffff821117612bfb57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612bfb57604052565b67ffffffffffffffff8111612bfb57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b7f80000000000000000000000000000000000000000000000000000000000000008114610346575f0390565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b3d15612d37573d90612d1e82612c69565b91612d2c6040519384612c28565b82523d5f602084013e565b606090565b359073ffffffffffffffffffffffffffffffffffffffff821682036102e057565b359062ffffff821682036102e057565b35908160020b82036102e057565b908160209103126102e0575190565b359065ffffffffffff821682036102e057565b65ffffffffffff612e0c6060809373ffffffffffffffffffffffffffffffffffffffff612dc982612d3c565b16865273ffffffffffffffffffffffffffffffffffffffff612ded60208301612d3c565b16602087015283612e0060408301612d8a565b16604087015201612d8a565b16910152565b909163ffffffff82351682019263ffffffff8435169260208086019585010191011061129457565b909163ffffffff60608301351682019263ffffffff8435169260208086019585010191011061129457565b9073ffffffffffffffffffffffffffffffffffffffff9283821684841611612f71575b62ffffff90846040519381602086019616865216604084015216606082015260608152612eb6608082612c28565b5190206040517fff00000000000000000000000000000000000000000000000000000000000000602082019081527f000000000000000000000000000000000000000000000000000000000000000060601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602183015260358201929092527f00000000000000000000000000000000000000000000000000000000000000006055820152612f6a81607581016111ff565b5190201690565b909190612e88565b9190820180921161034657565b9092919073ffffffffffffffffffffffffffffffffffffffff84163003612fb357612fb1935061326c565b565b919273ffffffffffffffffffffffffffffffffffffffff8411612ff05773ffffffffffffffffffffffffffffffffffffffff612fb1941692613348565b7fc4bd89a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b939290602b82106103a5578235938460601c92601785013560601c9380851094859760481c62ffffff169061304c92612e65565b73ffffffffffffffffffffffffffffffffffffffff1692845f1460409673ffffffffffffffffffffffffffffffffffffffff80956130e15f9661313495613182576401000276a4925b846130af8e51978f94899560208701526060860191612ccf565b91168d830152037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101855284612c28565b89519b8c998a9889977f128acb080000000000000000000000000000000000000000000000000000000089521660048801526024870152604486015216606484015260a0608484015260a48301906109a1565b03925af18015610e2c575f925f9161314b57509192565b9250506040823d60401161317a575b8161316760409383612c28565b810103126102e057602082519201519192565b3d915061315a565b73fffd8963efd1fc6a506488495d951d5263988d2592613095565b9160608301358301916131ba602084359581860195030185612f79565b116103a557565b3573ffffffffffffffffffffffffffffffffffffffff811681036102e05790565b73ffffffffffffffffffffffffffffffffffffffff8116600181036132285750507f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c90565b60020361323457503090565b90565b908160209103126102e0575180151581036102e05790565b91908110156109f05760051b0190565b9190820391821161034657565b90919073ffffffffffffffffffffffffffffffffffffffff16806132945750612fb1916134c8565b7f800000000000000000000000000000000000000000000000000000000000000082146132c6575b91612fb192613a14565b9050604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481855afa8015610e2c575f90613314575b909250906132bc565b506020833d602011613340575b8161332e60209383612c28565b810103126102e057612fb1925161330b565b3d9150613321565b919273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691823b156102e0575f73ffffffffffffffffffffffffffffffffffffffff9384829681608496816040519b8c9a8b997f36c78516000000000000000000000000000000000000000000000000000000008b521660048a01521660248801521660448601521660648401525af18015610e2c576133fa5750565b5f612fb191612c28565b604081351891606082019363ffffffff6040840135169363ffffffe0601f8601169060608201602086013518179084019260608401359463ffffffff861694641fffffffe0608082019760051b1680915f925b80841061346f57506080925001019101101761129457565b90916020809163ffffffe0601f60808089890101359b848d18179b88010135011601019301929190613457565b908160209103126102e0575173ffffffffffffffffffffffffffffffffffffffff811681036102e05790565b5f80809381935af1156134d757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152fd5b51906dffffffffffffffffffffffffffff821682036102e057565b908160609103126102e05761356481613535565b91604061357360208401613535565b92015163ffffffff811681036102e05790565b91600282106139605781156109f05761359e836131c1565b82600110156109f0576135ba906115af602086979596016131c1565b50927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101937ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe8201955f906020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501965b8884106136415750505050505050505050565b61364f61165585848661324f565b9473ffffffffffffffffffffffffffffffffffffffff61367661165560018801868861324f565b921695604051917f0902f1ac0000000000000000000000000000000000000000000000000000000083526060836004818b5afa918215610e2c57895f945f9461390d575b5073ffffffffffffffffffffffffffffffffffffffff806dffffffffffffffffffffffffffff80602496979816971693169416841494855f146139075791935b604051938480927f70a082310000000000000000000000000000000000000000000000000000000082528d60048301525afa918215610e2c575f926138d8575b50808203928115928380156138d0575b611a8157826103e586029586046103e514911417156103465761376d9084613988565b916103e882029182046103e8141715610346576137939261378d91612f79565b9061399b565b90156138c9575f90915b8b8610156138c057906137be613808926115af61165560028a01888a61324f565b8193917f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614226565b915b96604051906138198a83612c28565b5f82528b368b840137803b156102e057613894945f8094604051978895869485937f022c0d9f0000000000000000000000000000000000000000000000000000000085526004850152602484015273ffffffffffffffffffffffffffffffffffffffff891660448401526080606484015260848301906109a1565b03925af1918215610e2c576001926138b0575b5093019261362e565b5f6138ba91612c28565b5f6138a7565b5087905f61380a565b5f9161379d565b50811561374a565b9091508981813d8311613900575b6138f08183612c28565b810103126102e05751905f61373a565b503d6138e6565b936136fa565b6dffffffffffffffffffffffffffff9550602493945073ffffffffffffffffffffffffffffffffffffffff86613951829360603d8111611b0d57611af98183612c28565b509890989796505050506136ba565b7fae52ad0c000000000000000000000000000000000000000000000000000000005f5260045ffd5b8181029291811591840414171561034657565b81156139a5570490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b61271082116139ec57612710916139e891613988565b0490565b7fdeaa01e6000000000000000000000000000000000000000000000000000000005f5260045ffd5b5f9182604492602095604051937fa9059cbb000000000000000000000000000000000000000000000000000000008552600485015260248401525af13d15601f3d1160015f511416171615613a6557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152fd5b929190600b84101561401c5760078403613c3557613ae292935061474f565b6020810190613af1828261475d565b90505f92613afe836131c1565b90613b0b604085016146bc565b906fffffffffffffffffffffffffffffffff821615613c1c575b92915f915b838310613bab5750505050506060016fffffffffffffffffffffffffffffffff80613b54836146bc565b169216918210613b62575050565b613b7c6fffffffffffffffffffffffffffffffff916146bc565b7f8b063d73000000000000000000000000000000000000000000000000000000005f521660045260245260445ffd5b8496506fffffffffffffffffffffffffffffffff613c0091613be7613be086613bda613c059798999a8c61475d565b906147b1565b9586614ad8565b613bf46080880188610a1d565b949093165f0391614938565b614bff565b946001613c1287936131c1565b9194930191613b2a565b9050613c2f613c2a83614314565b6148f3565b90613b25565b60068403613d2c57613c489293506146ad565b613c5460c082016146bc565b6fffffffffffffffffffffffffffffffff811615613cdb575b613cbe613c0060e092613c9d6fffffffffffffffffffffffffffffffff613c9660a088016146d9565b9216612ca3565b90613cac610100870187610a1d565b929091613cb936896146e6565b614938565b91016fffffffffffffffffffffffffffffffff80613b54836146bc565b50613ce860a082016146d9565b15613d125760e0613cbe613c00613d09613c2a613d04866131c1565b614314565b92505050613c6d565b60e0613cbe613c00613d09613c2a613d04602087016131c1565b60098403613ecf57613d3f92935061474f565b6020810190613d4e828261475d565b5f939150613d5e604084016146bc565b613d67846131c1565b916fffffffffffffffffffffffffffffffff821615613ebb575b92919290815b613e0457505050506060016fffffffffffffffffffffffffffffffff80613dad836146bc565b169216918211613dbb575050565b613dd56fffffffffffffffffffffffffffffffff916146bc565b7f12bacdd3000000000000000000000000000000000000000000000000000000005f521660045260245260445ffd5b829395506fffffffffffffffffffffffffffffffff613e7b91613e61613e5a613e31613e8596978a61475d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8901916147b1565b9889614ad8565b90613e6f60808b018b610a1d565b94909316911590614938565b600f0b5f036148f3565b937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613eb186926131c1565b9392019081613d87565b9050613ec9613c2a8361462e565b90613d81565b60088414613f06575050505b7f5cda29d7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b613f119293506146ad565b613f1d60c082016146bc565b6fffffffffffffffffffffffffffffffff811615613fa1575b613f84613c2a613f7c6fffffffffffffffffffffffffffffffff60e094613f5f60a088016146d9565b613f6d610100890189610a1d565b9390921690613cb9368a6146e6565b600f0b612ca3565b91016fffffffffffffffffffffffffffffffff80613dad836146bc565b50613fae60a082016146d9565b15613ff15760e0613f84613c2a613f7c6fffffffffffffffffffffffffffffffff613fe6613c2a613fe1602089016131c1565b61462e565b945050505050613f36565b60e0613f84613c2a613f7c6fffffffffffffffffffffffffffffffff613fe6613c2a613fe1886131c1565b92600c81036140a05750614030919261461b565b9061403a8161462e565b91808311614070575090612fb1917f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c90614495565b90507f12bacdd3000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b600f810361412357506140b3919261461b565b906140bd81614314565b918083106140f3575090612fb1917f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c9061438d565b90507f8b063d73000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b600b810361417c575061413a90612fb192936142fc565b156141715761416b827f0e87e1788ebd9ed6a7e63c70a374cd3283e41cad601d21fbe27863899ed4a7085c92614454565b91614495565b61416b823092614454565b600e81036141af57506141a36141996141a992612fb194956142fc565b92829492916131e2565b92614440565b9161438d565b92601084146141c057505050613edb565b612fb19293506141d66141df926141a9926142fc565b929193906131e2565b916141e984614314565b6139d2565b73ffffffffffffffffffffffffffffffffffffffff821673ffffffffffffffffffffffffffffffffffffffff8216105f14610a855791565b91612f6a9073ffffffffffffffffffffffffffffffffffffffff947fffffffffffffffffffffffffffffffffffffffff0000000000000000000000006040519181602084019460601b16845260601b1660348201526028815261428a604882612c28565b5190206111ff604051938492602084019687917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000605594927fff00000000000000000000000000000000000000000000000000000000000000855260601b166001840152601583015260358201520190565b90606011611294578035916040602083013592013590565b61433f81307f00000000000000000000000000000000000000000000000000000000000000006147f1565b905f821261434b575090565b73ffffffffffffffffffffffffffffffffffffffff907f4c085bf1000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b9091801561443b5773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803b156102e0575f928360649273ffffffffffffffffffffffffffffffffffffffff948560405198899788967f0b0d9c0900000000000000000000000000000000000000000000000000000000885216600487015216602485015260448401525af18015610e2c576133fa5750565b505050565b9081614450576132349150614314565b5090565b907f8000000000000000000000000000000000000000000000000000000000000000820361448657613234915061488b565b8161445057613234915061462e565b5f9183156146155773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691823b156102e05773ffffffffffffffffffffffffffffffffffffffff604051917fa584119400000000000000000000000000000000000000000000000000000000835216908160048201525f8160248183885af18015610e2c57614600575b50806145b35750506020906004604051809581937f11da60b40000000000000000000000000000000000000000000000000000000083525af19081156145a7575061457c5750565b61459d9060203d6020116145a0575b6145958183612c28565b810190612d7b565b50565b503d61458b565b604051903d90823e3d90fd5b839483602094936145c393612f86565b6004604051809581937f11da60b40000000000000000000000000000000000000000000000000000000083525af19081156145a7575061457c5750565b61460d9194505f90612c28565b5f925f614534565b50505050565b9190604011611294576020823592013590565b61465981307f00000000000000000000000000000000000000000000000000000000000000006147f1565b905f821361466b575061323490612ca3565b73ffffffffffffffffffffffffffffffffffffffff907f3351b260000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b90610140116112945780350190565b356fffffffffffffffffffffffffffffffff811681036102e05790565b3580151581036102e05790565b91908260a09103126102e0576040516146fe81612bdf565b608061474a81839561470f81612d3c565b855261471d60208201612d3c565b602086015261472e60408201612d5d565b604086015261473f60608201612d6d565b606086015201612d3c565b910152565b9060a0116112945780350190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156102e0570180359067ffffffffffffffff82116102e057602001918160051b360383136102e057565b91908110156109f05760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61813603018212156102e0570190565b73ffffffffffffffffffffffffffffffffffffffff809381602094165f52168252602460405f2060405194859384927ff135baaa0000000000000000000000000000000000000000000000000000000084526004840152165afa908115610e2c575f9161485c575090565b90506020813d602011614883575b8161487760209383612c28565b810103126102e0575190565b3d915061486a565b73ffffffffffffffffffffffffffffffffffffffff16806148ab57504790565b6020602491604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa908115610e2c575f9161485c575090565b906fffffffffffffffffffffffffffffffff821680920361491057565b7f93dafdf1000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092908315614abd576401000276a4905b60405194606086019386851067ffffffffffffffff861117612bfb5773ffffffffffffffffffffffffffffffffffffffff9788608095614a2b946020986040521515998a8152888101908a82528360408201931683526040519c8d998a997ff3cd914c000000000000000000000000000000000000000000000000000000008b528281511660048c0152828d8201511660248c015262ffffff60408201511660448c0152606081015160020b60648c0152015116608489015251151560a48801525160c4870152511660e4850152610120610104850152610124840191612ccf565b03815f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af1928315610e2c575f93614a89575b505f1303614a8357600f0b90565b60801d90565b9092506020813d602011614ab5575b81614aa560209383612c28565b810103126102e05751915f614a75565b3d9150614a98565b73fffd8963efd1fc6a506488495d951d5263988d2590614949565b905f6080604051614ae881612bdf565b8281528260208201528260408201528260608201520152614b08826131c1565b73ffffffffffffffffffffffffffffffffffffffff82169173ffffffffffffffffffffffffffffffffffffffff82168084105f14614be0575073ffffffffffffffffffffffffffffffffffffffff905b1680921492602081013562ffffff81168091036102e0576040820135918260020b8093036102e057606001359273ffffffffffffffffffffffffffffffffffffffff84168094036102e05773ffffffffffffffffffffffffffffffffffffffff9060405195614bc687612bdf565b865216602085015260408401526060830152608082015291565b91505073ffffffffffffffffffffffffffffffffffffffff8291614b58565b5f81600f0b12614910576fffffffffffffffffffffffffffffffff169056fea164736f6c634300081a000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {IFeeCollector} from '../../protocols/util-contracts/interfaces/IFeeCollector.sol'; library FeeCollectorDeployer { function deploy(address owner, address universalRouter, address permit2, address feeToken) internal returns (IFeeCollector feeCollector) { bytes memory args = abi.encode(owner, universalRouter, permit2, feeToken); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { feeCollector := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/util-contracts/src/FeeCollector.sol */ function initcode() internal pure returns (bytes memory) { return hex'60c060405234801561000f575f80fd5b50604051610d11380380610d1183398101604081905261002e916100bc565b5f80546001600160a01b0319166001600160a01b03861690811782556040518692907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600180546001600160a01b0319166001600160a01b0394851617905582166080521660a0525061010d565b80516001600160a01b03811681146100b7575f80fd5b919050565b5f805f80608085870312156100cf575f80fd5b6100d8856100a1565b93506100e6602086016100a1565b92506100f4604086016100a1565b9150610102606086016100a1565b905092959194509250565b60805160a051610bc16101505f395f818160f8015281816103fa015281816104f201528181610527015261064d01525f81816101c1015261048f0152610bc15ff3fe6080604052600436106100dc575f3560e01c80638da5cb5b1161007c578063b4a25ce711610057578063b4a25ce714610261578063bbf20c1514610291578063d88d35de146102b0578063f2fde38b146102cf575f80fd5b80638da5cb5b1461020257806394a228b514610220578063b2ef14e314610242575f80fd5b8063481fb142116100b7578063481fb14214610177578063628a4b2f14610191578063647846a5146101b057806365d82753146101e3575f80fd5b806312261ee7146100e75780631ac169861461013757806335a9e4df14610158575f80fd5b366100e357005b5f80fd5b3480156100f2575f80fd5b5061011a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610142575f80fd5b506101566101513660046108ee565b6102ee565b005b348015610163575f80fd5b5060015461011a906001600160a01b031681565b348015610182575f80fd5b5061011a6001600160a01b0381565b34801561019c575f80fd5b506101566101ab36600461094d565b610330565b3480156101bb575f80fd5b5061011a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101ee575f80fd5b506101566101fd3660046109b0565b6103c2565b34801561020d575f80fd5b505f5461011a906001600160a01b031681565b34801561022b575f80fd5b506102345f1981565b60405190815260200161012e565b34801561024d575f80fd5b5061015661025c3660046109ef565b610459565b34801561026c575f80fd5b5061027a65ffffffffffff81565b60405165ffffffffffff909116815260200161012e565b34801561029c575f80fd5b506101566102ab366004610a19565b6104ba565b3480156102bb575f80fd5b506101566102ca366004610a92565b61060d565b3480156102da575f80fd5b506101566102e936600461094d565b6106b5565b5f546001600160a01b031633146103205760405162461bcd60e51b815260040161031790610b03565b60405180910390fd5b61032b838383610728565b505050565b5f546001600160a01b031633146103595760405162461bcd60e51b815260040161031790610b03565b600154604080516001600160a01b03928316815291831660208301527f736ee8e49f5bc52c4483e2bf96ce5c99a25af7c12037267ccde543b28ab63071910160405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b5f546001600160a01b031633146103eb5760405162461bcd60e51b815260040161031790610b03565b5f5b8181101561032b576104517f00000000000000000000000000000000000000000000000000000000000000005f85858581811061042c5761042c610b29565b9050602002016020810190610441919061094d565b6001600160a01b031691906107b0565b6001016103ed565b5f546001600160a01b031633146104825760405162461bcd60e51b815260040161031790610b03565b6104b66001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016838361082c565b5050565b5f546001600160a01b031633146104e35760405162461bcd60e51b815260040161031790610b03565b5f5b818110156105fa576105257f00000000000000000000000000000000000000000000000000000000000000005f1985858581811061042c5761042c610b29565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166387517c4584848481811061056657610566610b29565b905060200201602081019061057b919061094d565b60015460405160e084901b6001600160e01b03191681526001600160a01b0392831660048201529082166024820152604481019190915265ffffffffffff60648201526084015f604051808303815f87803b1580156105d8575f80fd5b505af11580156105ea573d5f803e3d5ffd5b5050600190920191506104e59050565b50610606858585610728565b5050505050565b5f546001600160a01b031633146106365760405162461bcd60e51b815260040161031790610b03565b60405163cc53287f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cc53287f906106849085908590600401610b3d565b5f604051808303815f87803b15801561069b575f80fd5b505af11580156106ad573d5f803e3d5ffd5b505050505050565b5f546001600160a01b031633146106de5760405162461bcd60e51b815260040161031790610b03565b5f80546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b6001546040515f916001600160a01b03169083906107499087908790610ba5565b5f6040518083038185875af1925050503d805f8114610783576040519150601f19603f3d011682016040523d82523d5f602084013e610788565b606091505b50509050806107aa5760405163cee8b77760e01b815260040160405180910390fd5b50505050565b5f60405163095ea7b360e01b81526001600160a01b038416600482015282602482015260205f6044835f895af13d15601f3d1160015f5114161716915050806107aa5760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606401610317565b5f60405163a9059cbb60e01b81526001600160a01b038416600482015282602482015260205f6044835f895af13d15601f3d1160015f5114161716915050806107aa5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610317565b5f8083601f8401126108b9575f80fd5b50813567ffffffffffffffff8111156108d0575f80fd5b6020830191508360208285010111156108e7575f80fd5b9250929050565b5f805f60408486031215610900575f80fd5b833567ffffffffffffffff811115610916575f80fd5b610922868287016108a9565b909790965060209590950135949350505050565b6001600160a01b038116811461094a575f80fd5b50565b5f6020828403121561095d575f80fd5b813561096881610936565b9392505050565b5f8083601f84011261097f575f80fd5b50813567ffffffffffffffff811115610996575f80fd5b6020830191508360208260051b85010111156108e7575f80fd5b5f80602083850312156109c1575f80fd5b823567ffffffffffffffff8111156109d7575f80fd5b6109e38582860161096f565b90969095509350505050565b5f8060408385031215610a00575f80fd5b8235610a0b81610936565b946020939093013593505050565b5f805f805f60608688031215610a2d575f80fd5b853567ffffffffffffffff811115610a43575f80fd5b610a4f888289016108a9565b90965094505060208601359250604086013567ffffffffffffffff811115610a75575f80fd5b610a818882890161096f565b969995985093965092949392505050565b5f8060208385031215610aa3575f80fd5b823567ffffffffffffffff811115610ab9575f80fd5b8301601f81018513610ac9575f80fd5b803567ffffffffffffffff811115610adf575f80fd5b8560208260061b8401011115610af3575f80fd5b6020919091019590945092505050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b602080825281018290525f8360408301825b85811015610b9b578235610b6281610936565b6001600160a01b031682526020830135610b7b81610936565b6001600160a01b0316602083015260409283019290910190600101610b4f565b5095945050505050565b818382375f910190815291905056fea164736f6c634300081a000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; library FeeOnTransferDetectorDeployer { function deploy(address v2Factory) internal returns (address detector) { bytes memory args = abi.encode(v2Factory); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { detector := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/util-contracts/src/FeeOnTransferDetector.sol */ function initcode() internal pure returns (bytes memory) { return hex'60a060405234801561001057600080fd5b5060405161145938038061145983398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b6080516113c061009960003960008181610575015281816105fb0152610a0901526113c06000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806310d1e85c1461005c578063686dc35914610071578063aa3ad4e414610084578063ade44597146100ad578063da80e4dd146100cd575b600080fd5b61006f61006a366004610e46565b6100e0565b005b61006f61007f366004610edc565b6102da565b610097610092366004610edc565b6102f3565b6040516100a49190610f1d565b60405180910390f35b6100c06100bb366004610f5c565b61030e565b6040516100a49190610fe8565b61006f6100db366004611067565b6103da565b6000339050600080826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610126573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061014a91906110ad565b836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101ac91906110ad565b9150915060008088116101bf57816101c1565b825b90506000806101d2878901896110ca565b6040516370a0823160e01b8152306004820152919350915060009083906001600160a01b038616906370a0823190602401602060405180830381865afa158015610220573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024491906110ec565b61024e919061111b565b9050600061025c838361053d565b905060008061026b878561055e565b9150915060008061027e8c8a8888610785565b9150915060006040518060a00160405280878152602001848152602001861515815260200185151581526020018315158152506040516020016102c19190610f1d565b6040516020818303038152906040529050805181602001fd5b6102ee6001600160a01b0384168383610941565b505050565b6102fb610e00565b6103068484846109c8565b949350505050565b60608367ffffffffffffffff8111156103295761032961112e565b60405190808252806020026020018201604052801561036257816020015b61034f610e00565b8152602001906001900390816103475790505b50905060005b848110156103d1576103a186868381811061038557610385611144565b905060200201602081019061039a919061115a565b85856109c8565b8282815181106103b3576103b3611144565b602002602001018190525080806103c990611177565b915050610368565b50949350505050565b60405163686dc35960e01b81526001600160a01b0380861660048301528416602482015260448101839052309063686dc35990606401600060405180830381600087803b15801561042a57600080fd5b505af192505050801561043b575060015b6104ba573d808015610469576040519150601f19603f3d011682016040523d82523d6000602084013e61046e565b606091505b5060448151101561047e57600080fd5b6004810190508080602001905181019061049891906111b4565b60405162461bcd60e51b81526004016104b1919061128d565b60405180910390fd5b6040516370a0823160e01b81526001600160a01b03848116600483015260009183918716906370a0823190602401602060405180830381865afa158015610505573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052991906110ec565b6040805192909114156020830152016102c1565b600061055761271084610550858261111b565b9190610c66565b9392505050565b6040516370a0823160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260009182918291908616906370a0823190602401602060405180830381865afa1580156105cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f091906110ec565b90503063da80e4dd867f00000000000000000000000000000000000000000000000000000000000000008761062581876112a0565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015293909216602484015260448301526064820152608401600060405180830381600087803b15801561067957600080fd5b505af192505050801561068a575060015b61077d573d8080156106b8576040519150601f19603f3d011682016040523d82523d6000602084013e6106bd565b606091505b50602081511115610764576004810190506000818060200190518101906106e491906111b4565b60408051808201909152600f81526e1514905394d1915497d19052531151608a1b6020918201528151908201209091507f74070f287f0ec8bf99f019cdcc4e806934e7ec77618231bede1aa47e84c9848e01610743576001935061075e565b80604051631fa44c4b60e21b81526004016104b1919061128d565b5061077b565b8080602001905181019061077891906112c3565b93505b505b509250929050565b6040516370a0823160e01b81526001600160a01b03858116600483015260009182918291908716906370a0823190602401602060405180830381865afa1580156107d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f791906110ec565b60405163686dc35960e01b81526001600160a01b0380891660048301528916602482015260448101879052909150309063686dc35990606401600060405180830381600087803b15801561084a57600080fd5b505af192505050801561085b575060015b61089c573d808015610889576040519150601f19603f3d011682016040523d82523d6000602084013e61088e565b606091505b508493506001925050610937565b6040516370a0823160e01b81526001600160a01b03888116600483015260009183918916906370a0823190602401602060405180830381865afa1580156108e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090b91906110ec565b610915919061111b565b90506000610923828861111b565b90506109328161271089610c66565b945050505b5094509492505050565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806109c25760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016104b1565b50505050565b6109d0610e00565b826001600160a01b0316846001600160a01b031603610a025760405163100dac0560e11b815260040160405180910390fd5b6000610a2f7f00000000000000000000000000000000000000000000000000000000000000008686610c8c565b60408051600481526024810182526020810180516001600160e01b0316630dfe168160e01b17905290519192506000916001600160a01b03841691610a73916112de565b600060405180830381855afa9150503d8060008114610aae576040519150601f19603f3d011682016040523d82523d6000602084013e610ab3565b606091505b509150508051600003610ad9576040516310df924f60e31b815260040160405180910390fd5b600081806020019051810190610aef91906110ad565b9050600080826001600160a01b0316896001600160a01b031614610b1557600087610b19565b8660005b6040516370a0823160e01b815230600482015291935091506000906001600160a01b038b16906370a0823190602401602060405180830381865afa158015610b65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8991906110ec565b90506000869050806001600160a01b031663022c0d9f858530868e604051602001610bbe929190918252602082015260400190565b6040516020818303038152906040526040518563ffffffff1660e01b8152600401610bec94939291906112fa565b600060405180830381600087803b158015610c0657600080fd5b505af1925050508015610c17575060015b610c58573d808015610c45576040519150601f19603f3d011682016040523d82523d6000602084013e610c4a565b606091505b50610c5481610d65565b9850505b505050505050509392505050565b6000826000190484118302158202610c7d57600080fd5b50910281810615159190040190565b6000806000610c9b8585610d9d565b6040516bffffffffffffffffffffffff19606084811b8216602084015283901b1660348201529193509150869060480160405160208183030381529060405280519060200120604051602001610d439291906001600160f81b0319815260609290921b6bffffffffffffffffffffffff1916600183015260158201527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b610d6d610e00565b815160a014610d7e57815182602001fd5b81806020019051810190610d929190611331565b92915050565b919050565b600080826001600160a01b0316846001600160a01b031603610dbe57600080fd5b826001600160a01b0316846001600160a01b031610610dde578284610de1565b83835b90925090506001600160a01b038216610df957600080fd5b9250929050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b6001600160a01b0381168114610e4357600080fd5b50565b600080600080600060808688031215610e5e57600080fd5b8535610e6981610e2e565b94506020860135935060408601359250606086013567ffffffffffffffff80821115610e9457600080fd5b818801915088601f830112610ea857600080fd5b813581811115610eb757600080fd5b896020828501011115610ec957600080fd5b9699959850939650602001949392505050565b600080600060608486031215610ef157600080fd5b8335610efc81610e2e565b92506020840135610f0c81610e2e565b929592945050506040919091013590565b60a08101610d92828480518252602081015160208301526040810151151560408301526060810151151560608301526080810151151560808301525050565b60008060008060608587031215610f7257600080fd5b843567ffffffffffffffff80821115610f8a57600080fd5b818701915087601f830112610f9e57600080fd5b813581811115610fad57600080fd5b8860208260051b8501011115610fc257600080fd5b60209283019650945050850135610fd881610e2e565b9396929550929360400135925050565b6020808252825182820181905260009190848201906040850190845b8181101561105b5761104883855180518252602081015160208301526040810151151560408301526060810151151560608301526080810151151560808301525050565b9284019260a09290920191600101611004565b50909695505050505050565b6000806000806080858703121561107d57600080fd5b843561108881610e2e565b9350602085013561109881610e2e565b93969395505050506040820135916060013590565b6000602082840312156110bf57600080fd5b815161055781610e2e565b600080604083850312156110dd57600080fd5b50508035926020909101359150565b6000602082840312156110fe57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610d9257610d92611105565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121561116c57600080fd5b813561055781610e2e565b60006001820161118957611189611105565b5060010190565b60005b838110156111ab578181015183820152602001611193565b50506000910152565b6000602082840312156111c657600080fd5b815167ffffffffffffffff808211156111de57600080fd5b818401915084601f8301126111f257600080fd5b8151818111156112045761120461112e565b604051601f8201601f19908116603f0116810190838211818310171561122c5761122c61112e565b8160405282815287602084870101111561124557600080fd5b611256836020830160208801611190565b979650505050505050565b60008151808452611279816020860160208601611190565b601f01601f19169290920160200192915050565b6020815260006105576020830184611261565b80820180821115610d9257610d92611105565b80518015158114610d9857600080fd5b6000602082840312156112d557600080fd5b610557826112b3565b600082516112f0818460208701611190565b9190910192915050565b84815283602082015260018060a01b03831660408201526080606082015260006113276080830184611261565b9695505050505050565b600060a0828403121561134357600080fd5b60405160a0810181811067ffffffffffffffff821117156113665761136661112e565b80604052508251815260208301516020820152611385604084016112b3565b6040820152611396606084016112b3565b60608201526113a7608084016112b3565b6080820152939250505056fea164736f6c6343000813000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.5.0; import {IUniswapV2Factory} from '../../protocols/v2-core/interfaces/IUniswapV2Factory.sol'; library UniswapV2FactoryDeployer { function deploy(address feeToSetter) internal returns (IUniswapV2Factory factory) { bytes memory args = abi.encode(feeToSetter); bytes memory initcode_ = abi.encodePacked(legacyInitcode(), args); assembly { factory := create(0, add(initcode_, 32), mload(initcode_)) } } /// @dev this is the init code of the previously deployed v2 factory instances with a different metadata hash. Using this version ensures the correct pool init code hash function legacyInitcode() internal pure returns (bytes memory) { return hex'608060405234801561001057600080fd5b506040516136863803806136868339818101604052602081101561003357600080fd5b5051600180546001600160a01b0319166001600160a01b03909216919091179055613623806100636000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063a2e74af61161005b578063a2e74af6146100fd578063c9c6539614610132578063e6a439051461016d578063f46901ed146101a857610088565b8063017e7e581461008d578063094b7415146100be5780631e3dd18b146100c6578063574f2ba3146100e3575b600080fd5b6100956101db565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100956101f7565b610095600480360360208110156100dc57600080fd5b5035610213565b6100eb610247565b60408051918252519081900360200190f35b6101306004803603602081101561011357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661024d565b005b6100956004803603604081101561014857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602001351661031a565b6100956004803603604081101561018357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602001351661076d565b610130600480360360208110156101be57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166107a0565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b6003818154811061022057fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60035490565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102d357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e697377617056323a20464f5242494444454e000000000000000000000000604482015290519081900360640190fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156103b757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f556e697377617056323a204944454e544943414c5f4144445245535345530000604482015290519081900360640190fd5b6000808373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16106103f45783856103f7565b84845b909250905073ffffffffffffffffffffffffffffffffffffffff821661047e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f556e697377617056323a205a45524f5f41444452455353000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff82811660009081526002602090815260408083208585168452909152902054161561051f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f556e697377617056323a20504149525f45584953545300000000000000000000604482015290519081900360640190fd5b6060604051806020016105319061086d565b6020820181038252601f19601f82011660405250905060008383604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140192505050604051602081830303815290604052805190602001209050808251602084016000f5604080517f485cc95500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152868116602483015291519297509087169163485cc9559160448082019260009290919082900301818387803b15801561065e57600080fd5b505af1158015610672573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff84811660008181526002602081815260408084208987168086529083528185208054978d167fffffffffffffffffffffffff000000000000000000000000000000000000000098891681179091559383528185208686528352818520805488168517905560038054600181018255958190527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b90950180549097168417909655925483519283529082015281517f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9929181900390910190a35050505092915050565b600260209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16331461082657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e697377617056323a20464f5242494444454e000000000000000000000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b612d748061087b8339019056fe60806040526001600c5534801561001557600080fd5b506040514690806052612d228239604080519182900360520182208282018252600a8352692ab734b9bbb0b8102b1960b11b6020938401528151808301835260018152603160f81b908401528151808401919091527fbfcc8ef98ffbf7b6c3fec7bf5185b566b9863e35a9d83acd49ad6824b5969738818301527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606082015260808101949094523060a0808601919091528151808603909101815260c09094019052825192019190912060035550600580546001600160a01b03191633179055612c1d806101056000396000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c80636a627842116100f9578063ba9a7a5611610097578063d21220a711610071578063d21220a7146105da578063d505accf146105e2578063dd62ed3e14610640578063fff6cae91461067b576101b9565b8063ba9a7a5614610597578063bc25cf771461059f578063c45a0155146105d2576101b9565b80637ecebe00116100d35780637ecebe00146104d757806389afcb441461050a57806395d89b4114610556578063a9059cbb1461055e576101b9565b80636a6278421461046957806370a082311461049c5780637464fc3d146104cf576101b9565b806323b872dd116101665780633644e515116101405780633644e51514610416578063485cc9551461041e5780635909c0d5146104595780635a3d549314610461576101b9565b806323b872dd146103ad57806330adf81f146103f0578063313ce567146103f8576101b9565b8063095ea7b311610197578063095ea7b3146103155780630dfe16811461036257806318160ddd14610393576101b9565b8063022c0d9f146101be57806306fdde03146102595780630902f1ac146102d6575b600080fd5b610257600480360360808110156101d457600080fd5b81359160208101359173ffffffffffffffffffffffffffffffffffffffff604083013516919081019060808101606082013564010000000081111561021857600080fd5b82018360208201111561022a57600080fd5b8035906020019184600183028401116401000000008311171561024c57600080fd5b509092509050610683565b005b610261610d57565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561029b578181015183820152602001610283565b50505050905090810190601f1680156102c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102de610d90565b604080516dffffffffffffffffffffffffffff948516815292909316602083015263ffffffff168183015290519081900360600190f35b61034e6004803603604081101561032b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610de5565b604080519115158252519081900360200190f35b61036a610dfc565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61039b610e18565b60408051918252519081900360200190f35b61034e600480360360608110156103c357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610e1e565b61039b610efd565b610400610f21565b6040805160ff9092168252519081900360200190f35b61039b610f26565b6102576004803603604081101561043457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516610f2c565b61039b611005565b61039b61100b565b61039b6004803603602081101561047f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611011565b61039b600480360360208110156104b257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166113cb565b61039b6113dd565b61039b600480360360208110156104ed57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166113e3565b61053d6004803603602081101561052057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166113f5565b6040805192835260208301919091528051918290030190f35b610261611892565b61034e6004803603604081101561057457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356118cb565b61039b6118d8565b610257600480360360208110156105b557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166118de565b61036a611ad4565b61036a611af0565b610257600480360360e08110156105f857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135611b0c565b61039b6004803603604081101561065657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611dd8565b610257611df5565b600c546001146106f457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c55841515806107075750600084115b61075c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180612b2f6025913960400191505060405180910390fd5b600080610767610d90565b5091509150816dffffffffffffffffffffffffffff168710801561079a5750806dffffffffffffffffffffffffffff1686105b6107ef576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180612b786021913960400191505060405180910390fd5b600654600754600091829173ffffffffffffffffffffffffffffffffffffffff91821691908116908916821480159061085457508073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b6108bf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f556e697377617056323a20494e56414c49445f544f0000000000000000000000604482015290519081900360640190fd5b8a156108d0576108d0828a8d611fdb565b89156108e1576108e1818a8c611fdb565b86156109c3578873ffffffffffffffffffffffffffffffffffffffff166310d1e85c338d8d8c8c6040518663ffffffff1660e01b8152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b1580156109aa57600080fd5b505af11580156109be573d6000803e3d6000fd5b505050505b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b158015610a2f57600080fd5b505afa158015610a43573d6000803e3d6000fd5b505050506040513d6020811015610a5957600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905191955073ffffffffffffffffffffffffffffffffffffffff8316916370a0823191602480820192602092909190829003018186803b158015610acb57600080fd5b505afa158015610adf573d6000803e3d6000fd5b505050506040513d6020811015610af557600080fd5b5051925060009150506dffffffffffffffffffffffffffff85168a90038311610b1f576000610b35565b89856dffffffffffffffffffffffffffff160383035b9050600089856dffffffffffffffffffffffffffff16038311610b59576000610b6f565b89856dffffffffffffffffffffffffffff160383035b90506000821180610b805750600081115b610bd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180612b546024913960400191505060405180910390fd5b6000610c09610beb84600363ffffffff6121e816565b610bfd876103e863ffffffff6121e816565b9063ffffffff61226e16565b90506000610c21610beb84600363ffffffff6121e816565b9050610c59620f4240610c4d6dffffffffffffffffffffffffffff8b8116908b1663ffffffff6121e816565b9063ffffffff6121e816565b610c69838363ffffffff6121e816565b1015610cd657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f556e697377617056323a204b0000000000000000000000000000000000000000604482015290519081900360640190fd5b5050610ce4848488886122e0565b60408051838152602081018390528082018d9052606081018c9052905173ffffffffffffffffffffffffffffffffffffffff8b169133917fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229181900360800190a350506001600c55505050505050505050565b6040518060400160405280600a81526020017f556e69737761702056320000000000000000000000000000000000000000000081525081565b6008546dffffffffffffffffffffffffffff808216926e0100000000000000000000000000008304909116917c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690565b6000610df233848461259c565b5060015b92915050565b60065473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b73ffffffffffffffffffffffffffffffffffffffff831660009081526002602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14610ee85773ffffffffffffffffffffffffffffffffffffffff84166000908152600260209081526040808320338452909152902054610eb6908363ffffffff61226e16565b73ffffffffffffffffffffffffffffffffffffffff851660009081526002602090815260408083203384529091529020555b610ef384848461260b565b5060019392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b601281565b60035481565b60055473ffffffffffffffffffffffffffffffffffffffff163314610fb257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e697377617056323a20464f5242494444454e000000000000000000000000604482015290519081900360640190fd5b6006805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560078054929093169116179055565b60095481565b600a5481565b6000600c5460011461108457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c81905580611094610d90565b50600654604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905193955091935060009273ffffffffffffffffffffffffffffffffffffffff909116916370a08231916024808301926020929190829003018186803b15801561110e57600080fd5b505afa158015611122573d6000803e3d6000fd5b505050506040513d602081101561113857600080fd5b5051600754604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905192935060009273ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b1580156111b157600080fd5b505afa1580156111c5573d6000803e3d6000fd5b505050506040513d60208110156111db57600080fd5b505190506000611201836dffffffffffffffffffffffffffff871663ffffffff61226e16565b90506000611225836dffffffffffffffffffffffffffff871663ffffffff61226e16565b9050600061123387876126ec565b600054909150806112705761125c6103e8610bfd611257878763ffffffff6121e816565b612878565b985061126b60006103e86128ca565b6112cd565b6112ca6dffffffffffffffffffffffffffff8916611294868463ffffffff6121e816565b8161129b57fe5b046dffffffffffffffffffffffffffff89166112bd868563ffffffff6121e816565b816112c457fe5b0461297a565b98505b60008911611326576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180612bc16028913960400191505060405180910390fd5b6113308a8a6128ca565b61133c86868a8a6122e0565b811561137e5760085461137a906dffffffffffffffffffffffffffff808216916e01000000000000000000000000000090041663ffffffff6121e816565b600b555b6040805185815260208101859052815133927f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f928290030190a250506001600c5550949695505050505050565b60016020526000908152604090205481565b600b5481565b60046020526000908152604090205481565b600080600c5460011461146957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c81905580611479610d90565b50600654600754604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905194965092945073ffffffffffffffffffffffffffffffffffffffff9182169391169160009184916370a08231916024808301926020929190829003018186803b1580156114fb57600080fd5b505afa15801561150f573d6000803e3d6000fd5b505050506040513d602081101561152557600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905191925060009173ffffffffffffffffffffffffffffffffffffffff8516916370a08231916024808301926020929190829003018186803b15801561159957600080fd5b505afa1580156115ad573d6000803e3d6000fd5b505050506040513d60208110156115c357600080fd5b5051306000908152600160205260408120549192506115e288886126ec565b600054909150806115f9848763ffffffff6121e816565b8161160057fe5b049a5080611614848663ffffffff6121e816565b8161161b57fe5b04995060008b11801561162e575060008a115b611683576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180612b996028913960400191505060405180910390fd5b61168d3084612992565b611698878d8d611fdb565b6116a3868d8c611fdb565b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8916916370a08231916024808301926020929190829003018186803b15801561170f57600080fd5b505afa158015611723573d6000803e3d6000fd5b505050506040513d602081101561173957600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905191965073ffffffffffffffffffffffffffffffffffffffff8816916370a0823191602480820192602092909190829003018186803b1580156117ab57600080fd5b505afa1580156117bf573d6000803e3d6000fd5b505050506040513d60208110156117d557600080fd5b505193506117e585858b8b6122e0565b811561182757600854611823906dffffffffffffffffffffffffffff808216916e01000000000000000000000000000090041663ffffffff6121e816565b600b555b604080518c8152602081018c9052815173ffffffffffffffffffffffffffffffffffffffff8f169233927fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496929081900390910190a35050505050505050506001600c81905550915091565b6040518060400160405280600681526020017f554e492d5632000000000000000000000000000000000000000000000000000081525081565b6000610df233848461260b565b6103e881565b600c5460011461194f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c55600654600754600854604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff9485169490931692611a2b9285928792611a26926dffffffffffffffffffffffffffff169185916370a0823191602480820192602092909190829003018186803b1580156119ee57600080fd5b505afa158015611a02573d6000803e3d6000fd5b505050506040513d6020811015611a1857600080fd5b50519063ffffffff61226e16565b611fdb565b600854604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051611aca9284928792611a26926e01000000000000000000000000000090046dffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff8616916370a0823191602480820192602092909190829003018186803b1580156119ee57600080fd5b50506001600c5550565b60055473ffffffffffffffffffffffffffffffffffffffff1681565b60075473ffffffffffffffffffffffffffffffffffffffff1681565b42841015611b7b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f556e697377617056323a20455850495245440000000000000000000000000000604482015290519081900360640190fd5b60035473ffffffffffffffffffffffffffffffffffffffff80891660008181526004602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958d166060860152608085018c905260a085019590955260c08085018b90528151808603909101815260e0850182528051908301207f19010000000000000000000000000000000000000000000000000000000000006101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff89166101828501526101a284018890526101c28401879052519193926101e2808201937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015611cdc573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590611d5757508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611dc257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f556e697377617056323a20494e56414c49445f5349474e415455524500000000604482015290519081900360640190fd5b611dcd89898961259c565b505050505050505050565b600260209081526000928352604080842090915290825290205481565b600c54600114611e6657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c55600654604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051611fd49273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b158015611edd57600080fd5b505afa158015611ef1573d6000803e3d6000fd5b505050506040513d6020811015611f0757600080fd5b5051600754604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b158015611f7a57600080fd5b505afa158015611f8e573d6000803e3d6000fd5b505050506040513d6020811015611fa457600080fd5b50516008546dffffffffffffffffffffffffffff808216916e0100000000000000000000000000009004166122e0565b6001600c55565b604080518082018252601981527f7472616e7366657228616464726573732c75696e743235362900000000000000602091820152815173ffffffffffffffffffffffffffffffffffffffff85811660248301526044808301869052845180840390910181526064909201845291810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781529251815160009460609489169392918291908083835b602083106120e157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016120a4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612143576040519150601f19603f3d011682016040523d82523d6000602084013e612148565b606091505b5091509150818015612176575080511580612176575080806020019051602081101561217357600080fd5b50515b6121e157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f556e697377617056323a205452414e534645525f4641494c4544000000000000604482015290519081900360640190fd5b5050505050565b60008115806122035750508082028282828161220057fe5b04145b610df657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b80820382811115610df657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b6dffffffffffffffffffffffffffff841180159061230c57506dffffffffffffffffffffffffffff8311155b61237757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f556e697377617056323a204f564552464c4f5700000000000000000000000000604482015290519081900360640190fd5b60085463ffffffff428116917c0100000000000000000000000000000000000000000000000000000000900481168203908116158015906123c757506dffffffffffffffffffffffffffff841615155b80156123e257506dffffffffffffffffffffffffffff831615155b15612492578063ffffffff16612425856123fb86612a57565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169063ffffffff612a7b16565b600980547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092169290920201905563ffffffff8116612465846123fb87612a57565b600a80547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216929092020190555b600880547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff888116919091177fffffffff0000000000000000000000000000ffffffffffffffffffffffffffff166e0100000000000000000000000000008883168102919091177bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff871602179283905560408051848416815291909304909116602082015281517f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1929181900390910190a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040902054612641908263ffffffff61226e16565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160205260408082209390935590841681522054612683908263ffffffff612abc16565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600080600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b15801561275757600080fd5b505afa15801561276b573d6000803e3d6000fd5b505050506040513d602081101561278157600080fd5b5051600b5473ffffffffffffffffffffffffffffffffffffffff821615801594509192509061286457801561285f5760006127d86112576dffffffffffffffffffffffffffff88811690881663ffffffff6121e816565b905060006127e583612878565b90508082111561285c576000612813612804848463ffffffff61226e16565b6000549063ffffffff6121e816565b905060006128388361282c86600563ffffffff6121e816565b9063ffffffff612abc16565b9050600081838161284557fe5b04905080156128585761285887826128ca565b5050505b50505b612870565b8015612870576000600b555b505092915050565b600060038211156128bb575080600160028204015b818110156128b5578091506002818285816128a457fe5b0401816128ad57fe5b04905061288d565b506128c5565b81156128c5575060015b919050565b6000546128dd908263ffffffff612abc16565b600090815573ffffffffffffffffffffffffffffffffffffffff8316815260016020526040902054612915908263ffffffff612abc16565b73ffffffffffffffffffffffffffffffffffffffff831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000818310612989578161298b565b825b9392505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160205260409020546129c8908263ffffffff61226e16565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081209190915554612a02908263ffffffff61226e16565b600090815560408051838152905173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef919081900360200190a35050565b6dffffffffffffffffffffffffffff166e0100000000000000000000000000000290565b60006dffffffffffffffffffffffffffff82167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841681612ab457fe5b049392505050565b80820182811015610df657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fdfe556e697377617056323a20494e53554646494349454e545f4f55545055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f494e5055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f4c4951554944495459556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4255524e4544556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4d494e544544a265627a7a723158207dca18479e58487606bf70c79e44d8dee62353c9ee6d01f9a9d70885b8765f2264736f6c63430005100032454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429a265627a7a723158202760f92d7fa1db6f5aa16307bad65df4ebcc8550c4b1f03755ab8dfd830c178f64736f6c63430005100032'; } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v2-core/contracts/UniswapV2Factory.sol */ function initcode() internal pure returns (bytes memory) { return hex'608060405234801561001057600080fd5b506040516136863803806136868339818101604052602081101561003357600080fd5b5051600180546001600160a01b0319166001600160a01b03909216919091179055613623806100636000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063a2e74af61161005b578063a2e74af6146100fd578063c9c6539614610132578063e6a439051461016d578063f46901ed146101a857610088565b8063017e7e581461008d578063094b7415146100be5780631e3dd18b146100c6578063574f2ba3146100e3575b600080fd5b6100956101db565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6100956101f7565b610095600480360360208110156100dc57600080fd5b5035610213565b6100eb610247565b60408051918252519081900360200190f35b6101306004803603602081101561011357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661024d565b005b6100956004803603604081101561014857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602001351661031a565b6100956004803603604081101561018357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602001351661076d565b610130600480360360208110156101be57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166107a0565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b6003818154811061022057fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60035490565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102d357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e697377617056323a20464f5242494444454e000000000000000000000000604482015290519081900360640190fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156103b757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f556e697377617056323a204944454e544943414c5f4144445245535345530000604482015290519081900360640190fd5b6000808373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16106103f45783856103f7565b84845b909250905073ffffffffffffffffffffffffffffffffffffffff821661047e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f556e697377617056323a205a45524f5f41444452455353000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff82811660009081526002602090815260408083208585168452909152902054161561051f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f556e697377617056323a20504149525f45584953545300000000000000000000604482015290519081900360640190fd5b6060604051806020016105319061086d565b6020820181038252601f19601f82011660405250905060008383604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140192505050604051602081830303815290604052805190602001209050808251602084016000f5604080517f485cc95500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152868116602483015291519297509087169163485cc9559160448082019260009290919082900301818387803b15801561065e57600080fd5b505af1158015610672573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff84811660008181526002602081815260408084208987168086529083528185208054978d167fffffffffffffffffffffffff000000000000000000000000000000000000000098891681179091559383528185208686528352818520805488168517905560038054600181018255958190527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b90950180549097168417909655925483519283529082015281517f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9929181900390910190a35050505092915050565b600260209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16331461082657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e697377617056323a20464f5242494444454e000000000000000000000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b612d748061087b8339019056fe60806040526001600c5534801561001557600080fd5b506040514690806052612d228239604080519182900360520182208282018252600a8352692ab734b9bbb0b8102b1960b11b6020938401528151808301835260018152603160f81b908401528151808401919091527fbfcc8ef98ffbf7b6c3fec7bf5185b566b9863e35a9d83acd49ad6824b5969738818301527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606082015260808101949094523060a0808601919091528151808603909101815260c09094019052825192019190912060035550600580546001600160a01b03191633179055612c1d806101056000396000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c80636a627842116100f9578063ba9a7a5611610097578063d21220a711610071578063d21220a7146105da578063d505accf146105e2578063dd62ed3e14610640578063fff6cae91461067b576101b9565b8063ba9a7a5614610597578063bc25cf771461059f578063c45a0155146105d2576101b9565b80637ecebe00116100d35780637ecebe00146104d757806389afcb441461050a57806395d89b4114610556578063a9059cbb1461055e576101b9565b80636a6278421461046957806370a082311461049c5780637464fc3d146104cf576101b9565b806323b872dd116101665780633644e515116101405780633644e51514610416578063485cc9551461041e5780635909c0d5146104595780635a3d549314610461576101b9565b806323b872dd146103ad57806330adf81f146103f0578063313ce567146103f8576101b9565b8063095ea7b311610197578063095ea7b3146103155780630dfe16811461036257806318160ddd14610393576101b9565b8063022c0d9f146101be57806306fdde03146102595780630902f1ac146102d6575b600080fd5b610257600480360360808110156101d457600080fd5b81359160208101359173ffffffffffffffffffffffffffffffffffffffff604083013516919081019060808101606082013564010000000081111561021857600080fd5b82018360208201111561022a57600080fd5b8035906020019184600183028401116401000000008311171561024c57600080fd5b509092509050610683565b005b610261610d57565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561029b578181015183820152602001610283565b50505050905090810190601f1680156102c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102de610d90565b604080516dffffffffffffffffffffffffffff948516815292909316602083015263ffffffff168183015290519081900360600190f35b61034e6004803603604081101561032b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610de5565b604080519115158252519081900360200190f35b61036a610dfc565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61039b610e18565b60408051918252519081900360200190f35b61034e600480360360608110156103c357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610e1e565b61039b610efd565b610400610f21565b6040805160ff9092168252519081900360200190f35b61039b610f26565b6102576004803603604081101561043457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516610f2c565b61039b611005565b61039b61100b565b61039b6004803603602081101561047f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611011565b61039b600480360360208110156104b257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166113cb565b61039b6113dd565b61039b600480360360208110156104ed57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166113e3565b61053d6004803603602081101561052057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166113f5565b6040805192835260208301919091528051918290030190f35b610261611892565b61034e6004803603604081101561057457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356118cb565b61039b6118d8565b610257600480360360208110156105b557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166118de565b61036a611ad4565b61036a611af0565b610257600480360360e08110156105f857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135611b0c565b61039b6004803603604081101561065657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516611dd8565b610257611df5565b600c546001146106f457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c55841515806107075750600084115b61075c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180612b2f6025913960400191505060405180910390fd5b600080610767610d90565b5091509150816dffffffffffffffffffffffffffff168710801561079a5750806dffffffffffffffffffffffffffff1686105b6107ef576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180612b786021913960400191505060405180910390fd5b600654600754600091829173ffffffffffffffffffffffffffffffffffffffff91821691908116908916821480159061085457508073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b6108bf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f556e697377617056323a20494e56414c49445f544f0000000000000000000000604482015290519081900360640190fd5b8a156108d0576108d0828a8d611fdb565b89156108e1576108e1818a8c611fdb565b86156109c3578873ffffffffffffffffffffffffffffffffffffffff166310d1e85c338d8d8c8c6040518663ffffffff1660e01b8152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b1580156109aa57600080fd5b505af11580156109be573d6000803e3d6000fd5b505050505b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b158015610a2f57600080fd5b505afa158015610a43573d6000803e3d6000fd5b505050506040513d6020811015610a5957600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905191955073ffffffffffffffffffffffffffffffffffffffff8316916370a0823191602480820192602092909190829003018186803b158015610acb57600080fd5b505afa158015610adf573d6000803e3d6000fd5b505050506040513d6020811015610af557600080fd5b5051925060009150506dffffffffffffffffffffffffffff85168a90038311610b1f576000610b35565b89856dffffffffffffffffffffffffffff160383035b9050600089856dffffffffffffffffffffffffffff16038311610b59576000610b6f565b89856dffffffffffffffffffffffffffff160383035b90506000821180610b805750600081115b610bd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180612b546024913960400191505060405180910390fd5b6000610c09610beb84600363ffffffff6121e816565b610bfd876103e863ffffffff6121e816565b9063ffffffff61226e16565b90506000610c21610beb84600363ffffffff6121e816565b9050610c59620f4240610c4d6dffffffffffffffffffffffffffff8b8116908b1663ffffffff6121e816565b9063ffffffff6121e816565b610c69838363ffffffff6121e816565b1015610cd657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f556e697377617056323a204b0000000000000000000000000000000000000000604482015290519081900360640190fd5b5050610ce4848488886122e0565b60408051838152602081018390528082018d9052606081018c9052905173ffffffffffffffffffffffffffffffffffffffff8b169133917fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229181900360800190a350506001600c55505050505050505050565b6040518060400160405280600a81526020017f556e69737761702056320000000000000000000000000000000000000000000081525081565b6008546dffffffffffffffffffffffffffff808216926e0100000000000000000000000000008304909116917c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690565b6000610df233848461259c565b5060015b92915050565b60065473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b73ffffffffffffffffffffffffffffffffffffffff831660009081526002602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14610ee85773ffffffffffffffffffffffffffffffffffffffff84166000908152600260209081526040808320338452909152902054610eb6908363ffffffff61226e16565b73ffffffffffffffffffffffffffffffffffffffff851660009081526002602090815260408083203384529091529020555b610ef384848461260b565b5060019392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b601281565b60035481565b60055473ffffffffffffffffffffffffffffffffffffffff163314610fb257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e697377617056323a20464f5242494444454e000000000000000000000000604482015290519081900360640190fd5b6006805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560078054929093169116179055565b60095481565b600a5481565b6000600c5460011461108457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c81905580611094610d90565b50600654604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905193955091935060009273ffffffffffffffffffffffffffffffffffffffff909116916370a08231916024808301926020929190829003018186803b15801561110e57600080fd5b505afa158015611122573d6000803e3d6000fd5b505050506040513d602081101561113857600080fd5b5051600754604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905192935060009273ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b1580156111b157600080fd5b505afa1580156111c5573d6000803e3d6000fd5b505050506040513d60208110156111db57600080fd5b505190506000611201836dffffffffffffffffffffffffffff871663ffffffff61226e16565b90506000611225836dffffffffffffffffffffffffffff871663ffffffff61226e16565b9050600061123387876126ec565b600054909150806112705761125c6103e8610bfd611257878763ffffffff6121e816565b612878565b985061126b60006103e86128ca565b6112cd565b6112ca6dffffffffffffffffffffffffffff8916611294868463ffffffff6121e816565b8161129b57fe5b046dffffffffffffffffffffffffffff89166112bd868563ffffffff6121e816565b816112c457fe5b0461297a565b98505b60008911611326576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180612bc16028913960400191505060405180910390fd5b6113308a8a6128ca565b61133c86868a8a6122e0565b811561137e5760085461137a906dffffffffffffffffffffffffffff808216916e01000000000000000000000000000090041663ffffffff6121e816565b600b555b6040805185815260208101859052815133927f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f928290030190a250506001600c5550949695505050505050565b60016020526000908152604090205481565b600b5481565b60046020526000908152604090205481565b600080600c5460011461146957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c81905580611479610d90565b50600654600754604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905194965092945073ffffffffffffffffffffffffffffffffffffffff9182169391169160009184916370a08231916024808301926020929190829003018186803b1580156114fb57600080fd5b505afa15801561150f573d6000803e3d6000fd5b505050506040513d602081101561152557600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905191925060009173ffffffffffffffffffffffffffffffffffffffff8516916370a08231916024808301926020929190829003018186803b15801561159957600080fd5b505afa1580156115ad573d6000803e3d6000fd5b505050506040513d60208110156115c357600080fd5b5051306000908152600160205260408120549192506115e288886126ec565b600054909150806115f9848763ffffffff6121e816565b8161160057fe5b049a5080611614848663ffffffff6121e816565b8161161b57fe5b04995060008b11801561162e575060008a115b611683576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180612b996028913960400191505060405180910390fd5b61168d3084612992565b611698878d8d611fdb565b6116a3868d8c611fdb565b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8916916370a08231916024808301926020929190829003018186803b15801561170f57600080fd5b505afa158015611723573d6000803e3d6000fd5b505050506040513d602081101561173957600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905191965073ffffffffffffffffffffffffffffffffffffffff8816916370a0823191602480820192602092909190829003018186803b1580156117ab57600080fd5b505afa1580156117bf573d6000803e3d6000fd5b505050506040513d60208110156117d557600080fd5b505193506117e585858b8b6122e0565b811561182757600854611823906dffffffffffffffffffffffffffff808216916e01000000000000000000000000000090041663ffffffff6121e816565b600b555b604080518c8152602081018c9052815173ffffffffffffffffffffffffffffffffffffffff8f169233927fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496929081900390910190a35050505050505050506001600c81905550915091565b6040518060400160405280600681526020017f554e492d5632000000000000000000000000000000000000000000000000000081525081565b6000610df233848461260b565b6103e881565b600c5460011461194f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c55600654600754600854604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff9485169490931692611a2b9285928792611a26926dffffffffffffffffffffffffffff169185916370a0823191602480820192602092909190829003018186803b1580156119ee57600080fd5b505afa158015611a02573d6000803e3d6000fd5b505050506040513d6020811015611a1857600080fd5b50519063ffffffff61226e16565b611fdb565b600854604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051611aca9284928792611a26926e01000000000000000000000000000090046dffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff8616916370a0823191602480820192602092909190829003018186803b1580156119ee57600080fd5b50506001600c5550565b60055473ffffffffffffffffffffffffffffffffffffffff1681565b60075473ffffffffffffffffffffffffffffffffffffffff1681565b42841015611b7b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f556e697377617056323a20455850495245440000000000000000000000000000604482015290519081900360640190fd5b60035473ffffffffffffffffffffffffffffffffffffffff80891660008181526004602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958d166060860152608085018c905260a085019590955260c08085018b90528151808603909101815260e0850182528051908301207f19010000000000000000000000000000000000000000000000000000000000006101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff89166101828501526101a284018890526101c28401879052519193926101e2808201937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015611cdc573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590611d5757508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611dc257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f556e697377617056323a20494e56414c49445f5349474e415455524500000000604482015290519081900360640190fd5b611dcd89898961259c565b505050505050505050565b600260209081526000928352604080842090915290825290205481565b600c54600114611e6657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f556e697377617056323a204c4f434b4544000000000000000000000000000000604482015290519081900360640190fd5b6000600c55600654604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051611fd49273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b158015611edd57600080fd5b505afa158015611ef1573d6000803e3d6000fd5b505050506040513d6020811015611f0757600080fd5b5051600754604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b158015611f7a57600080fd5b505afa158015611f8e573d6000803e3d6000fd5b505050506040513d6020811015611fa457600080fd5b50516008546dffffffffffffffffffffffffffff808216916e0100000000000000000000000000009004166122e0565b6001600c55565b604080518082018252601981527f7472616e7366657228616464726573732c75696e743235362900000000000000602091820152815173ffffffffffffffffffffffffffffffffffffffff85811660248301526044808301869052845180840390910181526064909201845291810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781529251815160009460609489169392918291908083835b602083106120e157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016120a4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612143576040519150601f19603f3d011682016040523d82523d6000602084013e612148565b606091505b5091509150818015612176575080511580612176575080806020019051602081101561217357600080fd5b50515b6121e157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f556e697377617056323a205452414e534645525f4641494c4544000000000000604482015290519081900360640190fd5b5050505050565b60008115806122035750508082028282828161220057fe5b04145b610df657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b80820382811115610df657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b6dffffffffffffffffffffffffffff841180159061230c57506dffffffffffffffffffffffffffff8311155b61237757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f556e697377617056323a204f564552464c4f5700000000000000000000000000604482015290519081900360640190fd5b60085463ffffffff428116917c0100000000000000000000000000000000000000000000000000000000900481168203908116158015906123c757506dffffffffffffffffffffffffffff841615155b80156123e257506dffffffffffffffffffffffffffff831615155b15612492578063ffffffff16612425856123fb86612a57565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169063ffffffff612a7b16565b600980547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092169290920201905563ffffffff8116612465846123fb87612a57565b600a80547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216929092020190555b600880547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff888116919091177fffffffff0000000000000000000000000000ffffffffffffffffffffffffffff166e0100000000000000000000000000008883168102919091177bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff871602179283905560408051848416815291909304909116602082015281517f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1929181900390910190a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040902054612641908263ffffffff61226e16565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160205260408082209390935590841681522054612683908263ffffffff612abc16565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600080600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b15801561275757600080fd5b505afa15801561276b573d6000803e3d6000fd5b505050506040513d602081101561278157600080fd5b5051600b5473ffffffffffffffffffffffffffffffffffffffff821615801594509192509061286457801561285f5760006127d86112576dffffffffffffffffffffffffffff88811690881663ffffffff6121e816565b905060006127e583612878565b90508082111561285c576000612813612804848463ffffffff61226e16565b6000549063ffffffff6121e816565b905060006128388361282c86600563ffffffff6121e816565b9063ffffffff612abc16565b9050600081838161284557fe5b04905080156128585761285887826128ca565b5050505b50505b612870565b8015612870576000600b555b505092915050565b600060038211156128bb575080600160028204015b818110156128b5578091506002818285816128a457fe5b0401816128ad57fe5b04905061288d565b506128c5565b81156128c5575060015b919050565b6000546128dd908263ffffffff612abc16565b600090815573ffffffffffffffffffffffffffffffffffffffff8316815260016020526040902054612915908263ffffffff612abc16565b73ffffffffffffffffffffffffffffffffffffffff831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000818310612989578161298b565b825b9392505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160205260409020546129c8908263ffffffff61226e16565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081209190915554612a02908263ffffffff61226e16565b600090815560408051838152905173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef919081900360200190a35050565b6dffffffffffffffffffffffffffff166e0100000000000000000000000000000290565b60006dffffffffffffffffffffffffffff82167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841681612ab457fe5b049392505050565b80820182811015610df657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fdfe556e697377617056323a20494e53554646494349454e545f4f55545055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f494e5055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f4c4951554944495459556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4255524e4544556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4d494e544544a265627a7a7231582014afc6061e778c649f750cf01e0fe3399deffd7f0b8aeef40111f4f362a5d10464736f6c63430005100032454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429a265627a7a723158203eff2123f12b1f383a35c2fede7d9544214632a39201f71dc12f715d582c9dc864736f6c63430005100032'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.5.0; import {IUniswapV2Router02} from '../../protocols/v2-periphery/interfaces/IUniswapV2Router02.sol'; library UniswapV2Router02Deployer { function deploy(address factory, address weth) internal returns (IUniswapV2Router02 router02) { bytes memory args = abi.encode(factory, weth); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { router02 := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v2-periphery/contracts/UniswapV2Router02.sol */ function initcode() internal pure returns (bytes memory) { return hex'60c06040523480156200001157600080fd5b506040516200571538038062005715833981810160405260408110156200003757600080fd5b5080516020909101516001600160601b0319606092831b8116608052911b1660a05260805160601c60a05160601c61558e62000187600039806101ac5280610e5d5280610e985280610fd5528061129852806116f252806118d65280611e1e5280611fa252806120725280612179528061232c52806123c15280612673528061271a52806127ef52806128f452806129dc5280612a5d52806130ec5280613422528061347852806134ac528061352d528061374752806138f7528061398c5250806110c752806111c5528061136b52806113a4528061154f52806117e452806118b45280611aa1528061225f528061240052806125a95280612a9c5280612ddf5280613071528061309a52806130ca52806132a75280613456528061382d52806139cb528061444a528061448d52806147ed52806149ce5280614f49528061502a52806150aa525061558e6000f3fe60806040526004361061018f5760003560e01c80638803dbee116100d6578063c45a01551161007f578063e8e3370011610059578063e8e3370014610c71578063f305d71914610cfe578063fb3bdb4114610d51576101d5565b8063c45a015514610b25578063d06ca61f14610b3a578063ded9382a14610bf1576101d5565b8063af2979eb116100b0578063af2979eb146109c8578063b6f9de9514610a28578063baa2abde14610abb576101d5565b80638803dbee146108af578063ad5c464814610954578063ad615dec14610992576101d5565b80634a25d94a11610138578063791ac94711610112578063791ac947146107415780637ff36ab5146107e657806385f8c25914610879576101d5565b80634a25d94a146105775780635b0d59841461061c5780635c11d7951461069c576101d5565b80631f00ca74116101695780631f00ca74146103905780632195995c1461044757806338ed1739146104d2576101d5565b806302751cec146101da578063054d50d41461025357806318cbafe51461029b576101d5565b366101d5573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146101d357fe5b005b600080fd5b3480156101e657600080fd5b5061023a600480360360c08110156101fd57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135916040820135916060810135916080820135169060a00135610de4565b6040805192835260208301919091528051918290030190f35b34801561025f57600080fd5b506102896004803603606081101561027657600080fd5b5080359060208101359060400135610f37565b60408051918252519081900360200190f35b3480156102a757600080fd5b50610340600480360360a08110156102be57600080fd5b8135916020810135918101906060810160408201356401000000008111156102e557600080fd5b8201836020820111156102f757600080fd5b8035906020019184602083028401116401000000008311171561031957600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff8135169060200135610f4c565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561037c578181015183820152602001610364565b505050509050019250505060405180910390f35b34801561039c57600080fd5b50610340600480360360408110156103b357600080fd5b813591908101906040810160208201356401000000008111156103d557600080fd5b8201836020820111156103e757600080fd5b8035906020019184602083028401116401000000008311171561040957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611364945050505050565b34801561045357600080fd5b5061023a600480360361016081101561046b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013582169160408201359160608101359160808201359160a08101359091169060c08101359060e081013515159060ff610100820135169061012081013590610140013561139a565b3480156104de57600080fd5b50610340600480360360a08110156104f557600080fd5b81359160208101359181019060608101604082013564010000000081111561051c57600080fd5b82018360208201111561052e57600080fd5b8035906020019184602083028401116401000000008311171561055057600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff81351690602001356114d8565b34801561058357600080fd5b50610340600480360360a081101561059a57600080fd5b8135916020810135918101906060810160408201356401000000008111156105c157600080fd5b8201836020820111156105d357600080fd5b803590602001918460208302840111640100000000831117156105f557600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff8135169060200135611669565b34801561062857600080fd5b50610289600480360361014081101561064057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135916040820135916060810135916080820135169060a08101359060c081013515159060ff60e082013516906101008101359061012001356118ac565b3480156106a857600080fd5b506101d3600480360360a08110156106bf57600080fd5b8135916020810135918101906060810160408201356401000000008111156106e657600080fd5b8201836020820111156106f857600080fd5b8035906020019184602083028401116401000000008311171561071a57600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff81351690602001356119fe565b34801561074d57600080fd5b506101d3600480360360a081101561076457600080fd5b81359160208101359181019060608101604082013564010000000081111561078b57600080fd5b82018360208201111561079d57600080fd5b803590602001918460208302840111640100000000831117156107bf57600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff8135169060200135611d97565b610340600480360360808110156107fc57600080fd5b8135919081019060408101602082013564010000000081111561081e57600080fd5b82018360208201111561083057600080fd5b8035906020019184602083028401116401000000008311171561085257600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff8135169060200135612105565b34801561088557600080fd5b506102896004803603606081101561089c57600080fd5b5080359060208101359060400135612525565b3480156108bb57600080fd5b50610340600480360360a08110156108d257600080fd5b8135916020810135918101906060810160408201356401000000008111156108f957600080fd5b82018360208201111561090b57600080fd5b8035906020019184602083028401116401000000008311171561092d57600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff8135169060200135612532565b34801561096057600080fd5b50610969612671565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561099e57600080fd5b50610289600480360360608110156109b557600080fd5b5080359060208101359060400135612695565b3480156109d457600080fd5b50610289600480360360c08110156109eb57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135916040820135916060810135916080820135169060a001356126a2565b6101d360048036036080811015610a3e57600080fd5b81359190810190604081016020820135640100000000811115610a6057600080fd5b820183602082011115610a7257600080fd5b80359060200191846020830284011164010000000083111715610a9457600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff8135169060200135612882565b348015610ac757600080fd5b5061023a600480360360e0811015610ade57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013582169160408201359160608101359160808201359160a08101359091169060c00135612d65565b348015610b3157600080fd5b5061096961306f565b348015610b4657600080fd5b5061034060048036036040811015610b5d57600080fd5b81359190810190604081016020820135640100000000811115610b7f57600080fd5b820183602082011115610b9157600080fd5b80359060200191846020830284011164010000000083111715610bb357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550613093945050505050565b348015610bfd57600080fd5b5061023a6004803603610140811015610c1557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135916040820135916060810135916080820135169060a08101359060c081013515159060ff60e082013516906101008101359061012001356130c0565b348015610c7d57600080fd5b50610ce06004803603610100811015610c9557600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013582169160408201359160608101359160808201359160a08101359160c0820135169060e00135613218565b60408051938452602084019290925282820152519081900360600190f35b610ce0600480360360c0811015610d1457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135916040820135916060810135916080820135169060a001356133a7565b61034060048036036080811015610d6757600080fd5b81359190810190604081016020820135640100000000811115610d8957600080fd5b820183602082011115610d9b57600080fd5b80359060200191846020830284011164010000000083111715610dbd57600080fd5b919350915073ffffffffffffffffffffffffffffffffffffffff81351690602001356136d3565b6000808242811015610e5757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b610e86897f00000000000000000000000000000000000000000000000000000000000000008a8a8a308a612d65565b9093509150610e96898685613b22565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015610f0957600080fd5b505af1158015610f1d573d6000803e3d6000fd5b50505050610f2b8583613cff565b50965096945050505050565b6000610f44848484613e3c565b949350505050565b60608142811015610fbe57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001686867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811061102357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146110c257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f50415448000000604482015290519081900360640190fd5b6111207f000000000000000000000000000000000000000000000000000000000000000089888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613f6092505050565b9150868260018451038151811061113357fe5b60200260200101511015611192576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615508602b913960400191505060405180910390fd5b611257868660008181106111a257fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff163361123d7f00000000000000000000000000000000000000000000000000000000000000008a8a60008181106111f157fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168b8b600181811061121b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166140c6565b8560008151811061124a57fe5b60200260200101516141b1565b61129682878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250309250614381915050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d836001855103815181106112e257fe5b60200260200101516040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561132057600080fd5b505af1158015611334573d6000803e3d6000fd5b50505050611359848360018551038151811061134c57fe5b6020026020010151613cff565b509695505050505050565b60606113917f00000000000000000000000000000000000000000000000000000000000000008484614608565b90505b92915050565b60008060006113ca7f00000000000000000000000000000000000000000000000000000000000000008f8f6140c6565b90506000876113d9578c6113fb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b604080517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101839052606481018c905260ff8a16608482015260a4810189905260c48101889052905191925073ffffffffffffffffffffffffffffffffffffffff84169163d505accf9160e48082019260009290919082900301818387803b15801561149757600080fd5b505af11580156114ab573d6000803e3d6000fd5b505050506114be8f8f8f8f8f8f8f612d65565b809450819550505050509b509b9950505050505050505050565b6060814281101561154a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b6115a87f000000000000000000000000000000000000000000000000000000000000000089888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613f6092505050565b915086826001845103815181106115bb57fe5b6020026020010151101561161a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615508602b913960400191505060405180910390fd5b61162a868660008181106111a257fe5b61135982878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250614381915050565b606081428110156116db57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001686867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811061174057fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117df57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f50415448000000604482015290519081900360640190fd5b61183d7f00000000000000000000000000000000000000000000000000000000000000008988888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061460892505050565b9150868260008151811061184d57fe5b60200260200101511115611192576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806154986027913960400191505060405180910390fd5b6000806118fa7f00000000000000000000000000000000000000000000000000000000000000008d7f00000000000000000000000000000000000000000000000000000000000000006140c6565b9050600086611909578b61192b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b604080517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101839052606481018b905260ff8916608482015260a4810188905260c48101879052905191925073ffffffffffffffffffffffffffffffffffffffff84169163d505accf9160e48082019260009290919082900301818387803b1580156119c757600080fd5b505af11580156119db573d6000803e3d6000fd5b505050506119ed8d8d8d8d8d8d6126a2565b9d9c50505050505050505050505050565b8042811015611a6e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b611afd85856000818110611a7e57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1633611af77f000000000000000000000000000000000000000000000000000000000000000089896000818110611acd57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168a8a600181811061121b57fe5b8a6141b1565b600085857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818110611b2d57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231856040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611bc657600080fd5b505afa158015611bda573d6000803e3d6000fd5b505050506040513d6020811015611bf057600080fd5b50516040805160208881028281018201909352888252929350611c32929091899189918291850190849080828437600092019190915250889250614796915050565b86611d368288887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818110611c6557fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231886040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611cfe57600080fd5b505afa158015611d12573d6000803e3d6000fd5b505050506040513d6020811015611d2857600080fd5b50519063ffffffff614b2916565b1015611d8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615508602b913960400191505060405180910390fd5b5050505050505050565b8042811015611e0757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001685857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818110611e6c57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f0b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f50415448000000604482015290519081900360640190fd5b611f1b85856000818110611a7e57fe5b611f59858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250309250614796915050565b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016916370a0823191602480820192602092909190829003018186803b158015611fe957600080fd5b505afa158015611ffd573d6000803e3d6000fd5b505050506040513d602081101561201357600080fd5b5051905086811015612070576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615508602b913960400191505060405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156120e357600080fd5b505af11580156120f7573d6000803e3d6000fd5b50505050611d8d8482613cff565b6060814281101561217757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16868660008181106121bb57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461225a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f50415448000000604482015290519081900360640190fd5b6122b87f000000000000000000000000000000000000000000000000000000000000000034888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613f6092505050565b915086826001845103815181106122cb57fe5b6020026020010151101561232a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615508602b913960400191505060405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db08360008151811061237357fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b1580156123a657600080fd5b505af11580156123ba573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb61242c7f000000000000000000000000000000000000000000000000000000000000000089896000818110611acd57fe5b8460008151811061243957fe5b60200260200101516040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156124aa57600080fd5b505af11580156124be573d6000803e3d6000fd5b505050506040513d60208110156124d457600080fd5b50516124dc57fe5b61251b82878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250614381915050565b5095945050505050565b6000610f44848484614b9b565b606081428110156125a457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b6126027f00000000000000000000000000000000000000000000000000000000000000008988888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061460892505050565b9150868260008151811061261257fe5b6020026020010151111561161a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806154986027913960400191505060405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000081565b6000610f44848484614cbf565b6000814281101561271457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b612743887f00000000000000000000000000000000000000000000000000000000000000008989893089612d65565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290519194506127ed92508a91879173ffffffffffffffffffffffffffffffffffffffff8416916370a0823191602480820192602092909190829003018186803b1580156127bc57600080fd5b505afa1580156127d0573d6000803e3d6000fd5b505050506040513d60208110156127e657600080fd5b5051613b22565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561286057600080fd5b505af1158015612874573d6000803e3d6000fd5b505050506113598483613cff565b80428110156128f257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168585600081811061293657fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129d557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f50415448000000604482015290519081900360640190fd5b60003490507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612a4257600080fd5b505af1158015612a56573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb612ac87f000000000000000000000000000000000000000000000000000000000000000089896000818110611acd57fe5b836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015612b3257600080fd5b505af1158015612b46573d6000803e3d6000fd5b505050506040513d6020811015612b5c57600080fd5b5051612b6457fe5b600086867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818110612b9457fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612c2d57600080fd5b505afa158015612c41573d6000803e3d6000fd5b505050506040513d6020811015612c5757600080fd5b50516040805160208981028281018201909352898252929350612c999290918a918a918291850190849080828437600092019190915250899250614796915050565b87611d368289897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818110612ccc57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231896040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611cfe57600080fd5b6000808242811015612dd857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b6000612e057f00000000000000000000000000000000000000000000000000000000000000008c8c6140c6565b604080517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff831660248201819052604482018d9052915192935090916323b872dd916064808201926020929091908290030181600087803b158015612e8657600080fd5b505af1158015612e9a573d6000803e3d6000fd5b505050506040513d6020811015612eb057600080fd5b5050604080517f89afcb4400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116600483015282516000938493928616926389afcb44926024808301939282900301818787803b158015612f2357600080fd5b505af1158015612f37573d6000803e3d6000fd5b505050506040513d6040811015612f4d57600080fd5b50805160209091015190925090506000612f678e8e614d9f565b5090508073ffffffffffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff1614612fa4578183612fa7565b82825b90975095508a871015613005576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806154bf6026913960400191505060405180910390fd5b8986101561305e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806154256026913960400191505060405180910390fd5b505050505097509795505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60606113917f00000000000000000000000000000000000000000000000000000000000000008484613f60565b60008060006131107f00000000000000000000000000000000000000000000000000000000000000008e7f00000000000000000000000000000000000000000000000000000000000000006140c6565b905060008761311f578c613141565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b604080517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101839052606481018c905260ff8a16608482015260a4810189905260c48101889052905191925073ffffffffffffffffffffffffffffffffffffffff84169163d505accf9160e48082019260009290919082900301818387803b1580156131dd57600080fd5b505af11580156131f1573d6000803e3d6000fd5b505050506132038e8e8e8e8e8e610de4565b909f909e509c50505050505050505050505050565b6000806000834281101561328d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b61329b8c8c8c8c8c8c614ef2565b909450925060006132cd7f00000000000000000000000000000000000000000000000000000000000000008e8e6140c6565b90506132db8d3383886141b1565b6132e78c3383876141b1565b8073ffffffffffffffffffffffffffffffffffffffff16636a627842886040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561336657600080fd5b505af115801561337a573d6000803e3d6000fd5b505050506040513d602081101561339057600080fd5b5051949d939c50939a509198505050505050505050565b6000806000834281101561341c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b61344a8a7f00000000000000000000000000000000000000000000000000000000000000008b348c8c614ef2565b9094509250600061349c7f00000000000000000000000000000000000000000000000000000000000000008c7f00000000000000000000000000000000000000000000000000000000000000006140c6565b90506134aa8b3383886141b1565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561351257600080fd5b505af1158015613526573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb82866040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156135d257600080fd5b505af11580156135e6573d6000803e3d6000fd5b505050506040513d60208110156135fc57600080fd5b505161360457fe5b8073ffffffffffffffffffffffffffffffffffffffff16636a627842886040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561368357600080fd5b505af1158015613697573d6000803e3d6000fd5b505050506040513d60208110156136ad57600080fd5b50519250348410156136c5576136c533853403613cff565b505096509650969350505050565b6060814281101561374557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e69737761705632526f757465723a20455850495245440000000000000000604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168686600081811061378957fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461382857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f556e69737761705632526f757465723a20494e56414c49445f50415448000000604482015290519081900360640190fd5b6138867f00000000000000000000000000000000000000000000000000000000000000008888888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061460892505050565b9150348260008151811061389657fe5b602002602001015111156138f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806154986027913960400191505060405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db08360008151811061393e57fe5b60200260200101516040518263ffffffff1660e01b81526004016000604051808303818588803b15801561397157600080fd5b505af1158015613985573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6139f77f000000000000000000000000000000000000000000000000000000000000000089896000818110611acd57fe5b84600081518110613a0457fe5b60200260200101516040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015613a7557600080fd5b505af1158015613a89573d6000803e3d6000fd5b505050506040513d6020811015613a9f57600080fd5b5051613aa757fe5b613ae682878780806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250899250614381915050565b81600081518110613af357fe5b602002602001015134111561251b5761251b3383600081518110613b1357fe5b60200260200101513403613cff565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000178152925182516000946060949389169392918291908083835b60208310613bf857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613bbb565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c5a576040519150601f19603f3d011682016040523d82523d6000602084013e613c5f565b606091505b5091509150818015613c8d575080511580613c8d5750808060200190516020811015613c8a57600080fd5b50515b613cf857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c454400604482015290519081900360640190fd5b5050505050565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040518082805190602001908083835b60208310613d7657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613d39565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613dd8576040519150601f19603f3d011682016040523d82523d6000602084013e613ddd565b606091505b5050905080613e37576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806154e56023913960400191505060405180910390fd5b505050565b6000808411613e96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615557602b913960400191505060405180910390fd5b600083118015613ea65750600082115b613efb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061544b6028913960400191505060405180910390fd5b6000613f0f856103e563ffffffff6151f316565b90506000613f23828563ffffffff6151f316565b90506000613f4983613f3d886103e863ffffffff6151f316565b9063ffffffff61527916565b9050808281613f5457fe5b04979650505050505050565b6060600282511015613fd357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f504154480000604482015290519081900360640190fd5b815167ffffffffffffffff81118015613feb57600080fd5b50604051908082528060200260200182016040528015614015578160200160208202803683370190505b509050828160008151811061402657fe5b60200260200101818152505060005b60018351038110156140be576000806140788786858151811061405457fe5b602002602001015187866001018151811061406b57fe5b60200260200101516152eb565b9150915061409a84848151811061408b57fe5b60200260200101518383613e3c565b8484600101815181106140a957fe5b60209081029190910101525050600101614035565b509392505050565b60008060006140d58585614d9f565b604080517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606094851b811660208084019190915293851b81166034830152825160288184030181526048830184528051908501207fff0000000000000000000000000000000000000000000000000000000000000060688401529a90941b9093166069840152607d8301989098527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f609d808401919091528851808403909101815260bd909201909752805196019590952095945050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017815292518251600094606094938a169392918291908083835b6020831061428f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614252565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146142f1576040519150601f19603f3d011682016040523d82523d6000602084013e6142f6565b606091505b5091509150818015614324575080511580614324575080806020019051602081101561432157600080fd5b50515b614379576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806155336024913960400191505060405180910390fd5b505050505050565b60005b60018351038110156146025760008084838151811061439f57fe5b60200260200101518584600101815181106143b657fe5b60200260200101519150915060006143ce8383614d9f565b50905060008785600101815181106143e257fe5b602002602001015190506000808373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461442a5782600061442e565b6000835b91509150600060028a510388106144455788614486565b6144867f0000000000000000000000000000000000000000000000000000000000000000878c8b6002018151811061447957fe5b60200260200101516140c6565b90506144b37f000000000000000000000000000000000000000000000000000000000000000088886140c6565b73ffffffffffffffffffffffffffffffffffffffff1663022c0d9f84848460006040519080825280601f01601f1916602001820160405280156144fd576020820181803683370190505b506040518563ffffffff1660e01b8152600401808581526020018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614588578181015183820152602001614570565b50505050905090810190601f1680156145b55780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b1580156145d757600080fd5b505af11580156145eb573d6000803e3d6000fd5b505060019099019850614384975050505050505050565b50505050565b606060028251101561467b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f504154480000604482015290519081900360640190fd5b815167ffffffffffffffff8111801561469357600080fd5b506040519080825280602002602001820160405280156146bd578160200160208202803683370190505b50905082816001835103815181106146d157fe5b602090810291909101015281517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b80156140be576000806147318786600186038151811061471d57fe5b602002602001015187868151811061406b57fe5b9150915061475384848151811061474457fe5b60200260200101518383614b9b565b84600185038151811061476257fe5b602090810291909101015250507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01614701565b60005b6001835103811015613e37576000808483815181106147b457fe5b60200260200101518584600101815181106147cb57fe5b60200260200101519150915060006147e38383614d9f565b50905060006148137f000000000000000000000000000000000000000000000000000000000000000085856140c6565b90506000806000808473ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561486157600080fd5b505afa158015614875573d6000803e3d6000fd5b505050506040513d606081101561488b57600080fd5b5080516020909101516dffffffffffffffffffffffffffff918216935016905060008073ffffffffffffffffffffffffffffffffffffffff8a8116908916146148d55782846148d8565b83835b9150915061495d828b73ffffffffffffffffffffffffffffffffffffffff166370a082318a6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611cfe57600080fd5b955061496a868383613e3c565b9450505050506000808573ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146149ae578260006149b2565b6000835b91509150600060028c51038a106149c9578a6149fd565b6149fd7f0000000000000000000000000000000000000000000000000000000000000000898e8d6002018151811061447957fe5b60408051600080825260208201928390527f022c0d9f000000000000000000000000000000000000000000000000000000008352602482018781526044830187905273ffffffffffffffffffffffffffffffffffffffff8086166064850152608060848501908152845160a48601819052969750908c169563022c0d9f958a958a958a9591949193919260c486019290918190849084905b83811015614aad578181015183820152602001614a95565b50505050905090810190601f168015614ada5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b158015614afc57600080fd5b505af1158015614b10573d6000803e3d6000fd5b50506001909b019a506147999950505050505050505050565b8082038281111561139457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604482015290519081900360640190fd5b6000808411614bf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806153d4602c913960400191505060405180910390fd5b600083118015614c055750600082115b614c5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061544b6028913960400191505060405180910390fd5b6000614c7e6103e8614c72868863ffffffff6151f316565b9063ffffffff6151f316565b90506000614c986103e5614c72868963ffffffff614b2916565b9050614cb56001828481614ca857fe5b049063ffffffff61527916565b9695505050505050565b6000808411614d19576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806154736025913960400191505060405180910390fd5b600083118015614d295750600082115b614d7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602881526020018061544b6028913960400191505060405180910390fd5b82614d8f858463ffffffff6151f316565b81614d9657fe5b04949350505050565b6000808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415614e27576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806154006025913960400191505060405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610614e61578284614e64565b83835b909250905073ffffffffffffffffffffffffffffffffffffffff8216614eeb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f414444524553530000604482015290519081900360640190fd5b9250929050565b604080517fe6a4390500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff888116600483015287811660248301529151600092839283927f00000000000000000000000000000000000000000000000000000000000000009092169163e6a4390591604480820192602092909190829003018186803b158015614f9257600080fd5b505afa158015614fa6573d6000803e3d6000fd5b505050506040513d6020811015614fbc57600080fd5b505173ffffffffffffffffffffffffffffffffffffffff1614156150a257604080517fc9c6539600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a81166004830152898116602483015291517f00000000000000000000000000000000000000000000000000000000000000009092169163c9c65396916044808201926020929091908290030181600087803b15801561507557600080fd5b505af1158015615089573d6000803e3d6000fd5b505050506040513d602081101561509f57600080fd5b50505b6000806150d07f00000000000000000000000000000000000000000000000000000000000000008b8b6152eb565b915091508160001480156150e2575080155b156150f2578793508692506151e6565b60006150ff898484614cbf565b905087811161516c5785811015615161576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806154256026913960400191505060405180910390fd5b8894509250826151e4565b6000615179898486614cbf565b90508981111561518557fe5b878110156151de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806154bf6026913960400191505060405180910390fd5b94508793505b505b5050965096945050505050565b600081158061520e5750508082028282828161520b57fe5b04145b61139457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b8082018281101561139457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604482015290519081900360640190fd5b60008060006152fa8585614d9f565b50905060008061530b8888886140c6565b73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561535057600080fd5b505afa158015615364573d6000803e3d6000fd5b505050506040513d606081101561537a57600080fd5b5080516020909101516dffffffffffffffffffffffffffff918216935016905073ffffffffffffffffffffffffffffffffffffffff878116908416146153c15780826153c4565b81815b9099909850965050505050505056fe556e697377617056324c6962726172793a20494e53554646494349454e545f4f55545055545f414d4f554e54556e697377617056324c6962726172793a204944454e544943414c5f414444524553534553556e69737761705632526f757465723a20494e53554646494349454e545f425f414d4f554e54556e697377617056324c6962726172793a20494e53554646494349454e545f4c4951554944495459556e697377617056324c6962726172793a20494e53554646494349454e545f414d4f554e54556e69737761705632526f757465723a204558434553534956455f494e5055545f414d4f554e54556e69737761705632526f757465723a20494e53554646494349454e545f415f414d4f554e545472616e7366657248656c7065723a204554485f5452414e534645525f4641494c4544556e69737761705632526f757465723a20494e53554646494349454e545f4f55545055545f414d4f554e545472616e7366657248656c7065723a205452414e534645525f46524f4d5f4641494c4544556e697377617056324c6962726172793a20494e53554646494349454e545f494e5055545f414d4f554e54a164736f6c6343000606000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {IUniswapV3Factory} from '../../protocols/v3-core/interfaces/IUniswapV3Factory.sol'; library UniswapV3FactoryDeployer { function deploy() internal returns (IUniswapV3Factory factory) { bytes memory initcode_ = abi.encodePacked(initcode()); assembly { factory := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v3-core/contracts/UniswapV3Factory.sol */ function initcode() internal pure returns (bytes memory) { return hex'60a060405234801561001057600080fd5b503060601b608052600380546001600160a01b031916339081179091556040516000907fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c908290a36101f4600081815260046020527ffb8cf1d12598d1a039dd1d106665851a96aadf67d0d9ed76fceea282119208b7805462ffffff1916600a90811790915560405190929160008051602061614b83398151915291a3610bb8600081815260046020527f72dffa9b822156d9cf4b0090fa0b656bcb9cc2b2c60eb6acfc20a34f54b31743805462ffffff1916603c90811790915560405190929160008051602061614b83398151915291a3612710600081815260046020527f8cc740d51daa94ff54f33bd779c2d20149f524c340519b49181be5a08615f829805462ffffff191660c890811790915560405190929160008051602061614b83398151915291a360805160601c615fd7610174600039806105515250615fd76000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063890357301161005b578063890357301461013b5780638a7c195f146101855780638da5cb5b146101b0578063a1671295146101b85761007d565b806313af4035146100825780631698ee82146100aa57806322afcccb14610102575b600080fd5b6100a86004803603602081101561009857600080fd5b50356001600160a01b03166101f4565b005b6100e6600480360360608110156100c057600080fd5b5080356001600160a01b03908116916020810135909116906040013562ffffff16610267565b604080516001600160a01b039092168252519081900360200190f35b6101246004803603602081101561011857600080fd5b503562ffffff16610293565b6040805160029290920b8252519081900360200190f35b6101436102a8565b604080516001600160a01b0396871681529486166020860152929094168383015262ffffff16606083015260029290920b608082015290519081900360a00190f35b6100a86004803603604081101561019b57600080fd5b5062ffffff813516906020013560020b6102de565b6100e66103a1565b6100e6600480360360608110156101ce57600080fd5b5080356001600160a01b03908116916020810135909116906040013562ffffff166103b0565b6003546001600160a01b0316331461020b57600080fd5b6003546040516001600160a01b038084169216907fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c90600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b60056020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b60046020526000908152604090205460020b81565b600054600154600280546001600160a01b03938416939283169281169162ffffff600160a01b83041691600160b81b9004900b85565b6003546001600160a01b031633146102f557600080fd5b620f42408262ffffff161061030957600080fd5b60008160020b13801561032057506140008160020b125b61032957600080fd5b62ffffff8216600090815260046020526040902054600290810b900b1561034f57600080fd5b62ffffff828116600081815260046020526040808220805462ffffff1916600287900b958616179055517fc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc9190a35050565b6003546001600160a01b031681565b60006103ba610546565b826001600160a01b0316846001600160a01b031614156103d957600080fd5b600080846001600160a01b0316866001600160a01b0316106103fc5784866103ff565b85855b90925090506001600160a01b03821661041757600080fd5b62ffffff8416600090815260046020526040902054600290810b9081900b61043e57600080fd5b6001600160a01b0383811660009081526005602090815260408083208685168452825280832062ffffff8a168452909152902054161561047d57600080fd5b61048a308484888561057d565b6001600160a01b03808516600081815260056020818152604080842089871680865290835281852062ffffff8e168087529084528286208054988a166001600160a01b0319998a1681179091558287529484528286208787528452828620818752845294829020805490971684179096558051600289900b815291820192909252815195995091947f783cca1c0412dd0d695e784568c96da2e9c22ff989357a2e8b1d9b2b4e6b71189281900390910190a45050509392505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461057b57600080fd5b565b6040805160a0810182526001600160a01b03878116808352878216602080850182905292881684860181905262ffffff888116606080880182905260028a810b6080998a01819052600080546001600160a01b03199081169099178155600180548a1689179055825490981686177fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff16600160a01b8502177fffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffff16600160b81b91830b9095160293909317909255875180870194909452838801929092528281019190915285518083039091018152930193849052825192909101919091209091610686906106f5565b8190604051809103906000f59050801580156106a6573d6000803e3d6000fd5b50600080546001600160a01b0319908116909155600180549091169055600280547fffffffffffff00000000000000000000000000000000000000000000000000001690559695505050505050565b6158c8806107038339019056fe6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000aa164736f6c6343000706000ac66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {ISwapRouter} from '../../protocols/v3-periphery/interfaces/ISwapRouter.sol'; library NFTDescriptorDeployer { function deploy() internal returns (address nftDescriptor) { bytes memory initcode_ = abi.encodePacked(initcode()); assembly { nftDescriptor := create2(0, add(initcode_, 32), mload(initcode_), 0x00) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v3-periphery/contracts/libraries/NFTDescriptor.sol */ function initcode() internal pure returns (bytes memory) { return hex'615fdb610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063c49917d71461003a575b600080fd5b61004d610048366004613f06565b610063565b60405161005a9190614648565b60405180910390f35b6060600061007e83610079856101800151610170565b6103d1565b905060006100b2610092856060015161048c565b61009f866080015161048c565b6100ad876101a00151610644565b61065a565b905060006101006100c6866000015161068c565b6100d3876080015161048c565b6100e08860200151610644565b6100ed8960400151610644565b6100fb8a6101800151610170565b610767565b905060006101156101108761079d565b6109d8565b90506101458484848460405160200161013194939291906142c3565b6040516020818303038152906040526109d8565b6040516020016101559190614603565b6040516020818303038152906040529450505050505b919050565b606062ffffff82166101b6575060408051808201909152600281527f3025000000000000000000000000000000000000000000000000000000000000602082015261016b565b816000805b62ffffff8316156102065760ff8116156101d7576001016101f0565b600a62ffffff84160662ffffff166000146101f0576001015b600190910190600a62ffffff84160492506101bb565b61020e613e00565b60006005841061030357600060046102298660ff8716610b5b565b1015610236576001610239565b60005b60ff908116915061024d9085166001610b5b565b610258866005610b5b565b106102845761027f61026e60ff86166001610b5b565b610279876005610b5b565b90610b5b565b610287565b60005b60ff8516608085018190529092506102a6906001906102799085610bb8565b60ff90811660a085015260808401516102cd9183916102c791166001610b5b565b90610bb8565b60ff90811660408501526102f59082906102c7906102ee9088166001610bb8565b8590610bb8565b60ff16602084015250610373565b61030e600585610b5b565b60026080840181905290915061032c90600190610279908490610bb8565b60ff90811660a084015261034e906103479085166002610bb8565b8290610bb8565b60ff1660208301819052610363906002610b5b565b60ff166040830152600160c08301525b6103926103838560ff8616610b5b565b62ffffff891690600a0a610c12565b8252600160e0830152600484116103aa5760006103b5565b6103b5846004610b5b565b60ff1660608301526103c682610c79565b979650505050505050565b6060816103e1846060015161048c565b6103ee856080015161048c565b6104278660e00151156104065786610120015161040d565b8661010001515b8761016001518860c001518960a001518a60e00151610ea5565b6104608760e001511561043f57876101000151610446565b8761012001515b8861016001518960c001518a60a001518b60e00151610ea5565b6040516020016104749594939291906143ea565b60405160208183030381529060405290505b92915050565b6060816000805b82518160ff1610156104f057828160ff16815181106104ae57fe5b6020910101517fff0000000000000000000000000000000000000000000000000000000000000016601160f91b14156104e8576001909101905b600101610493565b5060ff81161561063c5760008160ff1683510167ffffffffffffffff8111801561051957600080fd5b506040519080825280601f01601f191660200182016040528015610544576020820181803683370190505b5090506000805b84518160ff16101561062f57848160ff168151811061056657fe5b6020910101517fff0000000000000000000000000000000000000000000000000000000000000016601160f91b14156105e4577f5c000000000000000000000000000000000000000000000000000000000000008383806001019450815181106105cc57fe5b60200101906001600160f81b031916908160001a9053505b848160ff16815181106105f357fe5b602001015160f81c60f81b83838060010194508151811061061057fe5b60200101906001600160f81b031916908160001a90535060010161054b565b508194505050505061016b565b509192915050565b60606104866001600160a01b0383166014610fcf565b6060838383866040516020016106739493929190614177565b60405160208183030381529060405290505b9392505050565b6060816106b157506040805180820190915260018152600360fc1b602082015261016b565b8160005b81156106c957600101600a820491506106b5565b60008167ffffffffffffffff811180156106e257600080fd5b506040519080825280601f01601f19166020018201604052801561070d576020820181803683370190505b50859350905060001982015b831561075e57600a840660300160f81b8282806001900393508151811061073c57fe5b60200101906001600160f81b031916908160001a905350600a84049350610719565b50949350505050565b606083858484896040516020016107829594939291906144eb565b60405160208183030381529060405290505b95945050505050565b60606000604051806102a001604052806107ba8560200151610644565b81526020016107cc8560400151610644565b8152602001846101a001516001600160a01b031681526020018460600151815260200184608001518152602001610807856101800151610170565b815260200184610100015160020b815260200184610120015160020b815260200184610160015160020b8152602001610850856101000151866101200151876101400151611157565b60000b81526020018460000151815260200161087a85602001516001600160a01b0316608861118e565b815260200161089785604001516001600160a01b0316608861118e565b81526020016108b485602001516001600160a01b0316600061118e565b81526020016108d185604001516001600160a01b0316600061118e565b81526020016109046108f686602001516001600160a01b03166010886000015161119d565b600060ff60106101126111bd565b815260200161093761092986604001516001600160a01b03166010886000015161119d565b600060ff60646101e46111bd565b815260200161095c6108f686602001516001600160a01b03166020886000015161119d565b815260200161098161092986604001516001600160a01b03166020886000015161119d565b81526020016109a66108f686602001516001600160a01b03166030886000015161119d565b81526020016109cb61092986604001516001600160a01b03166030886000015161119d565b9052905061068581611205565b60608151600014156109f9575060408051602081019091526000815261016b565b600060405180606001604052806040815260200161526960409139905060006003845160020181610a2657fe5b04600402905060008160200167ffffffffffffffff81118015610a4857600080fd5b506040519080825280601f01601f191660200182016040528015610a73576020820181803683370190505b509050818152600183018586518101602084015b81831015610adf576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825350600101610a87565b600389510660018114610af95760028114610b2557610b4d565b7f3d3d000000000000000000000000000000000000000000000000000000000000600119830152610b4d565b7f3d000000000000000000000000000000000000000000000000000000000000006000198301525b509398975050505050505050565b600082821115610bb2576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082820183811015610685576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000808211610c68576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381610c7157fe5b049392505050565b60606000826020015160ff1667ffffffffffffffff81118015610c9b57600080fd5b506040519080825280601f01601f191660200182016040528015610cc6576020820181803683370190505b5090508260e0015115610d1c577f250000000000000000000000000000000000000000000000000000000000000081600183510381518110610d0457fe5b60200101906001600160f81b031916908160001a9053505b8260c0015115610d7957600360fc1b81600081518110610d3857fe5b60200101906001600160f81b031916908160001a905350601760f91b81600181518110610d6157fe5b60200101906001600160f81b031916908160001a9053505b608083015160ff165b60a0840151610d959060ff166001610bb8565b811015610dcc57603060f81b828281518110610dad57fe5b60200101906001600160f81b031916908160001a905350600101610d82565b505b825115610486576000836060015160ff16118015610df95750826060015160ff16836040015160ff16145b15610e3c5760408301805160ff600019820181169092528251601760f91b92849216908110610e2457fe5b60200101906001600160f81b031916908160001a9053505b8251610e4e90603090600a9006610bb8565b60f81b818460400180518091906001900360ff1660ff1681525060ff1681518110610e7557fe5b60200101906001600160f81b031916908160001a905350600a8360000181815181610e9c57fe5b04905250610dce565b606084600281900b620d89e71981610eb957fe5b050260020b8660020b1415610f13578115610eef576040518060400160405280600381526020016209a82b60eb1b815250610f0c565b6040518060400160405280600381526020016226a4a760e91b8152505b9050610794565b84600281900b620d89e881610f2457fe5b050260020b8660020b1415610f7a578115610f5a576040518060400160405280600381526020016226a4a760e91b815250610f0c565b5060408051808201909152600381526209a82b60eb1b6020820152610794565b6000610f8587611494565b90508215610fbc57610fb978010000000000000000000000000000000000000000000000006001600160a01b038316610c12565b90505b610fc78186866117e2565b915050610794565b606060008260020260020167ffffffffffffffff81118015610ff057600080fd5b506040519080825280601f01601f19166020018201604052801561101b576020820181803683370190505b509050600360fc1b8160008151811061103057fe5b60200101906001600160f81b031916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061107557fe5b60200101906001600160f81b031916908160001a905350600160028402015b6001811115611103577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106110cc57fe5b1a60f81b8282815181106110dc57fe5b60200101906001600160f81b031916908160001a90535060049490941c9360001901611094565b508315610685576040805162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015290519081900360640190fd5b60008360020b8260020b12156111705750600019610685565b8260020b8260020b131561118657506001610685565b506000610685565b606061068583831c60036119b0565b600060ff826111ac8686611a77565b02816111b457fe5b06949350505050565b60606111fb6111f6846102c76111d3888a610b5b565b6111f06111e0888a610b5b565b6111ea8d8d610b5b565b90611a7e565b90610c12565b61068c565b9695505050505050565b606061121082611ad7565b61122c836000015184602001518560600151866080015161218b565b611243846060015185608001518660a001516124b6565b6112618560c001518660e00151876101000151886101200151612606565b61128161127287610140015161068c565b8760c001518860e00151612959565b6112948761014001518860400151612d8a565b6040516020018087805190602001908083835b602083106112c65780518252601f1990920191602091820191016112a7565b51815160209384036101000a600019018019909216911617905289519190930192890191508083835b6020831061130e5780518252601f1990920191602091820191016112ef565b51815160209384036101000a600019018019909216911617905288519190930192880191508083835b602083106113565780518252601f199092019160209182019101611337565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b6020831061139e5780518252601f19909201916020918201910161137f565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106113e65780518252601f1990920191602091820191016113c7565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831061142e5780518252601f19909201916020918201910161140f565b5181516020939093036101000a60001901801990911692169190911790527f3c2f7376673e000000000000000000000000000000000000000000000000000092019182525060408051808303601919018152600690920190529998505050505050505050565b60008060008360020b126114ab578260020b6114b3565b8260020b6000035b9050620d89e881111561150d576040805162461bcd60e51b815260206004820152600160248201527f5400000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60006001821661152157600160801b611533565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615611567576ffff97272373d413259a46990580e213a0260801c5b6004821615611586576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b60088216156115a5576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b60108216156115c4576fffcb9843d60f6159c9db58835c9266440260801c5b60208216156115e3576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615611602576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611621576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611641576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615611661576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615611681576ff3392b0822b70005940c7a398e4b70f30260801c5b6108008216156116a1576fe7159475a2c29b7443b29c7fa6e889d90260801c5b6110008216156116c1576fd097f3bdfd2022b8845ad8f792aa58250260801c5b6120008216156116e1576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615611701576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611721576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611742576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615611762576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615611781576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561179e576b048a170391f7dc42444e8fa20260801c5b60008460020b13156117b95780600019816117b557fe5b0490505b6401000000008106156117cd5760016117d0565b60005b60ff16602082901c0192505050919050565b606060006117f1858585612e02565b90506000611809828368010000000000000000612f04565b90506c010000000000000000000000008210801561184a576118438272047bf19673df52e37f2410011d100000000000600160801b612f04565b915061185f565b61185c82620186a0600160801b612f04565b91505b8160005b811561187757600101600a82049150611863565b600019016000806118888684612fb3565b915091508015611899576001909201915b6118a1613e00565b851561190e576118c06118b8602b60ff8716610b5b565b600790610bb8565b60ff9081166020830152600260808301526118e6906001906102c790602b908816610b5b565b60ff90811660a0830152602082015161190191166001610b5b565b60ff166040820152611985565b60098460ff16106119575761192760ff85166004610b5b565b60ff166020820181905260056080830152611943906001610b5b565b60ff1660a082015260046040820152611985565b6006602082015260056040820181905261197c906001906102c79060ff881690610b5b565b60ff1660608201525b82815285151560c0820152600060e08201526119a081610c79565b9c9b505050505050505050505050565b606060008260020267ffffffffffffffff811180156119ce57600080fd5b506040519080825280601f01601f1916602001820160405280156119f9576020820181803683370190505b5080519091505b8015611a6f577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611a3557fe5b1a60f81b826001830381518110611a4857fe5b60200101906001600160f81b031916908160001a90535060049490941c9360001901611a00565b509392505050565b1c60ff1690565b600082611a8d57506000610486565b82820282848281611a9a57fe5b04146106855760405162461bcd60e51b81526004018080602001828103825260218152602001806154886021913960400191505060405180910390fd5b6060611b6c82610160015160405160200180806150426081913960810182805190602001908083835b60208310611b1f5780518252601f199092019160209182019101611b00565b6001836020036101000a038019825116818451168082178552505050505050905001806813979f1e17b9bb339f60b91b8152506009019150506040516020818303038152906040526109d8565b611cd8836101e001518461020001518561018001516040516020018080614b7f6063913960630184805190602001908083835b60208310611bbe5780518252601f199092019160209182019101611b9f565b51815160209384036101000a600019018019909216911617905265272063793d2760d01b919093019081528551600690910192860191508083835b60208310611c185780518252601f199092019160209182019101611bf9565b51815160209384036101000a60001901801990921691161790527f2720723d273132307078272066696c6c3d272300000000000000000000000000919093019081528451601390910192850191508083835b60208310611c895780518252601f199092019160209182019101611c6a565b6001836020036101000a038019825116818451168082178552505050505050905001806813979f1e17b9bb339f60b91b81525060090193505050506040516020818303038152906040526109d8565b611d29846102200151856102400151866101a001516040516020018080614b7f60639139606301848051906020019080838360208310611bbe5780518252601f199092019160209182019101611b9f565b611e48856102600151866102800151876101c001516040516020018080614b7f6063913960630184805190602001908083835b60208310611d7b5780518252601f199092019160209182019101611d5c565b51815160209384036101000a600019018019909216911617905265272063793d2760d01b919093019081528551600690910192860191508083835b60208310611dd55780518252601f199092019160209182019101611db6565b51815160001960209485036101000a019081169019919091161790527f2720723d273130307078272066696c6c3d272300000000000000000000000000939091019283528451601390930192908501915080838360208310611c895780518252601f199092019160209182019101611c6a565b6101608601516040516020018060566148fa8239605601602c6152a982397f3c646566733e0000000000000000000000000000000000000000000000000000602c820152603201604b614ff78239604b0186805190602001908083835b60208310611ec45780518252601f199092019160209182019101611ea5565b6001836020036101000a03801982511681845116808217855250505050505090500180615b2f603e9139603e0185805190602001908083835b60208310611f1c5780518252601f199092019160209182019101611efd565b6001836020036101000a038019825116818451168082178552505050505050905001806150c3603e9139603e0184805190602001908083835b60208310611f745780518252601f199092019160209182019101611f55565b5181516020939093036101000a60001901801990911692169190911790527f22202f3e00000000000000000000000000000000000000000000000000000000920191825250600401603b6147f28239603b0183805190602001908083835b60208310611ff15780518252601f199092019160209182019101611fd2565b6001836020036101000a03801982511681845116808217855250505050505090500180614c3f60999139609901607f6156e08239607f016088615aa782396088016041614cd88239604101605d615c678239605d01607261578c8239607201604961475b823960490160be614f39823960be016071614a0b8239607101607561562382396075016066614d19823960660160a46152d5823960a4016085615b6d82397f3c6720636c69702d706174683d2275726c2823636f726e65727329223e00000060858201527f3c726563742066696c6c3d22000000000000000000000000000000000000000060a2820152825160ae9091019060208401908083835b6020831061210f5780518252601f1990920191602091820191016120f0565b6001836020036101000a03801982511681845116808217855250505050505090500180614d7f60319139603101604e6147a48239604e01605d614be28239605d0160416152288239604101605261510182396052016075615bf28239607501955050505050506040516020818303038152906040529050919050565b60608382858488878a896040516020018080615d4a60259139602501607d614ebc8239607d0189805190602001908083835b602083106121dc5780518252601f1990920191602091820191016121bd565b51815160209384036101000a600019018019909216911617905264010714051160dd1b919093019081528a516005909101928b0191508083835b602083106122355780518252601f199092019160209182019101612216565b6001836020036101000a03801982511681845116808217855250505050505090500180614db0607991396079016086615cc4823960860187805190602001908083835b602083106122975780518252601f199092019160209182019101612278565b51815160209384036101000a600019018019909216911617905264010714051160dd1b919093019081528851600590910192890191508083835b602083106122f05780518252601f1990920191602091820191016122d1565b6001836020036101000a0380198251168184511680821785525050505050509050018061498660859139608501607b6159158239607b0185805190602001908083835b602083106123525780518252601f199092019160209182019101612333565b51815160209384036101000a600019018019909216911617905264010714051160dd1b919093019081528651600590910192870191508083835b602083106123ab5780518252601f19909201916020918201910161238c565b6001836020036101000a03801982511681845116808217855250505050505090500180614ad0605d9139605d0160a3615580823960a30183805190602001908083835b6020831061240d5780518252601f1990920191602091820191016123ee565b51815160209384036101000a600019018019909216911617905264010714051160dd1b919093019081528451600590910192850191508083835b602083106124665780518252601f199092019160209182019101612447565b6001836020036101000a038019825116818451168082178552505050505050905001806146d0608b9139608b01985050505050505050506040516020818303038152906040529050949350505050565b6060838383604051602001808061482d60cd913960cd0184805190602001908083835b602083106124f85780518252601f1990920191602091820191016124d9565b6001836020036101000a03801982511681845116808217855250505050505090500180602f60f81b81525060010183805190602001908083835b602083106125515780518252601f199092019160209182019101612532565b6001836020036101000a03801982511681845116808217855250505050505090500180615ef36077913960770182805190602001908083835b602083106125a95780518252601f19909201916020918201910161258a565b5181516020939093036101000a60001901801990911692169190911790526a1e17ba32bc3a1f1e17b39f60a91b920191825250600b016073615d938239607301935050505060405160208183030381529060405290509392505050565b606060008260000b600114612698578260000b6000191461265c576040518060400160405280600581526020017f236e6f6e65000000000000000000000000000000000000000000000000000000815250612693565b6040518060400160405280600a81526020017f23666164652d646f776e000000000000000000000000000000000000000000008152505b6126cf565b6040518060400160405280600881526020017f23666164652d75700000000000000000000000000000000000000000000000008152505b905060006126de878787613024565b9050818183836126ed88613272565b60405160200180807f3c67206d61736b3d2275726c2800000000000000000000000000000000000000815250600d0186805190602001908083835b602083106127475780518252601f199092019160209182019101612728565b5181516020939093036101000a600019018019909116921691909117905261149160f11b9201918252506002016077615379823960770185805190602001908083835b602083106127a95780518252601f19909201916020918201910161278a565b6001836020036101000a03801982511681845116808217855250505050505090500180614a7c60549139605401807f3c2f673e3c67206d61736b3d2275726c2800000000000000000000000000000081525060110184805190602001908083835b602083106128295780518252601f19909201916020918201910161280a565b5181516020939093036101000a600019018019909116921691909117905261149160f11b92019182525060020160296153f0823960290160456154438239604501807f3c7061746820643d22000000000000000000000000000000000000000000000081525060090183805190602001908083835b602083106128bd5780518252601f19909201916020918201910161289e565b6001836020036101000a038019825116818451168082178552505050505050905001806156986048913960480182805190602001908083835b602083106129155780518252601f1990920191602091820191016128f6565b6001836020036101000a0380198251168184511680821785525050505050509050019550505050505060405160208183030381529060405292505050949350505050565b6060600061296684613746565b9050600061297384613746565b865183518251929350600490910191600a91820191016000806129968a8a613850565b915091506129a98560040160070261068c565b8b6129b98660040160070261068c565b896129c98760040160070261068c565b8a8787604051602001808061575f602d9139602d01806c1e3932b1ba103bb4b23a341e9160991b815250600d0189805190602001908083835b60208310612a215780518252601f199092019160209182019101612a02565b6001836020036101000a03801982511681845116808217855250505050505090500180615153603d9139603d01608d615e068239608d0188805190602001908083835b60208310612a835780518252601f199092019160209182019101612a64565b5181516020939093036101000a60001901801990911692169190911790526a1e17ba32bc3a1f1e17b39f60a91b920191825250600b01602d615fa28239602d01806c1e3932b1ba103bb4b23a341e9160991b815250600d0187805190602001908083835b60208310612b065780518252601f199092019160209182019101612ae7565b6001836020036101000a03801982511681845116808217855250505050505090500180615153603d9139603d016093614e29823960930186805190602001908083835b60208310612b685780518252601f199092019160209182019101612b49565b5181516020939093036101000a60001901801990911692169190911790526a1e17ba32bc3a1f1e17b39f60a91b920191825250600b01602d614b2d8239602d01806c1e3932b1ba103bb4b23a341e9160991b815250600d0185805190602001908083835b60208310612beb5780518252601f199092019160209182019101612bcc565b6001836020036101000a03801982511681845116808217855250505050505090500180615153603d9139603d016093615990823960930184805190602001908083835b60208310612c4d5780518252601f199092019160209182019101612c2e565b6001836020036101000a03801982511681845116808217855250505050505090500180615f6a603891396038016060615e938239606001606461551c82396064016025614b5a823960250183805190602001908083835b60208310612cc35780518252601f199092019160209182019101612ca4565b51815160209384036101000a60001901801990921691161790527f70782c2000000000000000000000000000000000000000000000000000000000919093019081528451600490910192850191508083835b60208310612d345780518252601f199092019160209182019101612d15565b6001836020036101000a0380198251168184511680821785525050505050509050018061495060369139603601985050505050505050506040516020818303038152906040529750505050505050509392505050565b6060612d968383613c81565b15612dec5760405160200180608d6158888239608d0160736154a9823960730160716151b78239607101608a6157fe8239608a016084615a23823960840190506040516020818303038152906040529050610486565b5060408051602081019091526000815292915050565b600080612e1d612e1860ff868116908616613ce4565b613d49565b9050600081118015612e30575060128111155b15612ef1578260ff168460ff161115612e9a57612e64612e51826002610c12565b6001600160a01b03871690600a0a611a7e565b91506002810660011415612e9557612e92827003298b075b4b6a5240945790619b37fd4a600160801b612f04565b91505b612eec565b612ebb612ea8826002610c12565b6001600160a01b03871690600a0a610c12565b91506002810660011415612eec57612ee982600160801b7003298b075b4b6a5240945790619b37fd4a612f04565b91505b611a6f565b50506001600160a01b0390921692915050565b6000808060001985870986860292508281109083900303905080612f3a5760008411612f2f57600080fd5b508290049050610685565b808411612f4657600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b600080600060058460ff161115612fdb57612fd88560ff600419870116600a0a610c12565b94505b60006004600a8706119050612ff186600a610c12565b95508015613000578560010195505b85620186a0141561301657600a86049550600191505b5084925090505b9250929050565b606060008260020b85850360020b8161303957fe5b05905060048160020b13613084576040518060400160405280601a81526020017f4d312031433431203431203130352031303520313435203134350000000000008152509150611a6f565b60088160020b136130cc576040518060400160405280601981526020017f4d312031433333203439203937203131332031343520313435000000000000008152509150611a6f565b60108160020b13613114576040518060400160405280601981526020017f4d312031433333203537203839203131332031343520313435000000000000008152509150611a6f565b60208160020b1361315c576040518060400160405280601981526020017f4d312031433235203635203831203132312031343520313435000000000000008152509150611a6f565b60408160020b136131a4576040518060400160405280601981526020017f4d312031433137203733203733203132392031343520313435000000000000008152509150611a6f565b60808160020b136131ec576040518060400160405280601881526020017f4d312031433920383120363520313337203134352031343500000000000000008152509150611a6f565b6101008160020b13613235576040518060400160405280601a81526020017f4d31203143312038392035372e352031343520313435203134350000000000008152509150611a6f565b505060408051808201909152601881527f4d3120314331203937203439203134352031343520313435000000000000000060208201529392505050565b604080518082018252600281527f37330000000000000000000000000000000000000000000000000000000000006020808301919091528251808401845260038082527f313930000000000000000000000000000000000000000000000000000000000082840152845180860186528181527f32313700000000000000000000000000000000000000000000000000000000008185015285518087019096529085527f3333340000000000000000000000000000000000000000000000000000000000928501929092526060939091906001600087900b148061335957508560000b600019145b15613550578560000b600019146133705781613372565b835b8660000b600019146133845781613386565b835b8760000b60001914613398578361339a565b855b8860000b600019146133ac57836133ae565b855b60405160200180806b1e31b4b931b6329031bc1e9160a11b815250600c0185805190602001908083835b602083106133f75780518252601f1990920191602091820191016133d8565b51815160209384036101000a600019018019909216911617905267383c111031bc9e9160c11b919093019081528651600890910192870191508083835b602083106134535780518252601f199092019160209182019101613434565b6001836020036101000a038019825116818451168082178552505050505050905001806151906027913960270183805190602001908083835b602083106134ab5780518252601f19909201916020918201910161348c565b51815160209384036101000a600019018019909216911617905267383c111031bc9e9160c11b919093019081528451600890910192850191508083835b602083106135075780518252601f1990920191602091820191016134e8565b6001836020036101000a03801982511681845116808217855250505050505090500180615419602a9139602a01945050505050604051602081830303815290604052945061373d565b8383838360405160200180806b1e31b4b931b6329031bc1e9160a11b815250600c0185805190602001908083835b6020831061359d5780518252601f19909201916020918201910161357e565b51815160209384036101000a600019018019909216911617905267383c111031bc9e9160c11b919093019081528651600890910192870191508083835b602083106135f95780518252601f1990920191602091820191016135da565b51815160209384036101000a60001901801990921691161790527f70782220723d22347078222066696c6c3d22776869746522202f3e0000000000919093019081526b1e31b4b931b6329031bc1e9160a11b601b8201528551602790910192860191508083835b6020831061367f5780518252601f199092019160209182019101613660565b51815160209384036101000a600019018019909216911617905267383c111031bc9e9160c11b919093019081528451600890910192850191508083835b602083106136db5780518252601f1990920191602091820191016136bc565b6001836020036101000a038019825116818451168082178552505050505050905001807f70782220723d22347078222066696c6c3d22776869746522202f3e0000000000815250601b0194505050505060405160208183030381529060405294505b50505050919050565b6060600060405180602001604052806000815250905060008360020b121561378c5782600019029250604051806040016040528060018152602001602d60f81b81525090505b806137998460020b61068c565b6040516020018083805190602001908083835b602083106137cb5780518252601f1990920191602091820191016137ac565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106138135780518252601f1990920191602091820191016137f4565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052915050919050565b60608060006002858501810b0590506201e847198160020b12156138c857604051806040016040528060018152602001600760fb1b8152506040518060400160405280600181526020017f3700000000000000000000000000000000000000000000000000000000000000815250925092505061301d565b620124f7198160020b121561393157604051806040016040528060018152602001600760fb1b8152506040518060400160405280600481526020017f31302e3500000000000000000000000000000000000000000000000000000000815250925092505061301d565b6161a7198160020b121561399957604051806040016040528060018152602001600760fb1b8152506040518060400160405280600581526020017f31342e3235000000000000000000000000000000000000000000000000000000815250925092505061301d565b611387198160020b1215613a02576040518060400160405280600281526020017f313000000000000000000000000000000000000000000000000000000000000081525060405180604001604052806002815260200161062760f31b815250925092505061301d565b60008160020b1215613a69576040518060400160405280600281526020017f313100000000000000000000000000000000000000000000000000000000000081525060405180604001604052806002815260200161323160f01b815250925092505061301d565b6113888160020b1215613aec576040518060400160405280600281526020017f31330000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600281526020017f3233000000000000000000000000000000000000000000000000000000000000815250925092505061301d565b6161a88160020b1215613b6f576040518060400160405280600281526020017f31350000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600281526020017f3235000000000000000000000000000000000000000000000000000000000000815250925092505061301d565b620124f88160020b1215613bd85760405180604001604052806002815260200161062760f31b8152506040518060400160405280600281526020017f3236000000000000000000000000000000000000000000000000000000000000815250925092505061301d565b6201e8488160020b1215613c265760405180604001604052806002815260200161323160f01b81525060405180604001604052806002815260200161323760f01b815250925092505061301d565b6040518060400160405280600281526020017f323400000000000000000000000000000000000000000000000000000000000081525060405180604001604052806002815260200161323760f01b815250925092505061301d565b6040805160208082018590526bffffffffffffffffffffffff19606085901b16828401528251603481840301815260549092019092528051910120600090613cc884613d60565b60020260010160ff1660001981613cdb57fe5b04119392505050565b6000818303818312801590613cf95750838113155b80613d0e5750600083128015613d0e57508381135b6106855760405162461bcd60e51b8152600401808060200182810382526024815260200180615d6f6024913960400191505060405180910390fd5b600080821215613d5c5781600003610486565b5090565b6000808211613d6e57600080fd5b600160801b8210613d8157608091821c91015b680100000000000000008210613d9957604091821c91015b6401000000008210613dad57602091821c91015b620100008210613dbf57601091821c91015b6101008210613dd057600891821c91015b60108210613de057600491821c91015b60048210613df057600291821c91015b6002821061016b57600101919050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b80356001600160a01b038116811461016b57600080fd5b8035801515811461016b57600080fd5b8035600281900b811461016b57600080fd5b600082601f830112613e8d578081fd5b813567ffffffffffffffff811115613ea157fe5b613eb4601f8201601f191660200161467b565b818152846020838601011115613ec8578283fd5b816020850160208301379081016020019190915292915050565b803562ffffff8116811461016b57600080fd5b803560ff8116811461016b57600080fd5b600060208284031215613f17578081fd5b813567ffffffffffffffff80821115613f2e578283fd5b81840191506101c0808387031215613f44578384fd5b613f4d8161467b565b905082358152613f5f60208401613e44565b6020820152613f7060408401613e44565b6040820152606083013582811115613f86578485fd5b613f9287828601613e7d565b606083015250608083013582811115613fa9578485fd5b613fb587828601613e7d565b608083015250613fc760a08401613ef5565b60a0820152613fd860c08401613ef5565b60c0820152613fe960e08401613e5b565b60e08201526101009150613ffe828401613e6b565b828201526101209150614012828401613e6b565b828201526101409150614026828401613e6b565b82820152610160915061403a828401613e6b565b82820152610180915061404e828401613ee2565b828201526101a09150614062828401613e44565b91810191909152949350505050565b6000815161408381856020860161469f565b9290920192915050565b7fe29aa0efb88f20444953434c41494d45523a204475652064696c6967656e636581527f20697320696d7065726174697665207768656e20617373657373696e6720746860208201527f6973204e46542e204d616b65207375726520746f6b656e20616464726573736560408201527f73206d617463682074686520657870656374656420746f6b656e732c2061732060608201527f746f6b656e2073796d626f6c73206d617920626520696d6974617465642e00006080820152609e0190565b7f5c6e5c6e00000000000000000000000000000000000000000000000000000000815260040190565b60007f54686973204e465420726570726573656e74732061206c69717569646974792082527f706f736974696f6e20696e206120556e69737761702056332000000000000000602083015285516141d5816039850160208a0161469f565b602d60f81b60399184019182015285516141f681603a840160208a0161469f565b7f20706f6f6c2e2000000000000000000000000000000000000000000000000000603a92909101918201527f546865206f776e6572206f662074686973204e46542063616e206d6f6469667960418201527f206f722072656465656d2074686520706f736974696f6e2e5c6e00000000000060618201527f5c6e506f6f6c20416464726573733a2000000000000000000000000000000000607b82015284516142a681608b84016020890161469f565b612e3760f11b608b92909101918201526103c6608d820185614071565b60007f7b226e616d65223a220000000000000000000000000000000000000000000000825285516142fb816009850160208a0161469f565b7f222c20226465736372697074696f6e223a220000000000000000000000000000600991840191820152855161433881601b840160208a0161469f565b855191019061434e81601b84016020890161469f565b7f222c2022696d616765223a202200000000000000000000000000000000000000601b92909101918201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000602882015283516143b281604284016020880161469f565b7f227d000000000000000000000000000000000000000000000000000000000000604292909101918201526044019695505050505050565b60007f556e6973776170202d20000000000000000000000000000000000000000000008252865161442281600a850160208b0161469f565b80830190507f202d20000000000000000000000000000000000000000000000000000000000080600a830152875161446181600d850160208c0161469f565b602f60f81b600d9390910192830152865161448381600e850160208b0161469f565b600e920191820152845161449e81601184016020890161469f565b7f3c3e0000000000000000000000000000000000000000000000000000000000006011929091019182015283516144dc81601384016020880161469f565b01601301979650505050505050565b60007f20416464726573733a2000000000000000000000000000000000000000000000808352875161452481600a860160208c0161469f565b612e3760f11b600a91850191820152875161454681600c840160208c0161469f565b01600c810191909152855190614563826016830160208a0161469f565b8181019150507f5c6e46656520546965723a200000000000000000000000000000000000000000601682015284516145a281602284016020890161469f565b7f5c6e546f6b656e2049443a2000000000000000000000000000000000000000006022929091019182015283516145e081602e84016020880161469f565b6145f66145f1602e8385010161414e565b61408d565b9998505050505050505050565b60007f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008252825161463b81601d85016020870161469f565b91909101601d0192915050565b600060208252825180602084015261466781604085016020870161469f565b601f01601f19169190910160400192915050565b60405181810167ffffffffffffffff8111828210171561469757fe5b604052919050565b60005b838110156146ba5781810151838201526020016146a2565b838111156146c9576000848401525b5050505056fe203c616e696d6174652061646469746976653d2273756d22206174747269627574654e616d653d2273746172744f6666736574222066726f6d3d2230252220746f3d22313030252220626567696e3d22307322206475723d223330732220726570656174436f756e743d22696e646566696e69746522202f3e3c2f74657874506174683e3c2f746578743e3c73746f70206f66667365743d222e39222073746f702d636f6c6f723d227768697465222073746f702d6f7061636974793d223022202f3e3c2f6c696e6561724772616469656e743e3c72656374207374796c653d2266696c7465723a2075726c28236631292220783d223070782220793d22307078222077696474683d22323930707822206865696768743d22353030707822202f3e3c6665496d61676520726573756c743d2270332220786c696e6b3a687265663d22646174613a696d6167652f7376672b786d6c3b6261736536342c3c67206d61736b3d2275726c2823666164652d73796d626f6c29223e3c726563742066696c6c3d226e6f6e652220783d223070782220793d22307078222077696474683d22323930707822206865696768743d22323030707822202f3e203c7465787420793d22373070782220783d2233327078222066696c6c3d2277686974652220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d7765696768743d223230302220666f6e742d73697a653d2233367078223e3c7376672077696474683d2232393022206865696768743d22353030222076696577426f783d2230203020323930203530302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672270782c2030707829222063783d22307078222063793d223070782220723d22347078222066696c6c3d227768697465222f3e3c2f673e203c616e696d6174652061646469746976653d2273756d22206174747269627574654e616d653d2273746172744f6666736574222066726f6d3d2230252220746f3d22313030252220626567696e3d22307322206475723d223330732220726570656174436f756e743d22696e646566696e69746522202f3e203c2f74657874506174683e3c6d61736b2069643d22666164652d757022206d61736b436f6e74656e74556e6974733d226f626a656374426f756e64696e67426f78223e3c726563742077696474683d223122206865696768743d2231222066696c6c3d2275726c2823677261642d75702922202f3e3c2f6d61736b3e22207374726f6b653d227267626128302c302c302c302e332922207374726f6b652d77696474683d2233327078222066696c6c3d226e6f6e6522207374726f6b652d6c696e656361703d22726f756e6422202f3e203c616e696d6174652061646469746976653d2273756d22206174747269627574654e616d653d2273746172744f6666736574222066726f6d3d2230252220746f3d22313030252220626567696e3d22307322206475723d2233307322203c67207374796c653d227472616e73666f726d3a7472616e736c61746528323970782c20343434707829223e3c636972636c65207374796c653d227472616e73666f726d3a7472616e736c6174653364283c7376672077696474683d2732393027206865696768743d27353030272076696577426f783d2730203020323930203530302720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323030302f737667273e3c636972636c652063783d27203c67207374796c653d2266696c7465723a75726c2823746f702d726567696f6e2d626c7572293b207472616e73666f726d3a7363616c6528312e35293b207472616e73666f726d2d6f726967696e3a63656e74657220746f703b223e22202f3e3c6665426c656e64206d6f64653d226f7665726c61792220696e3d2270302220696e323d22703122202f3e3c6665426c656e64206d6f64653d226578636c7573696f6e2220696e323d22703222202f3e3c6665426c656e64206d6f64653d226f7665726c61792220696e323d2270332220726573756c743d22626c656e644f757422202f3e3c6665476175737369616e426c7572203c706174682069643d226d696e696d61702220643d224d3233342034343443323334203435372e393439203234322e323120343633203235332034363322202f3e3c6d61736b2069643d226e6f6e6522206d61736b436f6e74656e74556e6974733d226f626a656374426f756e64696e67426f78223e3c726563742077696474683d223122206865696768743d2231222066696c6c3d22776869746522202f3e3c2f6d61736b3e2220783d223070782220793d22307078222077696474683d22323930707822206865696768743d22353030707822202f3e203c616e696d6174652061646469746976653d2273756d22206174747269627574654e616d653d2273746172744f6666736574222066726f6d3d2230252220746f3d22313030252220626567696e3d22307322206475723d223330732220726570656174436f756e743d22696e646566696e69746522202f3e3c7465787420783d22313270782220793d22313770782220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d2231327078222066696c6c3d227768697465223e3c747370616e2066696c6c3d2272676261283235352c3235352c3235352c302e3629223e4d696e205469636b3a203c2f747370616e3e3c74657874506174682073746172744f66667365743d222d31303025222066696c6c3d2277686974652220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d22313070782220786c696e6b3a687265663d2223746578742d706174682d61223e3c6c696e6561724772616469656e742069643d22677261642d646f776e222078313d2230222078323d2231222079313d2230222079323d2231223e3c73746f70206f66667365743d22302e30222073746f702d636f6c6f723d227768697465222073746f702d6f7061636974793d223122202f3e3c73746f70206f66667365743d22302e39222073746f702d636f6c6f723d227768697465222073746f702d6f7061636974793d223022202f3e3c2f6c696e6561724772616469656e743e3c66696c7465722069643d226631223e3c6665496d61676520726573756c743d2270302220786c696e6b3a687265663d22646174613a696d6167652f7376672b786d6c3b6261736536342c3c7376672077696474683d2732393027206865696768743d27353030272076696577426f783d2730203020323930203530302720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323030302f737667273e3c726563742077696474683d27323930707827206865696768743d273530307078272066696c6c3d2723222f3e3c6665496d61676520726573756c743d2270322220786c696e6b3a687265663d22646174613a696d6167652f7376672b786d6c3b6261736536342c3c656c6c697073652063783d22353025222063793d22307078222072783d223138307078222072793d223132307078222066696c6c3d222330303022206f7061636974793d22302e383522202f3e3c2f673e707822206865696768743d2232367078222072783d22387078222072793d22387078222066696c6c3d227267626128302c302c302c302e362922202f3e70782220723d22347078222066696c6c3d22776869746522202f3e3c636972636c652063783d2231312e333437384c32342031324c31342e343334312031322e363532324c32322e333932332031384c31332e373831392031332e373831394c31382032322e333932334c31322e363532322031342e343334314c31322032344c31312e333437382031342e343334314c362032322e33393c726563742066696c6c3d226e6f6e652220783d223070782220793d22307078222077696474683d22323930707822206865696768743d22353030707822202f3e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f20786d6c6e733a786c696e6b3d27687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b273e3c6c696e6561724772616469656e742069643d22677261642d73796d626f6c223e3c73746f70206f66667365743d22302e37222073746f702d636f6c6f723d227768697465222073746f702d6f7061636974793d223122202f3e3c73746f70206f66667365743d222e3935222073746f702d636f6c6f723d227768697465222073746f702d6f7061636974793d223022202f3e3c2f6c696e6561724772616469656e743e207374796c653d227472616e73666f726d3a7472616e736c61746528373270782c313839707829223e3c7265637420783d222d313670782220793d222d31367078222077696474683d22313830707822206865696768743d223138307078222066696c6c3d226e6f6e6522202f3e3c7061746820643d22207374796c653d227472616e73666f726d3a7472616e736c61746528373270782c313839707829223e70782220723d2232347078222066696c6c3d226e6f6e6522207374726f6b653d22776869746522202f3e3c7265637420783d222d313670782220793d222d31367078222077696474683d22313830707822206865696768743d223138307078222066696c6c3d226e6f6e6522202f3e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f773c673e3c70617468207374796c653d227472616e73666f726d3a7472616e736c617465283670782c367078292220643d224d313220304c31322e3635323220392e35363538374c313820312e363037374c31332e373831392031302e323138314c32322e3339323320364c31342e34333431203c70617468207374726f6b652d6c696e656361703d22726f756e642220643d224d38203943382e30303030342032322e393439342031362e32303939203238203237203238222066696c6c3d226e6f6e6522207374726f6b653d22776869746522202f3e20726570656174436f756e743d22696e646566696e69746522202f3e3c2f74657874506174683e3c74657874506174682073746172744f66667365743d222d353025222066696c6c3d2277686974652220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d22313070782220786c696e6b3a687265663d2223746578742d706174682d61223e3c6d61736b2069643d22666164652d646f776e22206d61736b436f6e74656e74556e6974733d226f626a656374426f756e64696e67426f78223e3c726563742077696474683d223122206865696768743d2231222066696c6c3d2275726c2823677261642d646f776e2922202f3e3c2f6d61736b3e22207374726f6b653d2272676261283235352c3235352c3235352c3129222066696c6c3d226e6f6e6522207374726f6b652d6c696e656361703d22726f756e6422202f3e3c2f673e696e3d22626c656e644f75742220737464446576696174696f6e3d22343222202f3e3c2f66696c7465723e203c636c6970506174682069643d22636f726e657273223e3c726563742077696474683d2232393022206865696768743d22353030222072783d223432222072793d22343222202f3e3c2f636c6970506174683e203c67207374796c653d227472616e73666f726d3a7472616e736c61746528323970782c20333834707829223e3c6c696e6561724772616469656e742069643d22677261642d7570222078313d2231222078323d2230222079313d2231222079323d2230223e3c73746f70206f66667365743d22302e30222073746f702d636f6c6f723d227768697465222073746f702d6f7061636974793d223122202f3e32334c31302e323138312031332e373831394c312e363037372031384c392e35363538372031322e363532324c302031324c392e35363538372031312e333437384c312e3630373720364c31302e323138312031302e323138314c3620312e363037374c31312e3334373820392e35363538374c313220305a222066696c6c3d22776869746522202f3e3c67207374796c653d227472616e73666f726d3a7472616e736c6174652832323670782c20333932707829223e3c726563742077696474683d223336707822206865696768743d2233367078222072783d22387078222072793d22387078222066696c6c3d226e6f6e6522207374726f6b653d2272676261283235352c3235352c3235352c302e322922202f3e3c74657874506174682073746172744f66667365743d22353025222066696c6c3d2277686974652220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d22313070782220786c696e6b3a687265663d2223746578742d706174682d61223e3c7465787420783d22313270782220793d22313770782220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d2231327078222066696c6c3d227768697465223e3c747370616e2066696c6c3d2272676261283235352c3235352c3235352c302e3629223e4d6178205469636b3a203c2f747370616e3e3c616e696d6174655472616e73666f726d206174747269627574654e616d653d227472616e73666f726d2220747970653d22726f74617465222066726f6d3d22302031382031382220746f3d2233363020313820313822206475723d223130732220726570656174436f756e743d22696e646566696e697465222f3e3c2f673e3c2f673e3c706174682069643d22746578742d706174682d612220643d224d34302031322048323530204132382032382030203020312032373820343020563436302041323820323820302030203120323530203438382048343020413238203238203020302031203132203436302056343020413238203238203020302031203430203132207a22202f3e222f3e3c6665496d61676520726573756c743d2270312220786c696e6b3a687265663d22646174613a696d6167652f7376672b786d6c3b6261736536342c3c6d61736b2069643d22666164652d73796d626f6c22206d61736b436f6e74656e74556e6974733d227573657253706163654f6e557365223e3c726563742077696474683d22323930707822206865696768743d223230307078222066696c6c3d2275726c2823677261642d73796d626f6c2922202f3e3c2f6d61736b3e3c2f646566733e3c7265637420783d22302220793d2230222077696474683d2232393022206865696768743d22353030222072783d223432222072793d223432222066696c6c3d227267626128302c302c302c302922207374726f6b653d2272676261283235352c3235352c3235352c302e322922202f3e3c2f673e3c66696c7465722069643d22746f702d726567696f6e2d626c7572223e3c6665476175737369616e426c757220696e3d22536f75726365477261706869632220737464446576696174696f6e3d22323422202f3e3c2f66696c7465723e3c2f74657874506174683e203c74657874506174682073746172744f66667365743d223025222066696c6c3d2277686974652220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d22313070782220786c696e6b3a687265663d2223746578742d706174682d61223e3c7465787420746578742d72656e646572696e673d226f7074696d697a655370656564223e5369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f773c7265637420783d2231362220793d223136222077696474683d2232353822206865696768743d22343638222072783d223236222072793d223236222066696c6c3d227267626128302c302c302c302922207374726f6b653d2272676261283235352c3235352c3235352c302e322922202f3e3c7465787420783d22313270782220793d22313770782220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d2231327078222066696c6c3d227768697465223e3c747370616e2066696c6c3d2272676261283235352c3235352c3235352c302e3629223e49443a203c2f747370616e3e3c726563742077696474683d223336707822206865696768743d2233367078222072783d22387078222072793d22387078222066696c6c3d226e6f6e6522207374726f6b653d2272676261283235352c3235352c3235352c302e322922202f3e3c2f746578743e3c7465787420793d2231313570782220783d2233327078222066696c6c3d2277686974652220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d7765696768743d223230302220666f6e742d73697a653d2233367078223e3c2f746578743e3c2f673e3c67207374796c653d227472616e73666f726d3a7472616e736c6174652832323670782c20343333707829223e203c67207374796c653d227472616e73666f726d3a7472616e736c61746528323970782c20343134707829223ea164736f6c6343000706000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {INonfungiblePositionManager} from '../../protocols/v3-periphery/interfaces/INonfungiblePositionManager.sol'; library NonfungiblePositionManagerDeployer { function deploy(address factory, address weth9, address tokenDescriptor) internal returns (INonfungiblePositionManager manager) { bytes memory args = abi.encode(factory, weth9, tokenDescriptor); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { manager := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v3-periphery/contracts/NonfungiblePositionManager.sol */ function initcode() internal pure returns (bytes memory) { return hex'610120604052600d80546001600160b01b0319166001176001600160b01b0316600160b01b1790553480156200003457600080fd5b50604051620062e9380380620062e98339810160408190526200005791620002db565b82826040518060400160405280601b81526020017f556e697377617020563320506f736974696f6e73204e46542d563100000000008152506040518060400160405280600a815260200169554e492d56332d504f5360b01b815250604051806040016040528060018152602001603160f81b8152508282620000e66301ffc9a760e01b6200018d60201b60201c565b8151620000fb90600690602085019062000212565b5080516200011190600790602084019062000212565b50620001246380ac58cd60e01b6200018d565b62000136635b5e139f60e01b6200018d565b6200014863780e9d6360e01b6200018d565b50508251602093840120608052805192019190912060a052506001600160601b0319606092831b811660c05290821b811660e05291901b166101005250620003249050565b6001600160e01b03198082161415620001ed576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152602081905260409020805460ff19166001179055565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826200024a576000855562000295565b82601f106200026557805160ff191683800117855562000295565b8280016001018555821562000295579182015b828111156200029557825182559160200191906001019062000278565b50620002a3929150620002a7565b5090565b5b80821115620002a35760008155600101620002a8565b80516001600160a01b0381168114620002d657600080fd5b919050565b600080600060608486031215620002f0578283fd5b620002fb84620002be565b92506200030b60208501620002be565b91506200031b60408501620002be565b90509250925092565b60805160a05160c05160601c60e05160601c6101005160601c615f40620003a960003980612a835250806102995280611718528061180e52806118965280613e5d5280613ea35280613f17525080610aa75280610dde5280610ea55280612a1d5280612b235280612e4452806136e15250806114ff5250806114de5250615f406000f3fe6080604052600436106102895760003560e01c80636352211e11610153578063ac9650d8116100cb578063d34879971161007f578063e985e9c511610064578063e985e9c5146106f5578063f3995c6714610715578063fc6f7865146107285761030d565b8063d3487997146106c2578063df2ab5bb146106e25761030d565b8063c2e3140a116100b0578063c2e3140a1461067a578063c45a01551461068d578063c87b56dd146106a25761030d565b8063ac9650d81461063a578063b88d4fde1461065a5761030d565b8063883164561161012257806399fbab881161010757806399fbab88146105cf578063a22cb46514610607578063a4a78f0c146106275761030d565b8063883164561461059757806395d89b41146105ba5761030d565b80636352211e1461052f5780636c0360eb1461054f57806370a08231146105645780637ac2ff7b146105845761030d565b806323b872dd1161020157806342966c68116101b557806349404b7c1161019a57806349404b7c146104e75780634aa4a4fc146104fa5780634f6ccce71461050f5761030d565b806342966c68146104c15780634659a494146104d45761030d565b806330adf81f116101e657806330adf81f146104775780633644e5151461048c57806342842e0e146104a15761030d565b806323b872dd146104375780632f745c59146104575761030d565b80630c49ccbe1161025857806313ead5621161023d57806313ead562146103e057806318160ddd146103f3578063219f5d17146104155761030d565b80630c49ccbe146103b757806312210e8a146103d85761030d565b806301ffc9a71461031257806306fdde0314610348578063081812fc1461036a578063095ea7b3146103975761030d565b3661030d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461030b576040805162461bcd60e51b815260206004820152600960248201527f4e6f742057455448390000000000000000000000000000000000000000000000604482015290519081900360640190fd5b005b600080fd5b34801561031e57600080fd5b5061033261032d3660046153a6565b61073b565b60405161033f919061591e565b60405180910390f35b34801561035457600080fd5b5061035d610776565b60405161033f9190615971565b34801561037657600080fd5b5061038a6103853660046156b8565b61080c565b60405161033f91906157e2565b3480156103a357600080fd5b5061030b6103b2366004615270565b610868565b6103ca6103c5366004615483565b61093e565b60405161033f929190615b42565b61030b610daa565b61038a6103ee366004615103565b610dbc565b3480156103ff57600080fd5b506104086110c9565b60405161033f9190615929565b610428610423366004615494565b6110da565b60405161033f93929190615afd565b34801561044357600080fd5b5061030b61045236600461515c565b611413565b34801561046357600080fd5b50610408610472366004615270565b61146a565b34801561048357600080fd5b50610408611495565b34801561049857600080fd5b506104086114b9565b3480156104ad57600080fd5b5061030b6104bc36600461515c565b611577565b61030b6104cf3660046156b8565b611592565b61030b6104e23660046152dc565b611661565b61030b6104f53660046156d0565b611714565b34801561050657600080fd5b5061038a611894565b34801561051b57600080fd5b5061040861052a3660046156b8565b6118b8565b34801561053b57600080fd5b5061038a61054a3660046156b8565b6118ce565b34801561055b57600080fd5b5061035d6118f6565b34801561057057600080fd5b5061040861057f3660046150af565b6118fb565b61030b6105923660046152dc565b611963565b6105aa6105a5366004615550565b611e0f565b60405161033f9493929190615b1e565b3480156105c657600080fd5b5061035d612370565b3480156105db57600080fd5b506105ef6105ea3660046156b8565b6123d1565b60405161033f9c9b9a99989796959493929190615b50565b34801561061357600080fd5b5061030b610622366004615243565b612600565b61030b6106353660046152dc565b612723565b61064d610648366004615337565b6127d5565b60405161033f91906158a0565b34801561066657600080fd5b5061030b61067536600461519c565b612915565b61030b6106883660046152dc565b612973565b34801561069957600080fd5b5061038a612a1b565b3480156106ae57600080fd5b5061035d6106bd3660046156b8565b612a3f565b3480156106ce57600080fd5b5061030b6106dd366004615717565b612b0e565b61030b6106f036600461529b565b612b8c565b34801561070157600080fd5b506103326107103660046150cb565b612c6f565b61030b6107233660046152dc565b612c9d565b6103ca61073636600461546c565b612d28565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526020819052604090205460ff165b919050565b60068054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108025780601f106107d757610100808354040283529160200191610802565b820191906000526020600020905b8154815290600101906020018083116107e557829003601f168201915b5050505050905090565b600061081782613246565b61083c5760405162461bcd60e51b8152600401610833906159bb565b60405180910390fd5b506000908152600c60205260409020546c0100000000000000000000000090046001600160a01b031690565b6000610873826118ce565b9050806001600160a01b0316836001600160a01b031614156108c65760405162461bcd60e51b8152600401808060200182810382526021815260200180615ee26021913960400191505060405180910390fd5b806001600160a01b03166108d8613253565b6001600160a01b031614806108f457506108f481610710613253565b61092f5760405162461bcd60e51b8152600401808060200182810382526038815260200180615e0c6038913960400191505060405180910390fd5b6109398383613257565b505050565b600080823561094d33826132db565b6109695760405162461bcd60e51b815260040161083390615984565b836080013580610977613377565b11156109ca576040805162461bcd60e51b815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b60006109dc6040870160208801615562565b6001600160801b0316116109ef57600080fd5b84356000908152600c602090815260409182902060018101549092600160801b9091046001600160801b031691610a2a918901908901615562565b6001600160801b0316816001600160801b03161015610a4857600080fd5b60018281015469ffffffffffffffffffff166000908152600b60209081526040808320815160608101835281546001600160a01b039081168252919095015490811692850192909252600160a01b90910462ffffff1690830152610acc7f00000000000000000000000000000000000000000000000000000000000000008361337b565b60018501549091506001600160a01b0382169063a34123a7906a01000000000000000000008104600290810b91600160681b9004900b610b1260408e0160208f01615562565b6040518463ffffffff1660e01b8152600401610b309392919061594b565b6040805180830381600087803b158015610b4957600080fd5b505af1158015610b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8191906156f4565b909850965060408901358810801590610b9e575088606001358710155b610bba5760405162461bcd60e51b815260040161083390615a18565b6001840154600090610bea9030906a01000000000000000000008104600290810b91600160681b9004900b613477565b9050600080836001600160a01b031663514ea4bf846040518263ffffffff1660e01b8152600401610c1b9190615929565b60a06040518083038186803b158015610c3357600080fd5b505afa158015610c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6b91906155ac565b50509250925050610c9087600201548303876001600160801b0316600160801b6134d1565b6004880180546fffffffffffffffffffffffffffffffff198116928e016001600160801b039182160181169290921790556003880154610cda91908303908816600160801b6134d1565b6004880180546001600160801b03808216938e01600160801b9283900482160116029190911790556002870182905560038701819055610d2060408d0160208e01615562565b86038760010160106101000a8154816001600160801b0302191690836001600160801b031602179055508b600001357f26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b48d6020016020810190610d839190615562565b8d8d604051610d9493929190615afd565b60405180910390a2505050505050505050915091565b4715610dba57610dba3347613580565b565b6000836001600160a01b0316856001600160a01b031610610ddc57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018262ffffff168152602001935050505060206040518083038186803b158015610e6757600080fd5b505afa158015610e7b573d6000803e3d6000fd5b505050506040513d6020811015610e9157600080fd5b505190506001600160a01b038116610fe0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a16712958686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018262ffffff1681526020019350505050602060405180830381600087803b158015610f3057600080fd5b505af1158015610f44573d6000803e3d6000fd5b505050506040513d6020811015610f5a57600080fd5b5051604080517ff637731d0000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015291519293509083169163f637731d9160248082019260009290919082900301818387803b158015610fc357600080fd5b505af1158015610fd7573d6000803e3d6000fd5b505050506110c1565b6000816001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561101b57600080fd5b505afa15801561102f573d6000803e3d6000fd5b505050506040513d60e081101561104557600080fd5b505190506001600160a01b0381166110bf57816001600160a01b031663f637731d846040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156110a657600080fd5b505af11580156110ba573d6000803e3d6000fd5b505050505b505b949350505050565b60006110d56002613689565b905090565b60008060008360a00135806110ed613377565b1115611140576040805162461bcd60e51b815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b84356000908152600c6020908152604080832060018082015469ffffffffffffffffffff81168652600b855283862084516060808201875282546001600160a01b039081168352929094015480831682890190815262ffffff600160a01b9092048216838901908152885161014081018a528451861681529151909416818a01529251168287015230828501526a01000000000000000000008304600290810b810b608080850191909152600160681b909404810b900b60a0830152958c013560c0820152938b013560e0850152908a0135610100840152890135610120830152929061122c90613694565b6001870154939a50919850965091506000906112669030906a01000000000000000000008104600290810b91600160681b9004900b613477565b9050600080836001600160a01b031663514ea4bf846040518263ffffffff1660e01b81526004016112979190615929565b60a06040518083038186803b1580156112af57600080fd5b505afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e791906155ac565b50509250925050611323866002015483038760010160109054906101000a90046001600160801b03166001600160801b0316600160801b6134d1565b6004870180546001600160801b0380821690930183166fffffffffffffffffffffffffffffffff19909116179055600387015460018801546113739291840391600160801b9182900416906134d1565b6004870180546001600160801b03600160801b80830482169094018116840291811691909117909155600288018490556003880183905560018801805483810483168e018316909302929091169190911790556040518b35907f3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f906113fd908d908d908d90615afd565b60405180910390a2505050505050509193909250565b61142461141e613253565b826132db565b61145f5760405162461bcd60e51b8152600401808060200182810382526031815260200180615f036031913960400191505060405180910390fd5b6109398383836138cf565b6001600160a01b038216600090815260016020526040812061148c9083613a1b565b90505b92915050565b7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad81565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611526613a27565b3060405160200180868152602001858152602001848152602001838152602001826001600160a01b031681526020019550505050505060405160208183030381529060405280519060200120905090565b61093983838360405180602001604052806000815250612915565b8061159d33826132db565b6115b95760405162461bcd60e51b815260040161083390615984565b6000828152600c602052604090206001810154600160801b90046001600160801b03161580156115f4575060048101546001600160801b0316155b801561161257506004810154600160801b90046001600160801b0316155b61162e5760405162461bcd60e51b815260040161083390615a86565b6000838152600c602052604081208181556001810182905560028101829055600381018290556004015561093983613a2b565b604080517f8fcbaf0c00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101879052606481018690526001608482015260ff851660a482015260c4810184905260e4810183905290516001600160a01b03881691638fcbaf0c9161010480830192600092919082900301818387803b1580156116f457600080fd5b505af1158015611708573d6000803e3d6000fd5b50505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561178357600080fd5b505afa158015611797573d6000803e3d6000fd5b505050506040513d60208110156117ad57600080fd5b5051905082811015611806576040805162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e742057455448390000000000000000000000000000604482015290519081900360640190fd5b8015610939577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561187257600080fd5b505af1158015611886573d6000803e3d6000fd5b505050506109398282613580565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806118c6600284613af8565b509392505050565b600061148f82604051806060016040528060298152602001615e6e6029913960029190613b16565b606090565b60006001600160a01b0382166119425760405162461bcd60e51b815260040180806020018281038252602a815260200180615e44602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061148f90613689565b8361196c613377565b11156119bf576040805162461bcd60e51b815260206004820152600e60248201527f5065726d69742065787069726564000000000000000000000000000000000000604482015290519081900360640190fd5b60006119c96114b9565b7f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad88886119f581613b23565b604080516020808201969096526001600160a01b03909416848201526060840192909252608083015260a08083018a90528151808403909101815260c0830182528051908401207f190100000000000000000000000000000000000000000000000000000000000060e084015260e283019490945261010280830194909452805180830390940184526101229091019052815191012090506000611a98876118ce565b9050806001600160a01b0316886001600160a01b03161415611aeb5760405162461bcd60e51b8152600401808060200182810382526027815260200180615d6f6027913960400191505060405180910390fd5b611af481613b62565b15611ccf576040805160208082018790528183018690527fff0000000000000000000000000000000000000000000000000000000000000060f889901b16606083015282516041818403018152606183018085527f1626ba7e0000000000000000000000000000000000000000000000000000000090526065830186815260858401948552815160a585015281516001600160a01b03871695631626ba7e958995919260c59091019185019080838360005b83811015611bbe578181015183820152602001611ba6565b50505050905090810190601f168015611beb5780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b158015611c0957600080fd5b505afa158015611c1d573d6000803e3d6000fd5b505050506040513d6020811015611c3357600080fd5b50517fffffffff00000000000000000000000000000000000000000000000000000000167f1626ba7e0000000000000000000000000000000000000000000000000000000014611cca576040805162461bcd60e51b815260206004820152600c60248201527f556e617574686f72697a65640000000000000000000000000000000000000000604482015290519081900360640190fd5b611dfb565b600060018387878760405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611d2b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611d93576040805162461bcd60e51b815260206004820152601160248201527f496e76616c6964207369676e6174757265000000000000000000000000000000604482015290519081900360640190fd5b816001600160a01b0316816001600160a01b031614611df9576040805162461bcd60e51b815260206004820152600c60248201527f556e617574686f72697a65640000000000000000000000000000000000000000604482015290519081900360640190fd5b505b611e058888613257565b5050505050505050565b60008060008084610140013580611e24613377565b1115611e77576040805162461bcd60e51b815260206004820152601360248201527f5472616e73616374696f6e20746f6f206f6c6400000000000000000000000000604482015290519081900360640190fd5b604080516101408101909152600090611f439080611e9860208b018b6150af565b6001600160a01b03168152602001896020016020810190611eb991906150af565b6001600160a01b03168152602001611ed760608b0160408c0161569e565b62ffffff168152306020820152604001611ef760808b0160608c016153e6565b60020b8152602001611f0f60a08b0160808c016153e6565b60020b81526020018960a0013581526020018960c0013581526020018960e001358152602001896101000135815250613694565b92975090955093509050611fb7611f6261014089016101208a016150af565b600d80547fffffffffffffffffffff000000000000000000000000000000000000000000008116600175ffffffffffffffffffffffffffffffffffffffffffff92831690810190921617909155975087613b68565b6000611fe230611fcd60808b0160608c016153e6565b611fdd60a08c0160808d016153e6565b613477565b9050600080836001600160a01b031663514ea4bf846040518263ffffffff1660e01b81526004016120139190615929565b60a06040518083038186803b15801561202b57600080fd5b505afa15801561203f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206391906155ac565b5050925092505060006120dc8560405180606001604052808e600001602081019061208e91906150af565b6001600160a01b031681526020018e60200160208101906120af91906150af565b6001600160a01b031681526020018e60400160208101906120d0919061569e565b62ffffff169052613c96565b905060405180610140016040528060006bffffffffffffffffffffffff16815260200160006001600160a01b031681526020018269ffffffffffffffffffff1681526020018c606001602081019061213491906153e6565b60020b815260200161214c60a08e0160808f016153e6565b60020b81526020018a6001600160801b0316815260200184815260200183815260200160006001600160801b0316815260200160006001600160801b0316815250600c60008c815260200190815260200160002060008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160006101000a81548169ffffffffffffffffffff021916908369ffffffffffffffffffff160217905550606082015181600101600a6101000a81548162ffffff021916908360020b62ffffff160217905550608082015181600101600d6101000a81548162ffffff021916908360020b62ffffff16021790555060a08201518160010160106101000a8154816001600160801b0302191690836001600160801b0316021790555060c0820151816002015560e082015181600301556101008201518160040160006101000a8154816001600160801b0302191690836001600160801b031602179055506101208201518160040160106101000a8154816001600160801b0302191690836001600160801b03160217905550905050897f3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f8a8a8a60405161235b93929190615afd565b60405180910390a25050505050509193509193565b60078054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108025780601f106107d757610100808354040283529160200191610802565b6000818152600c6020908152604080832081516101408101835281546bffffffffffffffffffffffff811682526001600160a01b036c010000000000000000000000009091041693810193909352600181015469ffffffffffffffffffff81169284018390526a01000000000000000000008104600290810b810b810b6060860152600160681b8204810b810b810b60808601526001600160801b03600160801b92839004811660a08701529083015460c0860152600383015460e0860152600490920154808316610100860152041661012083015282918291829182918291829182918291829182918291906124da5760405162461bcd60e51b815260040161083390615a4f565b6000600b6000836040015169ffffffffffffffffffff1669ffffffffffffffffffff1681526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160149054906101000a900462ffffff1662ffffff1662ffffff1681525050905081600001518260200151826000015183602001518460400151866060015187608001518860a001518960c001518a60e001518b61010001518c61012001519d509d509d509d509d509d509d509d509d509d509d509d50505091939597999b5091939597999b565b612608613253565b6001600160a01b0316826001600160a01b0316141561266e576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b806005600061267b613253565b6001600160a01b0390811682526020808301939093526040918201600090812091871680825291909352912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016921515929092179091556126dd613253565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523360048201523060248201529051600019916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b15801561278d57600080fd5b505afa1580156127a1573d6000803e3d6000fd5b505050506040513d60208110156127b757600080fd5b505110156127cd576127cd868686868686611661565b505050505050565b60608167ffffffffffffffff811180156127ee57600080fd5b5060405190808252806020026020018201604052801561282257816020015b606081526020019060019003908161280d5790505b50905060005b8281101561290e576000803086868581811061284057fe5b90506020028101906128529190615bef565b6040516128609291906157d2565b600060405180830381855af49150503d806000811461289b576040519150601f19603f3d011682016040523d82523d6000602084013e6128a0565b606091505b5091509150816128ec576044815110156128b957600080fd5b600481019050808060200190518101906128d39190615402565b60405162461bcd60e51b81526004016108339190615971565b808484815181106128f957fe5b60209081029190910101525050600101612828565b5092915050565b612926612920613253565b836132db565b6129615760405162461bcd60e51b8152600401808060200182810382526031815260200180615f036031913960400191505060405180910390fd5b61296d84848484613de6565b50505050565b604080517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152905186916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b1580156129db57600080fd5b505afa1580156129ef573d6000803e3d6000fd5b505050506040513d6020811015612a0557600080fd5b505110156127cd576127cd868686868686612c9d565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060612a4a82613246565b612a5357600080fd5b6040517fe9dc63750000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e9dc637590612aba9030908690600401615932565b60006040518083038186803b158015612ad257600080fd5b505afa158015612ae6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261148f9190810190615402565b6000612b1c828401846154a5565b9050612b4c7f00000000000000000000000000000000000000000000000000000000000000008260000151613e38565b508415612b67578051516020820151612b6791903388613e5b565b8315612b8557612b8581600001516020015182602001513387613e5b565b5050505050565b6000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612bdb57600080fd5b505afa158015612bef573d6000803e3d6000fd5b505050506040513d6020811015612c0557600080fd5b5051905082811015612c5e576040805162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420746f6b656e0000000000000000000000000000604482015290519081900360640190fd5b801561296d5761296d848383613feb565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b604080517fd505accf000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018790526064810186905260ff8516608482015260a4810184905260c4810183905290516001600160a01b0388169163d505accf9160e480830192600092919082900301818387803b1580156116f457600080fd5b6000808235612d3733826132db565b612d535760405162461bcd60e51b815260040161083390615984565b6000612d656060860160408701615562565b6001600160801b03161180612d9257506000612d876080860160608701615562565b6001600160801b0316115b612d9b57600080fd5b600080612dae60408701602088016150af565b6001600160a01b031614612dd157612dcc60408601602087016150af565b612dd3565b305b85356000908152600c6020908152604080832060018082015469ffffffffffffffffffff168552600b8452828520835160608101855281546001600160a01b039081168252919092015490811694820194909452600160a01b90930462ffffff169183019190915292935090612e697f00000000000000000000000000000000000000000000000000000000000000008361337b565b600484015460018501549192506001600160801b0380821692600160801b92839004821692900416156130865760018501546040517fa34123a70000000000000000000000000000000000000000000000000000000081526001600160a01b0385169163a34123a791612f00916a01000000000000000000008104600290810b92600160681b909204900b9060009060040161594b565b6040805180830381600087803b158015612f1957600080fd5b505af1158015612f2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5191906156f4565b5050600185015460009081906001600160a01b0386169063514ea4bf90612f969030906a01000000000000000000008104600290810b91600160681b9004900b613477565b6040518263ffffffff1660e01b8152600401612fb29190615929565b60a06040518083038186803b158015612fca57600080fd5b505afa158015612fde573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061300291906155ac565b5050925092505061303e876002015483038860010160109054906101000a90046001600160801b03166001600160801b0316600160801b6134d1565b84019350613077876003015482038860010160109054906101000a90046001600160801b03166001600160801b0316600160801b6134d1565b60028801929092556003870155015b6000806001600160801b0384166130a360608e0160408f01615562565b6001600160801b0316116130c6576130c160608d0160408e01615562565b6130c8565b835b836001600160801b03168d60600160208101906130e59190615562565b6001600160801b0316116131085761310360808e0160608f01615562565b61310a565b835b60018901546040517f4f1eb3d80000000000000000000000000000000000000000000000000000000081529294509092506001600160a01b03871691634f1eb3d89161317d918c916a01000000000000000000008104600290810b92600160681b909204900b9088908890600401615839565b6040805180830381600087803b15801561319657600080fd5b505af11580156131aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ce919061557e565b6004890180546fffffffffffffffffffffffffffffffff196001600160801b03918216600160801b878a0384160217168689038216179091556040519281169d50169a508c35907f40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f0190610d94908b9086908690615876565b600061148f60028361417b565b3390565b6000818152600c6020526040902080546bffffffffffffffffffffffff166c010000000000000000000000006001600160a01b0385169081029190911790915581906132a2826118ce565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006132e682613246565b6133215760405162461bcd60e51b815260040180806020018281038252602c815260200180615de0602c913960400191505060405180910390fd5b600061332c836118ce565b9050806001600160a01b0316846001600160a01b031614806133675750836001600160a01b031661335c8461080c565b6001600160a01b0316145b806110c157506110c18185612c6f565b4290565b600081602001516001600160a01b031682600001516001600160a01b0316106133a357600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516bffffffffffffffffffffffff19606086901b16602080830191909152600285810b60e890811b60348501529085900b901b60378301528251601a818403018152603a90920190925280519101205b9392505050565b600080806000198587098686029250828110908390030390508061350757600084116134fc57600080fd5b5082900490506134ca565b80841161351357600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b602083106135cc5780518252601f1990920191602091820191016135ad565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461362e576040519150601f19603f3d011682016040523d82523d6000602084013e613633565b606091505b5050905080610939576040805162461bcd60e51b815260206004820152600360248201527f5354450000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600061148f82614187565b6000806000806000604051806060016040528087600001516001600160a01b0316815260200187602001516001600160a01b03168152602001876040015162ffffff1681525090506137067f00000000000000000000000000000000000000000000000000000000000000008261337b565b91506000826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561374357600080fd5b505afa158015613757573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377b919061560d565b50505050505090506000613792886080015161418b565b905060006137a38960a0015161418b565b90506137ba8383838c60c001518d60e001516144d9565b9750505050816001600160a01b0316633c8a7d8d876060015188608001518960a00151896040518060400160405280888152602001336001600160a01b031681525060405160200161380c9190615abd565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161383b9594939291906157f6565b6040805180830381600087803b15801561385457600080fd5b505af1158015613868573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061388c91906156f4565b610100880151919550935084108015906138ab57508561012001518310155b6138c75760405162461bcd60e51b815260040161083390615a18565b509193509193565b826001600160a01b03166138e2826118ce565b6001600160a01b0316146139275760405162461bcd60e51b8152600401808060200182810382526029815260200180615eb96029913960400191505060405180910390fd5b6001600160a01b03821661396c5760405162461bcd60e51b8152600401808060200182810382526024815260200180615d966024913960400191505060405180910390fd5b613977838383610939565b613982600082613257565b6001600160a01b03831660009081526001602052604090206139a4908261459d565b506001600160a01b03821660009081526001602052604090206139c790826145a9565b506139d4600282846145b5565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061148c83836145cb565b4690565b6000613a36826118ce565b9050613a4481600084610939565b613a4f600083613257565b6000828152600860205260409020546002600019610100600184161502019091160415613a8d576000828152600860205260408120613a8d9161501f565b6001600160a01b0381166000908152600160205260409020613aaf908361459d565b50613abb60028361462f565b5060405182906000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000808080613b07868661463b565b909450925050505b9250929050565b60006110c18484846146b6565b6000908152600c6020526040902080546bffffffffffffffffffffffff19811660016bffffffffffffffffffffffff9283169081019092161790915590565b3b151590565b6001600160a01b038216613bc3576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b613bcc81613246565b15613c1e576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b613c2a60008383610939565b6001600160a01b0382166000908152600160205260409020613c4c90826145a9565b50613c59600282846145b5565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001600160a01b0382166000908152600a602052604090205469ffffffffffffffffffff168061148f5750600d8054600169ffffffffffffffffffff76010000000000000000000000000000000000000000000080840482168381019092160275ffffffffffffffffffffffffffffffffffffffffffff909316929092179092556001600160a01b038085166000908152600a6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001686179055848352600b825291829020865181549085167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617825591870151950180549287015162ffffff16600160a01b027fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff969094169290911691909117939093161790915592915050565b613df18484846138cf565b613dfd84848484614780565b61296d5760405162461bcd60e51b8152600401808060200182810382526032815260200180615d3d6032913960400191505060405180910390fd5b6000613e44838361337b565b9050336001600160a01b0382161461148f57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316148015613e9c5750804710155b15613fbe577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015613efc57600080fd5b505af1158015613f10573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015613f8c57600080fd5b505af1158015613fa0573d6000803e3d6000fd5b505050506040513d6020811015613fb657600080fd5b5061296d9050565b6001600160a01b038316301415613fdf57613fda848383613feb565b61296d565b61296d8484848461495c565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781529251825160009485949389169392918291908083835b602083106140955780518252601f199092019160209182019101614076565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146140f7576040519150601f19603f3d011682016040523d82523d6000602084013e6140fc565b606091505b509150915081801561412a57508051158061412a575080806020019051602081101561412757600080fd5b50515b612b85576040805162461bcd60e51b815260206004820152600260248201527f5354000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600061148c8383614af4565b5490565b60008060008360020b126141a2578260020b6141aa565b8260020b6000035b9050620d89e8811115614204576040805162461bcd60e51b815260206004820152600160248201527f5400000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60006001821661421857600160801b61422a565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561425e576ffff97272373d413259a46990580e213a0260801c5b600482161561427d576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b600882161561429c576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b60108216156142bb576fffcb9843d60f6159c9db58835c9266440260801c5b60208216156142da576fff973b41fa98c081472e6896dfb254c00260801c5b60408216156142f9576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615614318576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615614338576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615614358576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615614378576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615614398576fe7159475a2c29b7443b29c7fa6e889d90260801c5b6110008216156143b8576fd097f3bdfd2022b8845ad8f792aa58250260801c5b6120008216156143d8576fa9f746462d870fdf8a65dc1f90e061e50260801c5b6140008216156143f8576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615614418576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615614439576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b62020000821615614459576e5d6af8dedb81196699c329225ee6040260801c5b62040000821615614478576d2216e584f5fa1ea926041bedfe980260801c5b62080000821615614495576b048a170391f7dc42444e8fa20260801c5b60008460020b13156144b05780600019816144ac57fe5b0490505b6401000000008106156144c45760016144c7565b60005b60ff16602082901c0192505050919050565b6000836001600160a01b0316856001600160a01b031611156144f9579293925b846001600160a01b0316866001600160a01b0316116145245761451d858585614b0c565b9050614594565b836001600160a01b0316866001600160a01b0316101561458657600061454b878686614b0c565b9050600061455a878986614b78565b9050806001600160801b0316826001600160801b03161061457b578061457d565b815b92505050614594565b614591858584614b78565b90505b95945050505050565b600061148c8383614bbe565b600061148c8383614c84565b60006110c184846001600160a01b038516614cce565b8154600090821061460d5760405162461bcd60e51b8152600401808060200182810382526022815260200180615d1b6022913960400191505060405180910390fd5b82600001828154811061461c57fe5b9060005260206000200154905092915050565b600061148c8383614d65565b81546000908190831061467f5760405162461bcd60e51b8152600401808060200182810382526022815260200180615e976022913960400191505060405180910390fd5b600084600001848154811061469057fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b600082815260018401602052604081205482816147515760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156147165781810151838201526020016146fe565b50505050905090810190601f1680156147435780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061476457fe5b9060005260206000209060020201600101549150509392505050565b6000614794846001600160a01b0316613b62565b6147a0575060016110c1565b60006148f17f150b7a02000000000000000000000000000000000000000000000000000000006147ce613253565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561483557818101518382015260200161481d565b50505050905090810190601f1680156148625780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001615d3d603291396001600160a01b0388169190614e39565b9050600081806020019051602081101561490a57600080fd5b50517fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001492505050949350505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000178152925182516000948594938a169392918291908083835b60208310614a0e5780518252601f1990920191602091820191016149ef565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614a70576040519150601f19603f3d011682016040523d82523d6000602084013e614a75565b606091505b5091509150818015614aa3575080511580614aa35750808060200190516020811015614aa057600080fd5b50515b6127cd576040805162461bcd60e51b815260206004820152600360248201527f5354460000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b60009081526001919091016020526040902054151590565b6000826001600160a01b0316846001600160a01b03161115614b2c579192915b6000614b58856001600160a01b0316856001600160a01b03166c010000000000000000000000006134d1565b9050614594614b7384838888036001600160a01b03166134d1565b614e48565b6000826001600160a01b0316846001600160a01b03161115614b98579192915b6110c1614b73836c010000000000000000000000008787036001600160a01b03166134d1565b60008181526001830160205260408120548015614c7a5783546000198083019190810190600090879083908110614bf157fe5b9060005260206000200154905080876000018481548110614c0e57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080614c3e57fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061148f565b600091505061148f565b6000614c908383614af4565b614cc65750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561148f565b50600061148f565b600082815260018401602052604081205480614d335750506040805180820182528381526020808201848152865460018181018955600089815284812095516002909302909501918255915190820155865486845281880190925292909120556134ca565b82856000016001830381548110614d4657fe5b90600052602060002090600202016001018190555060009150506134ca565b60008181526001830160205260408120548015614c7a5783546000198083019190810190600090879083908110614d9857fe5b9060005260206000209060020201905080876000018481548110614db857fe5b600091825260208083208454600290930201918255600193840154918401919091558354825289830190526040902090840190558654879080614df757fe5b600082815260208082206002600019909401938402018281556001908101839055929093558881528982019092526040822091909155945061148f9350505050565b60606110c18484600085614e5e565b806001600160801b038116811461077157600080fd5b606082471015614e9f5760405162461bcd60e51b8152600401808060200182810382526026815260200180615dba6026913960400191505060405180910390fd5b614ea885613b62565b614ef9576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b60208310614f375780518252601f199092019160209182019101614f18565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614f99576040519150601f19603f3d011682016040523d82523d6000602084013e614f9e565b606091505b5091509150614fae828286614fb9565b979650505050505050565b60608315614fc85750816134ca565b825115614fd85782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156147165781810151838201526020016146fe565b50805460018160011615610100020316600290046000825580601f106150455750615063565b601f0160209004906000526020600020908101906150639190615066565b50565b5b8082111561507b5760008155600101615067565b5090565b803561077181615cc4565b805161ffff8116811461077157600080fd5b803562ffffff8116811461077157600080fd5b6000602082840312156150c0578081fd5b81356134ca81615cc4565b600080604083850312156150dd578081fd5b82356150e881615cc4565b915060208301356150f881615cc4565b809150509250929050565b60008060008060808587031215615118578182fd5b843561512381615cc4565b9350602085013561513381615cc4565b92506151416040860161509c565b9150606085013561515181615cc4565b939692955090935050565b600080600060608486031215615170578081fd5b833561517b81615cc4565b9250602084013561518b81615cc4565b929592945050506040919091013590565b600080600080608085870312156151b1578182fd5b84356151bc81615cc4565b935060208501356151cc81615cc4565b925060408501359150606085013567ffffffffffffffff8111156151ee578182fd5b8501601f810187136151fe578182fd5b803561521161520c82615c76565b615c52565b818152886020838501011115615225578384fd5b81602084016020830137908101602001929092525092959194509250565b60008060408385031215615255578182fd5b823561526081615cc4565b915060208301356150f881615cd9565b60008060408385031215615282578182fd5b823561528d81615cc4565b946020939093013593505050565b6000806000606084860312156152af578081fd5b83356152ba81615cc4565b92506020840135915060408401356152d181615cc4565b809150509250925092565b60008060008060008060c087890312156152f4578384fd5b86356152ff81615cc4565b95506020870135945060408701359350606087013561531d81615d0b565b9598949750929560808101359460a0909101359350915050565b60008060208385031215615349578182fd5b823567ffffffffffffffff80821115615360578384fd5b818501915085601f830112615373578384fd5b813581811115615381578485fd5b8660208083028501011115615394578485fd5b60209290920196919550909350505050565b6000602082840312156153b7578081fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146134ca578182fd5b6000602082840312156153f7578081fd5b81356134ca81615ce7565b600060208284031215615413578081fd5b815167ffffffffffffffff811115615429578182fd5b8201601f81018413615439578182fd5b805161544761520c82615c76565b81815285602083850101111561545b578384fd5b614594826020830160208601615c98565b60006080828403121561547d578081fd5b50919050565b600060a0828403121561547d578081fd5b600060c0828403121561547d578081fd5b600081830360808112156154b7578182fd5b6040516040810167ffffffffffffffff82821081831117156154d557fe5b8160405260608412156154e6578485fd5b60a08301935081841081851117156154fa57fe5b50826040528435925061550c83615cc4565b91825260208401359161551e83615cc4565b8260608301526155306040860161509c565b608083015281526155436060850161507f565b6020820152949350505050565b6000610160828403121561547d578081fd5b600060208284031215615573578081fd5b81356134ca81615cf6565b60008060408385031215615590578182fd5b825161559b81615cf6565b60208401519092506150f881615cf6565b600080600080600060a086880312156155c3578283fd5b85516155ce81615cf6565b80955050602086015193506040860151925060608601516155ee81615cf6565b60808701519092506155ff81615cf6565b809150509295509295909350565b600080600080600080600060e0888a031215615627578485fd5b875161563281615cc4565b602089015190975061564381615ce7565b95506156516040890161508a565b945061565f6060890161508a565b935061566d6080890161508a565b925060a088015161567d81615d0b565b60c089015190925061568e81615cd9565b8091505092959891949750929550565b6000602082840312156156af578081fd5b61148c8261509c565b6000602082840312156156c9578081fd5b5035919050565b600080604083850312156156e2578182fd5b8235915060208301356150f881615cc4565b60008060408385031215615706578182fd5b505080516020909101519092909150565b6000806000806060858703121561572c578182fd5b8435935060208501359250604085013567ffffffffffffffff80821115615751578384fd5b818701915087601f830112615764578384fd5b813581811115615772578485fd5b886020828501011115615783578485fd5b95989497505060200194505050565b600081518084526157aa816020860160208601615c98565b601f01601f19169290920160200192915050565b60020b9052565b6001600160801b03169052565b6000828483379101908152919050565b6001600160a01b0391909116815260200190565b60006001600160a01b03871682528560020b60208301528460020b60408301526001600160801b038416606083015260a06080830152614fae60a0830184615792565b6001600160a01b03959095168552600293840b60208601529190920b60408401526001600160801b03918216606084015216608082015260a00190565b6001600160a01b039390931683526001600160801b03918216602084015216604082015260600190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015615911577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526158ff858351615792565b945092850192908501906001016158c5565b5092979650505050505050565b901515815260200190565b90815260200190565b6001600160a01b03929092168252602082015260400190565b600293840b81529190920b60208201526001600160801b03909116604082015260600190565b60006020825261148c6020830184615792565b6020808252600c908201527f4e6f7420617070726f7665640000000000000000000000000000000000000000604082015260600190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f507269636520736c69707061676520636865636b000000000000000000000000604082015260600190565b60208082526010908201527f496e76616c696420746f6b656e20494400000000000000000000000000000000604082015260600190565b6020808252600b908201527f4e6f7420636c6561726564000000000000000000000000000000000000000000604082015260600190565b815180516001600160a01b03908116835260208083015182168185015260409283015162ffffff1692840192909252920151909116606082015260800190565b6001600160801b039390931683526020830191909152604082015260600190565b9384526001600160801b039290921660208401526040830152606082015260800190565b918252602082015260400190565b6bffffffffffffffffffffffff8d1681526001600160a01b038c811660208301528b811660408301528a16606082015262ffffff89166080820152600288900b60a08201526101808101615ba760c08301896157be565b615bb460e08301886157c5565b8561010083015284610120830152615bd06101408301856157c5565b615bde6101608301846157c5565b9d9c50505050505050505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615c23578283fd5b83018035915067ffffffffffffffff821115615c3d578283fd5b602001915036819003821315613b0f57600080fd5b60405181810167ffffffffffffffff81118282101715615c6e57fe5b604052919050565b600067ffffffffffffffff821115615c8a57fe5b50601f01601f191660200190565b60005b83811015615cb3578181015183820152602001615c9b565b8381111561296d5750506000910152565b6001600160a01b038116811461506357600080fd5b801515811461506357600080fd5b8060020b811461506357600080fd5b6001600160801b038116811461506357600080fd5b60ff8116811461506357600080fdfe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724552433732315065726d69743a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e64734552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a164736f6c6343000706000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {INonfungibleTokenPositionDescriptor} from '../../protocols/v3-periphery/interfaces/INonfungibleTokenPositionDescriptor.sol'; import {NFTDescriptorDeployer} from './NFTDescriptorDeployer.sol'; library NonfungibleTokenPositionDescriptorDeployer { function deploy(address weth9, bytes32 nativeCurrencyLabelBytes) internal returns (INonfungibleTokenPositionDescriptor descriptor) { address nftDescriptor = NFTDescriptorDeployer.deploy(); bytes memory args = abi.encode(weth9, nativeCurrencyLabelBytes); bytes memory initcode_ = abi.encodePacked(initcode(nftDescriptor), args); assembly { descriptor := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v3-periphery/contracts/NonfungibleTokenPositionDescriptor.sol */ function initcode(address NFTDescriptor) internal pure returns (bytes memory) { return abi.encodePacked( hex'60c060405234801561001057600080fd5b5060405161158038038061158083398101604081905261002f9161004a565b60609190911b6001600160601b03191660805260a052610082565b6000806040838503121561005c578182fd5b82516001600160a01b0381168114610072578283fd5b6020939093015192949293505050565b60805160601c60a0516114bf6100c16000398061028f52806102c35280610377525080610107528061014c528061061a528061066e52506114bf6000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063a18246e211610050578063a18246e2146100d5578063b7af3cdc146100dd578063e9dc6375146100f257610072565b80634aa4a4fc146100775780637e5af771146100955780639d7b0ea8146100b5575b600080fd5b61007f610105565b60405161008c9190611311565b60405180910390f35b6100a86100a3366004611017565b610129565b60405161008c9190611325565b6100c86100c3366004611057565b610148565b60405161008c9190611330565b6100c861028d565b6100e56102b1565b60405161008c9190611339565b6100e5610100366004611057565b6103d7565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006101358383610148565b61013f8584610148565b13949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316141561018d5750606319610287565b8160011415610283576001600160a01b03831673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4814156101c4575061012c610287565b6001600160a01b03831673dac17f958d2ee523a2206206994597c13d831ec714156101f1575060c8610287565b6001600160a01b038316736b175474e89094c44da98b954eedeac495271d0f141561021e57506064610287565b6001600160a01b038316738daebade922df735c38c80c7ebd708af50815faa141561024c575060c719610287565b6001600160a01b038316732260fac5e5542a773aa44fbcfedf7c193bc2c599141561027b575061012b19610287565b506000610287565b5060005b92915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b606060005b60208110801561031657507f000000000000000000000000000000000000000000000000000000000000000081602081106102ed57fe5b1a60f81b7fff000000000000000000000000000000000000000000000000000000000000001615155b15610323576001016102b6565b60008167ffffffffffffffff8111801561033c57600080fd5b506040519080825280601f01601f191660200182016040528015610367576020820181803683370190505b50905060005b828110156103d0577f000000000000000000000000000000000000000000000000000000000000000081602081106103a157fe5b1a60f81b8282815181106103b157fe5b60200101906001600160f81b031916908160001a90535060010161036d565b5091505090565b60606000806000806000876001600160a01b03166399fbab88886040518263ffffffff1660e01b815260040161040d9190611330565b6101806040518083038186803b15801561042657600080fd5b505afa15801561043a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045e91906111dc565b5050505050965096509650965096505050600061051c896001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b1580156104ad57600080fd5b505afa1580156104c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e59190610ff4565b6040518060600160405280896001600160a01b03168152602001886001600160a01b031681526020018762ffffff168152506108e7565b9050600061052d87876100a36109e3565b90506000811561053d578761053f565b865b90506000821561054f5787610551565b885b90506000846001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561058e57600080fd5b505afa1580156105a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c69190611133565b505050505091505073', NFTDescriptor, hex'63c49917d7604051806101c001604052808f8152602001866001600160a01b03168152602001856001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b03161461065f5761065a876109e7565b610667565b6106676102b1565b81526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b0316146106b3576106ae866109e7565b6106bb565b6106bb6102b1565b8152602001866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f957600080fd5b505afa15801561070d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073191906111c2565b60ff168152602001856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561077257600080fd5b505afa158015610786573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107aa91906111c2565b60ff16815260200187151581526020018a60020b81526020018960020b81526020018460020b8152602001886001600160a01b031663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561080e57600080fd5b505afa158015610822573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108469190611082565b60020b81526020018b62ffffff168152602001886001600160a01b03168152506040518263ffffffff1660e01b8152600401610882919061134c565b60006040518083038186803b15801561089a57600080fd5b505af41580156108ae573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108d6919081019061109c565b9d9c50505050505050505050505050565b600081602001516001600160a01b031682600001516001600160a01b03161061090f57600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b4690565b60606000610a15837f95d89b4100000000000000000000000000000000000000000000000000000000610a3a565b9050805160001415610a3257610a2a83610c8f565b915050610a35565b90505b919050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000085161781529151815160609360009384936001600160a01b03891693919290918291908083835b60208310610ad35780518252601f199092019160209182019101610ab4565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114610b33576040519150601f19603f3d011682016040523d82523d6000602084013e610b38565b606091505b5091509150811580610b4957508051155b15610b67576040518060200160405280600081525092505050610287565b805160201415610b9f576000818060200190516020811015610b8857600080fd5b50519050610b9581610c9c565b9350505050610287565b604081511115610c7757808060200190516020811015610bbe57600080fd5b8101908080516040519392919084640100000000821115610bde57600080fd5b908301906020820185811115610bf357600080fd5b8251640100000000811182820188101715610c0d57600080fd5b82525081516020918201929091019080838360005b83811015610c3a578181015183820152602001610c22565b50505050905090810190601f168015610c675780820380516001836020036101000a031916815260200191505b5060405250505092505050610287565b50506040805160208101909152600081529392505050565b6060610a32826006610ddc565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b6020811015610d3e576000858260208110610cdc57fe5b1a60f81b90507fff00000000000000000000000000000000000000000000000000000000000000811615610d355780848481518110610d1757fe5b60200101906001600160f81b031916908160001a9053506001909201915b50600101610cc5565b5060008167ffffffffffffffff81118015610d5857600080fd5b506040519080825280601f01601f191660200182016040528015610d83576020820181803683370190505b50905060005b82811015610dd357838181518110610d9d57fe5b602001015160f81c60f81b828281518110610db457fe5b60200101906001600160f81b031916908160001a905350600101610d89565b50949350505050565b606060028206158015610def5750600082115b8015610dfc575060288211155b610e6757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f41646472657373537472696e675574696c3a20494e56414c49445f4c454e0000604482015290519081900360640190fd5b60008267ffffffffffffffff81118015610e8057600080fd5b506040519080825280601f01601f191660200182016040528015610eab576020820181803683370190505b5090506001600160a01b03841660005b60028504811015610f4f57600860138290030282901c600f600482901c1660f082168203610ee882610f59565b868560020281518110610ef757fe5b60200101906001600160f81b031916908160001a905350610f1781610f59565b868560020260010181518110610f2957fe5b60200101906001600160f81b031916908160001a9053505060019092019150610ebb9050565b5090949350505050565b6000600a8260ff161015610f7457506030810160f81b610a35565b506037810160f81b610a35565b8051610a358161149a565b8051600281900b8114610a3557600080fd5b80516fffffffffffffffffffffffffffffffff81168114610a3557600080fd5b805161ffff81168114610a3557600080fd5b805162ffffff81168114610a3557600080fd5b805160ff81168114610a3557600080fd5b600060208284031215611005578081fd5b81516110108161149a565b9392505050565b60008060006060848603121561102b578182fd5b83356110368161149a565b925060208401356110468161149a565b929592945050506040919091013590565b60008060408385031215611069578182fd5b82356110748161149a565b946020939093013593505050565b600060208284031215611093578081fd5b61101082610f8c565b6000602082840312156110ad578081fd5b815167ffffffffffffffff808211156110c4578283fd5b818401915084601f8301126110d7578283fd5b8151818111156110e357fe5b604051601f8201601f19168101602001838111828210171561110157fe5b604052818152838201602001871015611118578485fd5b61112982602083016020870161146a565b9695505050505050565b600080600080600080600060e0888a03121561114d578283fd5b87516111588161149a565b965061116660208901610f8c565b955061117460408901610fbe565b945061118260608901610fbe565b935061119060808901610fbe565b925061119e60a08901610fe3565b915060c088015180151581146111b2578182fd5b8091505092959891949750929550565b6000602082840312156111d3578081fd5b61101082610fe3565b6000806000806000806000806000806000806101808d8f0312156111fe578485fd5b8c516bffffffffffffffffffffffff81168114611219578586fd5b9b5061122760208e01610f81565b9a5061123560408e01610f81565b995061124360608e01610f81565b985061125160808e01610fd0565b975061125f60a08e01610f8c565b965061126d60c08e01610f8c565b955061127b60e08e01610f9e565b94506101008d015193506101208d0151925061129a6101408e01610f9e565b91506112a96101608e01610f9e565b90509295989b509295989b509295989b565b6001600160a01b03169052565b15159052565b60020b9052565b600081518084526112ed81602086016020860161146a565b601f01601f19169290920160200192915050565b62ffffff169052565b60ff169052565b6001600160a01b0391909116815260200190565b901515815260200190565b90815260200190565b60006020825261101060208301846112d5565b60006020825282516020830152602083015161136b60408401826112bb565b50604083015161137e60608401826112bb565b5060608301516101c080608085015261139b6101e08501836112d5565b91506080850151601f198584030160a08601526113b883826112d5565b92505060a08501516113cd60c086018261130a565b5060c08501516113e060e086018261130a565b5060e08501516101006113f5818701836112c8565b8601519050610120611409868201836112ce565b860151905061014061141d868201836112ce565b8601519050610160611431868201836112ce565b8601519050610180611445868201836112ce565b86015190506101a061145986820183611301565b8601519050610f4f858301826112bb565b60005b8381101561148557818101518382015260200161146d565b83811115611494576000848401525b50505050565b6001600160a01b03811681146114af57600080fd5b5056fea164736f6c6343000706000a' ); } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {IQuoterV2} from '../../protocols/v3-periphery/interfaces/IQuoterV2.sol'; library QuoterV2Deployer { function deploy(address factory, address weth9) internal returns (IQuoterV2 quoter) { bytes memory args = abi.encode(factory, weth9); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { quoter := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v3-periphery/contracts/lens/QuoterV2.sol */ function initcode() internal pure returns (bytes memory) { return hex'60c06040523480156200001157600080fd5b506040516200212c3803806200212c833981016040819052620000349162000070565b6001600160601b0319606092831b8116608052911b1660a052620000a7565b80516001600160a01b03811681146200006b57600080fd5b919050565b6000806040838503121562000083578182fd5b6200008e8362000053565b91506200009e6020840162000053565b90509250929050565b60805160601c60a05160601c612051620000db60003980610321525080610577528061095d5280610b9252506120516000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063c45a01551161005b578063c45a0155146100e6578063c6a5026a146100ee578063cdca175314610101578063fa461e33146101145761007d565b80632f80bb1d146100825780634aa4a4fc146100ae578063bd21704a146100c3575b600080fd5b610095610090366004611b2b565b610129565b6040516100a59493929190611eac565b60405180910390f35b6100b661031f565b6040516100a59190611def565b6100d66100d1366004611c49565b610343565b6040516100a59493929190611f54565b6100b6610575565b6100d66100fc366004611c49565b610599565b61009561010f366004611b2b565b610754565b610127610122366004611b91565b61092c565b005b6000606080600061013986610ae8565b67ffffffffffffffff8111801561014f57600080fd5b50604051908082528060200260200182016040528015610179578160200160208202803683370190505b50925061018586610ae8565b67ffffffffffffffff8111801561019b57600080fd5b506040519080825280602002602001820160405280156101c5578160200160208202803683370190505b50915060005b60008060006101d98a610b17565b92509250925060008060008061025c6040518060a001604052808873ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610343565b9350935093509350828b898151811061027157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106102b857fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926102e58e610b48565b156102fa576102f38e610b50565b9d5061030a565b8c9b505050505050505050610316565b505050505050506101cb565b92959194509250565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926103819290610b8b565b9050866080015173ffffffffffffffffffffffffffffffffffffffff16600014156103af5760408701516000555b60005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856103df8c60400151610bc9565b6000038c6080015173ffffffffffffffffffffffffffffffffffffffff1660001461040e578c60800151610434565b8761042d5773fffd8963efd1fc6a506488495d951d5263988d25610434565b6401000276a45b8d602001518e606001518f6000015160405160200161045593929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610484959493929190611e10565b6040805180830381600087803b15801561049d57600080fd5b505af19250505080156104eb575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526104e891810190611b6e565b60015b610568573d808015610519576040519150601f19603f3d011682016040523d82523d6000602084013e61051e565b606091505b505a82039450886080015173ffffffffffffffffffffffffffffffffffffffff166000141561054c57600080555b610557818487610bfb565b97509750975097505050505061056e565b50505050505b9193509193565b7f000000000000000000000000000000000000000000000000000000000000000081565b60208101518151606083015160009283928392839273ffffffffffffffffffffffffffffffffffffffff808216908416109284926105d79290610b8b565b905060005a90508173ffffffffffffffffffffffffffffffffffffffff1663128acb0830856106098c60400151610bc9565b60808d015173ffffffffffffffffffffffffffffffffffffffff1615610633578c60800151610659565b876106525773fffd8963efd1fc6a506488495d951d5263988d25610659565b6401000276a45b8d600001518e606001518f6020015160405160200161067a93929190611d89565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016106a9959493929190611e10565b6040805180830381600087803b1580156106c257600080fd5b505af1925050508015610710575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261070d91810190611b6e565b60015b610568573d80801561073e576040519150601f19603f3d011682016040523d82523d6000602084013e610743565b606091505b505a82039450610557818487610bfb565b6000606080600061076486610ae8565b67ffffffffffffffff8111801561077a57600080fd5b506040519080825280602002602001820160405280156107a4578160200160208202803683370190505b5092506107b086610ae8565b67ffffffffffffffff811180156107c657600080fd5b506040519080825280602002602001820160405280156107f0578160200160208202803683370190505b50915060005b60008060006108048a610b17565b9250925092506000806000806108876040518060a001604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018f81526020018762ffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815250610599565b9350935093509350828b898151811061089c57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818a89815181106108e357fe5b63ffffffff90921660209283029190910190910152929b50968201966001909601958b926109108e610b48565b156102fa5761091e8e610b50565b9d50505050505050506107f6565b600083138061093b5750600082135b61094457600080fd5b600080600061095284610b17565b9250925092506109847f0000000000000000000000000000000000000000000000000000000000000000848484610ccf565b5060008060008089136109ca578573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610888a6000036109ff565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161089896000035b9250925092506000610a12878787610b8b565b90506000808273ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610a5d57600080fd5b505afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611c6b565b5050505050915091508515610abb57604051848152826020820152816040820152606081fd5b60005415610ad1576000548414610ad157600080fd5b604051858152826020820152816040820152606081fd5b805160177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec909101045b919050565b60008080610b258482610cee565b9250610b32846014610dee565b9050610b3f846017610cee565b91509193909250565b516042111590565b8051606090610b859083906017907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901610ede565b92915050565b6000610bc17f0000000000000000000000000000000000000000000000000000000000000000610bbc8686866110c5565b611142565b949350505050565b60007f80000000000000000000000000000000000000000000000000000000000000008210610bf757600080fd5b5090565b6000806000806000808773ffffffffffffffffffffffffffffffffffffffff16633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610c4a57600080fd5b505afa158015610c5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c829190611c6b565b50939650610c9794508d935061127892505050565b91975095509050610cbf73ffffffffffffffffffffffffffffffffffffffff89168383611339565b9350869250505093509350935093565b6000610ce585610ce08686866110c5565b611991565b95945050505050565b600081826014011015610d6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f746f416464726573735f6f766572666c6f770000000000000000000000000000604482015290519081900360640190fd5b8160140183511015610dd557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e64730000000000000000000000604482015290519081900360640190fd5b5001602001516c01000000000000000000000000900490565b600081826003011015610e6257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f77000000000000000000000000000000604482015290519081900360640190fd5b8160030183511015610ed557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e6473000000000000000000000000604482015290519081900360640190fd5b50016003015190565b60608182601f011015610f5257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b828284011015610fc357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015290519081900360640190fd5b8183018451101561103557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015290519081900360640190fd5b60608215801561105457604051915060008252602082016040526110bc565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561108d578051835260209283019201611075565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6110cd6119fa565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161115611105579192915b506040805160608101825273ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015262ffffff169181019190915290565b6000816020015173ffffffffffffffffffffffffffffffffffffffff16826000015173ffffffffffffffffffffffffffffffffffffffff161061118457600080fd5b508051602080830151604093840151845173ffffffffffffffffffffffffffffffffffffffff94851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301207fff0000000000000000000000000000000000000000000000000000000000000060a085015294901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b60008060008351606014611318576044845110156112cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c290611e75565b60405180910390fd5b600484019350838060200190518101906112e59190611bdf565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c29190611e62565b8380602001905181019061132c9190611d02565b9250925092509193909250565b60008060008060008060008060088b73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561138d57600080fd5b505afa1580156113a1573d6000803e3d6000fd5b505050506040513d60208110156113b757600080fd5b5051600290810b908c900b816113c957fe5b0560020b901d905060006101008c73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561141c57600080fd5b505afa158015611430573d6000803e3d6000fd5b505050506040513d602081101561144657600080fd5b5051600290810b908d900b8161145857fe5b0560020b8161146357fe5b079050600060088d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114b057600080fd5b505afa1580156114c4573d6000803e3d6000fd5b505050506040513d60208110156114da57600080fd5b5051600290810b908d900b816114ec57fe5b0560020b901d905060006101008e73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561153f57600080fd5b505afa158015611553573d6000803e3d6000fd5b505050506040513d602081101561156957600080fd5b5051600290810b908e900b8161157b57fe5b0560020b8161158657fe5b07905060008160ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296856040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156115e757600080fd5b505afa1580156115fb573d6000803e3d6000fd5b505050506040513d602081101561161157600080fd5b5051161180156116a457508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561166257600080fd5b505afa158015611676573d6000803e3d6000fd5b505050506040513d602081101561168c57600080fd5b5051600290810b908d900b8161169e57fe5b0760020b155b80156116b557508b60020b8d60020b135b945060008360ff166001901b8f73ffffffffffffffffffffffffffffffffffffffff16635339c296876040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d602081101561173f57600080fd5b5051161180156117d257508d73ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561179057600080fd5b505afa1580156117a4573d6000803e3d6000fd5b505050506040513d60208110156117ba57600080fd5b5051600290810b908e900b816117cc57fe5b0760020b155b80156117e357508b60020b8d60020b125b95508160010b8460010b128061180f57508160010b8460010b14801561180f57508060ff168360ff1611155b1561182557839950829750819850809650611832565b8199508097508398508296505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff87161b9150505b8560010b8760010b13611969578560010b8760010b14156118a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ff858103161c165b6000818c73ffffffffffffffffffffffffffffffffffffffff16635339c2968a6040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b1580156118fa57600080fd5b505afa15801561190e573d6000803e3d6000fd5b505050506040513d602081101561192457600080fd5b5051169050611932816119c1565b61ffff16989098019750506001909501947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61185e565b8115611976576001880397505b8215611983576001880397505b505050505050509392505050565b600061199d8383611142565b90503373ffffffffffffffffffffffffffffffffffffffff821614610b8557600080fd5b6000805b8215610b85577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301909216916001016119c5565b604080516060810182526000808252602082018190529181019190915290565b600082601f830112611a2a578081fd5b8135611a3d611a3882611faf565b611f8b565b818152846020838601011115611a51578283fd5b816020850160208301379081016020019190915292915050565b8051600281900b8114610b1257600080fd5b600060a08284031215611a8e578081fd5b60405160a0810181811067ffffffffffffffff82111715611aab57fe5b6040529050808235611abc8161201f565b81526020830135611acc8161201f565b602082015260408381013590820152606083013562ffffff81168114611af157600080fd5b6060820152611b0260808401611b0e565b60808201525092915050565b8035610b128161201f565b805161ffff81168114610b1257600080fd5b60008060408385031215611b3d578182fd5b823567ffffffffffffffff811115611b53578283fd5b611b5f85828601611a1a565b95602094909401359450505050565b60008060408385031215611b80578182fd5b505080516020909101519092909150565b600080600060608486031215611ba5578081fd5b8335925060208401359150604084013567ffffffffffffffff811115611bc9578182fd5b611bd586828701611a1a565b9150509250925092565b600060208284031215611bf0578081fd5b815167ffffffffffffffff811115611c06578182fd5b8201601f81018413611c16578182fd5b8051611c24611a3882611faf565b818152856020838501011115611c38578384fd5b610ce5826020830160208601611fef565b600060a08284031215611c5a578081fd5b611c648383611a7d565b9392505050565b600080600080600080600060e0888a031215611c85578283fd5b8751611c908161201f565b9650611c9e60208901611a6b565b9550611cac60408901611b19565b9450611cba60608901611b19565b9350611cc860808901611b19565b925060a088015160ff81168114611cdd578283fd5b60c08901519092508015158114611cf2578182fd5b8091505092959891949750929550565b600080600060608486031215611d16578081fd5b835192506020840151611d288161201f565b9150611d3660408501611a6b565b90509250925092565b60008151808452611d57816020860160208601611fef565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606093841b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a06080830152611e5760a0830184611d3f565b979650505050505050565b600060208252611c646020830184611d3f565b60208082526010908201527f556e6578706563746564206572726f7200000000000000000000000000000000604082015260600190565b600060808201868352602060808185015281875180845260a0860191508289019350845b81811015611f0257845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101611ed0565b505084810360408601528651808252908201925081870190845b81811015611f3e57825163ffffffff1685529383019391830191600101611f1c565b5050505060609290920192909252949350505050565b93845273ffffffffffffffffffffffffffffffffffffffff92909216602084015263ffffffff166040830152606082015260800190565b60405181810167ffffffffffffffff81118282101715611fa757fe5b604052919050565b600067ffffffffffffffff821115611fc357fe5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b8381101561200a578181015183820152602001611ff2565b83811115612019576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461204157600080fd5b5056fea164736f6c6343000706000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {ISwapRouter} from '../../protocols/v3-periphery/interfaces/ISwapRouter.sol'; library SwapRouterDeployer { function deploy(address factory, address weth9) internal returns (ISwapRouter manager) { bytes memory args = abi.encode(factory, weth9); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { manager := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v3-periphery/contracts/SwapRouter.sol */ function initcode() internal pure returns (bytes memory) { return hex'60c06040526000196000553480156200001757600080fd5b5060405162002778380380620027788339810160408190526200003a9162000076565b6001600160601b0319606092831b8116608052911b1660a052620000ad565b80516001600160a01b03811681146200007157600080fd5b919050565b6000806040838503121562000089578182fd5b620000948362000059565b9150620000a46020840162000059565b90509250929050565b60805160601c60a05160601c61266f620001096000398061011252806104c752806105b2528061063f528061067f528061076a5280611721528061176752806117db525080610ba3528061109e52806118b6525061266f6000f3fe6080604052600436106101025760003560e01c8063c04b8d5911610095578063df2ab5bb11610064578063df2ab5bb14610284578063e0e189a014610297578063f28c0498146102aa578063f3995c67146102bd578063fa461e33146102d057610172565b8063c04b8d5914610236578063c2e3140a14610249578063c45a01551461025c578063db3e21981461027157610172565b80634aa4a4fc116100d15780634aa4a4fc146101ce5780639b2c0a37146101f0578063a4a78f0c14610203578063ac9650d81461021657610172565b806312210e8a14610177578063414bf3891461017f5780634659a494146101a857806349404b7c146101bb57610172565b3661017257336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610170576040805162461bcd60e51b81526020600482015260096024820152684e6f7420574554483960b81b604482015290519081900360640190fd5b005b600080fd5b6101706102f0565b61019261018d36600461222a565b610302565b60405161019f9190612583565b60405180910390f35b6101706101b6366004611fa8565b610429565b6101706101c9366004612331565b6104c3565b3480156101da57600080fd5b506101e361063d565b60405161019f9190612420565b6101706101fe366004612360565b610661565b610170610211366004611fa8565b61082d565b610229610224366004612008565b6108be565b60405161019f919061247a565b61019261024436600461217f565b6109fe565b610170610257366004611fa8565b610b12565b34801561026857600080fd5b506101e3610ba1565b61019261027f36600461222a565b610bc5565b610170610292366004611f09565b610cec565b6101706102a5366004611f4a565b610dca565b6101926102b8366004612246565b610ef1565b6101706102cb366004611fa8565b610fe7565b3480156102dc57600080fd5b506101706102eb36600461209a565b611059565b471561030057610300334761116c565b565b600081608001358061031261125b565b111561035b576040805162461bcd60e51b8152602060048201526013602482015272151c985b9cd858dd1a5bdb881d1bdbc81bdb19606a1b604482015290519081900360640190fd5b6103f460a08401356103736080860160608701611ee6565b610384610100870160e08801611ee6565b604080518082019091528061039c60208a018a611ee6565b6103ac60608b0160408c0161230e565b6103bc60408c0160208d01611ee6565b6040516020016103ce939291906123d5565b6040516020818303038152906040528152602001336001600160a01b031681525061125f565b91508260c001358210156104235760405162461bcd60e51b815260040161041a90612519565b60405180910390fd5b50919050565b604080516323f2ebc360e21b815233600482015230602482015260448101879052606481018690526001608482015260ff851660a482015260c4810184905260e4810183905290516001600160a01b03881691638fcbaf0c9161010480830192600092919082900301818387803b1580156104a357600080fd5b505af11580156104b7573d6000803e3d6000fd5b50505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561053257600080fd5b505afa158015610546573d6000803e3d6000fd5b505050506040513d602081101561055c57600080fd5b50519050828110156105aa576040805162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e7420574554483960701b604482015290519081900360640190fd5b8015610638577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561061657600080fd5b505af115801561062a573d6000803e3d6000fd5b50505050610638828261116c565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600082118015610672575060648211155b61067b57600080fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156106ea57600080fd5b505afa1580156106fe573d6000803e3d6000fd5b505050506040513d602081101561071457600080fd5b5051905084811015610762576040805162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e7420574554483960701b604482015290519081900360640190fd5b8015610826577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e1a7d4d826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156107ce57600080fd5b505af11580156107e2573d6000803e3d6000fd5b5050505060006127106107fe85846113b190919063ffffffff16565b8161080557fe5b049050801561081857610818838261116c565b6108248582840361116c565b505b5050505050565b60408051636eb1769f60e11b81523360048201523060248201529051600019916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b15801561087e57600080fd5b505afa158015610892573d6000803e3d6000fd5b505050506040513d60208110156108a857600080fd5b5051101561082457610824868686868686610429565b60608167ffffffffffffffff811180156108d757600080fd5b5060405190808252806020026020018201604052801561090b57816020015b60608152602001906001900390816108f65790505b50905060005b828110156109f7576000803086868581811061092957fe5b905060200281019061093b919061258c565b604051610949929190612410565b600060405180830381855af49150503d8060008114610984576040519150601f19603f3d011682016040523d82523d6000602084013e610989565b606091505b5091509150816109d5576044815110156109a257600080fd5b600481019050808060200190518101906109bc9190612115565b60405162461bcd60e51b815260040161041a91906124da565b808484815181106109e257fe5b60209081029190910101525050600101610911565b5092915050565b6000816040015180610a0e61125b565b1115610a57576040805162461bcd60e51b8152602060048201526013602482015272151c985b9cd858dd1a5bdb881d1bdbc81bdb19606a1b604482015290519081900360640190fd5b335b6000610a6885600001516113db565b9050610ab4856060015182610a81578660200151610a83565b305b60006040518060400160405280610a9d8b600001516113e7565b8152602001876001600160a01b031681525061125f565b60608601528015610ad4578451309250610acd906113f6565b8552610ae1565b8460600151935050610ae7565b50610a59565b8360800151831015610b0b5760405162461bcd60e51b815260040161041a90612519565b5050919050565b60408051636eb1769f60e11b8152336004820152306024820152905186916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b158015610b6157600080fd5b505afa158015610b75573d6000803e3d6000fd5b505050506040513d6020811015610b8b57600080fd5b5051101561082457610824868686868686610fe7565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000816080013580610bd561125b565b1115610c1e576040805162461bcd60e51b8152602060048201526013602482015272151c985b9cd858dd1a5bdb881d1bdbc81bdb19606a1b604482015290519081900360640190fd5b610cba60a0840135610c366080860160608701611ee6565b610c47610100870160e08801611ee6565b6040518060400160405280886020016020810190610c659190611ee6565b610c7560608b0160408c0161230e565b610c8260208c018c611ee6565b604051602001610c94939291906123d5565b6040516020818303038152906040528152602001336001600160a01b031681525061140d565b91508260c00135821115610ce05760405162461bcd60e51b815260040161041a906124ed565b50600019600055919050565b6000836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015610d3b57600080fd5b505afa158015610d4f573d6000803e3d6000fd5b505050506040513d6020811015610d6557600080fd5b5051905082811015610db3576040805162461bcd60e51b815260206004820152601260248201527124b739bab33334b1b4b2b73a103a37b5b2b760711b604482015290519081900360640190fd5b8015610dc457610dc4848383611588565b50505050565b600082118015610ddb575060648211155b610de457600080fd5b6000856001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015610e3357600080fd5b505afa158015610e47573d6000803e3d6000fd5b505050506040513d6020811015610e5d57600080fd5b5051905084811015610eab576040805162461bcd60e51b815260206004820152601260248201527124b739bab33334b1b4b2b73a103a37b5b2b760711b604482015290519081900360640190fd5b8015610824576000612710610ec083866113b1565b81610ec757fe5b0490508015610edb57610edb878483611588565b610ee88786838503611588565b50505050505050565b6000816040013580610f0161125b565b1115610f4a576040805162461bcd60e51b8152602060048201526013602482015272151c985b9cd858dd1a5bdb881d1bdbc81bdb19606a1b604482015290519081900360640190fd5b610fbd6060840135610f626040860160208701611ee6565b6040805180820190915260009080610f7a898061258c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252503360209091015261140d565b5060005491508260800135821115610ce05760405162461bcd60e51b815260040161041a906124ed565b6040805163d505accf60e01b8152336004820152306024820152604481018790526064810186905260ff8516608482015260a4810184905260c4810183905290516001600160a01b0388169163d505accf9160e480830192600092919082900301818387803b1580156104a357600080fd5b60008413806110685750600083135b61107157600080fd5b600061107f8284018461227e565b9050600080600061109384600001516116cf565b9250925092506110c57f0000000000000000000000000000000000000000000000000000000000000000848484611700565b5060008060008a136110ec57846001600160a01b0316846001600160a01b03161089611103565b836001600160a01b0316856001600160a01b0316108a5b9150915081156111225761111d858760200151338461171f565b6104b7565b855161112d906113db565b1561115257855161113d906113f6565b865261114c813360008961140d565b506104b7565b806000819055508394506104b7858760200151338461171f565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b602083106111b85780518252601f199092019160209182019101611199565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461121a576040519150601f19603f3d011682016040523d82523d6000602084013e61121f565b606091505b5050905080610638576040805162461bcd60e51b815260206004820152600360248201526253544560e81b604482015290519081900360640190fd5b4290565b60006001600160a01b038416611273573093505b600080600061128585600001516116cf565b919450925090506001600160a01b03808316908416106000806112a98686866118af565b6001600160a01b031663128acb088b856112c28f6118ed565b6001600160a01b038e16156112d7578d6112fd565b876112f65773fffd8963efd1fc6a506488495d951d5263988d256112fd565b6401000276a45b8d60405160200161130e9190612546565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161133d959493929190612434565b6040805180830381600087803b15801561135657600080fd5b505af115801561136a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138e9190612077565b915091508261139d578161139f565b805b6000039b9a5050505050505050505050565b60008215806113cc575050818102818382816113c957fe5b04145b6113d557600080fd5b92915050565b8051604211155b919050565b60606113d5826000602b611903565b80516060906113d590839060179060161901611903565b60006001600160a01b038416611421573093505b600080600061143385600001516116cf565b919450925090506001600160a01b03808416908316106000806114578587866118af565b6001600160a01b031663128acb088b856114708f6118ed565b6000036001600160a01b038e1615611488578d6114ae565b876114a75773fffd8963efd1fc6a506488495d951d5263988d256114ae565b6401000276a45b8d6040516020016114bf9190612546565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016114ee959493929190612434565b6040805180830381600087803b15801561150757600080fd5b505af115801561151b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153f9190612077565b9150915060008361155457818360000361155a565b82826000035b90985090506001600160a01b038a16611579578b811461157957600080fd5b50505050505050949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b602083106116045780518252601f1990920191602091820191016115e5565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611666576040519150601f19603f3d011682016040523d82523d6000602084013e61166b565b606091505b5091509150818015611699575080511580611699575080806020019051602081101561169657600080fd5b50515b610826576040805162461bcd60e51b815260206004820152600260248201526114d560f21b604482015290519081900360640190fd5b600080806116dd8482611a54565b92506116ea846014611b04565b90506116f7846017611a54565b91509193909250565b600061171685611711868686611bab565b611c01565b95945050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b03161480156117605750804710155b15611882577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156117c057600080fd5b505af11580156117d4573d6000803e3d6000fd5b50505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561185057600080fd5b505af1158015611864573d6000803e3d6000fd5b505050506040513d602081101561187a57600080fd5b50610dc49050565b6001600160a01b0383163014156118a35761189e848383611588565b610dc4565b610dc484848484611c24565b60006118e57f00000000000000000000000000000000000000000000000000000000000000006118e0868686611bab565b611d74565b949350505050565b6000600160ff1b82106118ff57600080fd5b5090565b60608182601f01101561194e576040805162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015290519081900360640190fd5b828284011015611996576040805162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015290519081900360640190fd5b818301845110156119e2576040805162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015290519081900360640190fd5b606082158015611a015760405191506000825260208201604052611a4b565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611a3a578051835260209283019201611a22565b5050858452601f01601f1916604052505b50949350505050565b600081826014011015611aa3576040805162461bcd60e51b8152602060048201526012602482015271746f416464726573735f6f766572666c6f7760701b604482015290519081900360640190fd5b8160140183511015611af4576040805162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b604482015290519081900360640190fd5b500160200151600160601b900490565b600081826003011015611b52576040805162461bcd60e51b8152602060048201526011602482015270746f55696e7432345f6f766572666c6f7760781b604482015290519081900360640190fd5b8160030183511015611ba2576040805162461bcd60e51b8152602060048201526014602482015273746f55696e7432345f6f75744f66426f756e647360601b604482015290519081900360640190fd5b50016003015190565b611bb3611e58565b826001600160a01b0316846001600160a01b03161115611bd1579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b6000611c0d8383611d74565b9050336001600160a01b038216146113d557600080fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b178152925182516000948594938a169392918291908083835b60208310611ca85780518252601f199092019160209182019101611c89565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611d0a576040519150601f19603f3d011682016040523d82523d6000602084013e611d0f565b606091505b5091509150818015611d3d575080511580611d3d5750808060200190516020811015611d3a57600080fd5b50515b610824576040805162461bcd60e51b815260206004820152600360248201526229aa2360e91b604482015290519081900360640190fd5b600081602001516001600160a01b031682600001516001600160a01b031610611d9c57600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301206001600160f81b031960a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b604080516060810182526000808252602082018190529181019190915290565b80356113e28161264a565b600082601f830112611e93578081fd5b8135611ea6611ea1826125fc565b6125d8565b818152846020838601011115611eba578283fd5b816020850160208301379081016020019190915292915050565b60006101008284031215610423578081fd5b600060208284031215611ef7578081fd5b8135611f028161264a565b9392505050565b600080600060608486031215611f1d578182fd5b8335611f288161264a565b9250602084013591506040840135611f3f8161264a565b809150509250925092565b600080600080600060a08688031215611f61578081fd5b8535611f6c8161264a565b9450602086013593506040860135611f838161264a565b9250606086013591506080860135611f9a8161264a565b809150509295509295909350565b60008060008060008060c08789031215611fc0578081fd5b8635611fcb8161264a565b95506020870135945060408701359350606087013560ff81168114611fee578182fd5b9598949750929560808101359460a0909101359350915050565b6000806020838503121561201a578182fd5b823567ffffffffffffffff80821115612031578384fd5b818501915085601f830112612044578384fd5b813581811115612052578485fd5b8660208083028501011115612065578485fd5b60209290920196919550909350505050565b60008060408385031215612089578182fd5b505080516020909101519092909150565b600080600080606085870312156120af578182fd5b8435935060208501359250604085013567ffffffffffffffff808211156120d4578384fd5b818701915087601f8301126120e7578384fd5b8135818111156120f5578485fd5b886020828501011115612106578485fd5b95989497505060200194505050565b600060208284031215612126578081fd5b815167ffffffffffffffff81111561213c578182fd5b8201601f8101841361214c578182fd5b805161215a611ea1826125fc565b81815285602083850101111561216e578384fd5b61171682602083016020860161261e565b600060208284031215612190578081fd5b813567ffffffffffffffff808211156121a7578283fd5b9083019060a082860312156121ba578283fd5b60405160a0810181811083821117156121cf57fe5b6040528235828111156121e0578485fd5b6121ec87828601611e83565b8252506121fb60208401611e78565b602082015260408301356040820152606083013560608201526080830135608082015280935050505092915050565b6000610100828403121561223c578081fd5b611f028383611ed4565b600060208284031215612257578081fd5b813567ffffffffffffffff81111561226d578182fd5b820160a08185031215611f02578182fd5b60006020828403121561228f578081fd5b813567ffffffffffffffff808211156122a6578283fd5b90830190604082860312156122b9578283fd5b6040516040810181811083821117156122ce57fe5b6040528235828111156122df578485fd5b6122eb87828601611e83565b825250602083013592506122fe8361264a565b6020810192909252509392505050565b60006020828403121561231f578081fd5b813562ffffff81168114611f02578182fd5b60008060408385031215612343578182fd5b8235915060208301356123558161264a565b809150509250929050565b60008060008060808587031215612375578182fd5b8435935060208501356123878161264a565b925060408501359150606085013561239e8161264a565b939692955090935050565b600081518084526123c181602086016020860161261e565b601f01601f19169290920160200192915050565b606093841b6bffffffffffffffffffffffff19908116825260e89390931b6001600160e81b0319166014820152921b166017820152602b0190565b6000828483379101908152919050565b6001600160a01b0391909116815260200190565b6001600160a01b0386811682528515156020830152604082018590528316606082015260a06080820181905260009061246f908301846123a9565b979650505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b828110156124cd57603f198886030184526124bb8583516123a9565b9450928501929085019060010161249f565b5092979650505050505050565b600060208252611f0260208301846123a9565b602080825260129082015271151bdbc81b5d58da081c995c5d595cdd195960721b604082015260600190565b602080825260139082015272151bdbc81b1a5d1d1b19481c9958d95a5d9959606a1b604082015260600190565b60006020825282516040602084015261256260608401826123a9565b602094909401516001600160a01b0316604093909301929092525090919050565b90815260200190565b6000808335601e198436030181126125a2578283fd5b83018035915067ffffffffffffffff8211156125bc578283fd5b6020019150368190038213156125d157600080fd5b9250929050565b60405181810167ffffffffffffffff811182821017156125f457fe5b604052919050565b600067ffffffffffffffff82111561261057fe5b50601f01601f191660200190565b60005b83811015612639578181015183820152602001612621565b83811115610dc45750506000910152565b6001600160a01b038116811461265f57600080fd5b5056fea164736f6c6343000706000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {ITickLens} from '../../protocols/v3-periphery/interfaces/ITickLens.sol'; library TickLensDeployer { function deploy() internal returns (ITickLens tickLens) { bytes memory initcode_ = abi.encodePacked(initcode()); assembly { tickLens := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v3-periphery/contracts/lens/TickLens.sol */ function initcode() internal pure returns (bytes memory) { return hex'608060405234801561001057600080fd5b50610569806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063351fb47814610030575b600080fd5b61004361003e36600461037c565b610059565b60405161005091906104aa565b60405180910390f35b606060008373ffffffffffffffffffffffffffffffffffffffff16635339c296846040518263ffffffff1660e01b8152600401610096919061051b565b60206040518083038186803b1580156100ae57600080fd5b505afa1580156100c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e69190610492565b90506000805b610100811015610110576001811b831615610108576001909101905b6001016100ec565b5060008573ffffffffffffffffffffffffffffffffffffffff1663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561015957600080fd5b505afa15801561016d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019191906103ba565b90508167ffffffffffffffff811180156101aa57600080fd5b506040519080825280602002602001820160405280156101e457816020015b6101d1610328565b8152602001906001900390816101c95790505b50935060005b61010081101561031e576001811b841615610316576040517ff30dba93000000000000000000000000000000000000000000000000000000008152600187900b60020b60081b8201830290600090819073ffffffffffffffffffffffffffffffffffffffff8b169063f30dba9390610266908690600401610529565b6101006040518083038186803b15801561027f57600080fd5b505afa158015610293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b791906103e2565b5050505050509150915060405180606001604052808460020b815260200182600f0b8152602001836fffffffffffffffffffffffffffffffff168152508887600190039750878151811061030757fe5b60200260200101819052505050505b6001016101ea565b5050505092915050565b604080516060810182526000808252602082018190529181019190915290565b8051801515811461035857600080fd5b919050565b805161035881610537565b805163ffffffff8116811461035857600080fd5b6000806040838503121561038e578182fd5b823561039981610537565b91506020830135600181900b81146103af578182fd5b809150509250929050565b6000602082840312156103cb578081fd5b81518060020b81146103db578182fd5b9392505050565b600080600080600080600080610100898b0312156103fe578384fd5b88516fffffffffffffffffffffffffffffffff8116811461041d578485fd5b80985050602089015180600f0b8114610434578485fd5b80975050604089015195506060890151945060808901518060060b8114610459578485fd5b935061046760a08a0161035d565b925061047560c08a01610368565b915061048360e08a01610348565b90509295985092959890939650565b6000602082840312156104a3578081fd5b5051919050565b602080825282518282018190526000919060409081850190868401855b8281101561050e578151805160020b855286810151600f0b878601528501516fffffffffffffffffffffffffffffffff1685850152606090930192908501906001016104c7565b5091979650505050505050565b60019190910b815260200190565b60029190910b815260200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461055957600080fd5b5056fea164736f6c6343000706000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; library UniswapInterfaceMulticallDeployer { function deploy() internal returns (address multicall) { bytes memory initcode_ = abi.encodePacked(initcode()); assembly { multicall := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v3-periphery/contracts/lens/UniswapInterfaceMulticall.sol */ function initcode() internal pure returns (bytes memory) { return hex'608060405234801561001057600080fd5b50610567806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80630f28c97d146100465780631749e1e3146100645780634d2301cc14610085575b600080fd5b61004e610098565b60405161005b919061041f565b60405180910390f35b6100776100723660046102a7565b61009c565b60405161005b929190610428565b61004e610093366004610286565b610220565b4290565b8051439060609067ffffffffffffffff811180156100b957600080fd5b506040519080825280602002602001820160405280156100f357816020015b6100e061023a565b8152602001906001900390816100d85790505b50905060005b835181101561021a57600080600086848151811061011357fe5b60200260200101516000015187858151811061012b57fe5b60200260200101516020015188868151811061014357fe5b60200260200101516040015192509250925060005a90506000808573ffffffffffffffffffffffffffffffffffffffff1685856040516101839190610403565b60006040518083038160008787f1925050503d80600081146101c1576040519150601f19603f3d011682016040523d82523d6000602084013e6101c6565b606091505b509150915060005a8403905060405180606001604052808415158152602001828152602001838152508989815181106101fb57fe5b60200260200101819052505050505050505080806001019150506100f9565b50915091565b73ffffffffffffffffffffffffffffffffffffffff163190565b604051806060016040528060001515815260200160008152602001606081525090565b803573ffffffffffffffffffffffffffffffffffffffff8116811461028157600080fd5b919050565b600060208284031215610297578081fd5b6102a08261025d565b9392505050565b600060208083850312156102b9578182fd5b823567ffffffffffffffff808211156102d0578384fd5b818501915085601f8301126102e3578384fd5b8135818111156102ef57fe5b6102fc8485830201610506565b81815284810190848601875b848110156103f457813587017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0606081838f03011215610346578a8bfd5b60408051606081018181108b8211171561035c57fe5b8252610369848d0161025d565b8152818401358c82015260608401358a811115610384578d8efd5b8085019450508e603f850112610398578c8dfd5b8b8401358a8111156103a657fe5b6103b68d85601f84011601610506565b93508084528f838287010111156103cb578d8efd5b808386018e86013783018c018d9052908101919091528552509287019290870190600101610308565b50909998505050505050505050565b6000825161041581846020870161052a565b9190910192915050565b90815260200190565b600060408083018584526020828186015281865180845260609350838701915083838202880101838901875b838110156104f6578983037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa001855281518051151584528681015187850152880151888401889052805188850181905260806104b582828801858c0161052a565b96880196601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01694909401909301925090850190600101610454565b50909a9950505050505050505050565b60405181810167ffffffffffffffff8111828210171561052257fe5b604052919050565b60005b8381101561054557818101518382015260200161052d565b83811115610554576000848401525b5050505056fea164736f6c6343000706000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {IV3Migrator} from '../../protocols/v3-periphery/interfaces/IV3Migrator.sol'; library V3MigratorDeployer { function deploy(address factory, address weth, address nonfungiblePositionManager) internal returns (IV3Migrator migrator) { bytes memory args = abi.encode(factory, weth, nonfungiblePositionManager); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { migrator := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v3-periphery/contracts/V3Migrator.sol */ function initcode() internal pure returns (bytes memory) { return hex'60e06040523480156200001157600080fd5b5060405162001a0d38038062001a0d833981016040819052620000349162000079565b6001600160601b0319606093841b811660805291831b821660a05290911b1660c052620000c2565b80516001600160a01b03811681146200007457600080fd5b919050565b6000806000606084860312156200008e578283fd5b62000099846200005c565b9250620000a9602085016200005c565b9150620000b9604085016200005c565b90509250925092565b60805160601c60a05160601c60c05160601c6118df6200012e600039806107735280610a3e5280610a785280610aa25280610c4b52508060a552806105765280610c975280610cee5280610dc95280610e2052508061020852806102cf528061082652506118df6000f3fe6080604052600436106100955760003560e01c8063b44a272211610059578063b44a272214610176578063c2e3140a1461018b578063c45a01551461019e578063d44f2bf2146101b3578063f3995c67146101d3576100ed565b806313ead562146100f25780634659a4941461011b5780634aa4a4fc1461012e578063a4a78f0c14610143578063ac9650d814610156576100ed565b366100ed57336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146100eb5760405162461bcd60e51b81526004016100e290611728565b60405180910390fd5b005b600080fd5b610105610100366004611325565b6101e6565b604051610112919061164f565b60405180910390f35b6100eb61012936600461137e565b6104da565b34801561013a57600080fd5b50610105610574565b6100eb61015136600461137e565b610598565b6101696101643660046113d7565b610631565b6040516101129190611687565b34801561018257600080fd5b50610105610771565b6100eb61019936600461137e565b610795565b3480156101aa57600080fd5b50610105610824565b3480156101bf57600080fd5b506100eb6101ce366004611536565b610848565b6100eb6101e136600461137e565b610eb4565b6000836001600160a01b0316856001600160a01b03161061020657600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631698ee828686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018262ffffff168152602001935050505060206040518083038186803b15801561029157600080fd5b505afa1580156102a5573d6000803e3d6000fd5b505050506040513d60208110156102bb57600080fd5b505190506001600160a01b0381166103f1577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a16712958686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018262ffffff1681526020019350505050602060405180830381600087803b15801561035a57600080fd5b505af115801561036e573d6000803e3d6000fd5b505050506040513d602081101561038457600080fd5b50516040805163f637731d60e01b81526001600160a01b03858116600483015291519293509083169163f637731d9160248082019260009290919082900301818387803b1580156103d457600080fd5b505af11580156103e8573d6000803e3d6000fd5b505050506104d2565b6000816001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561042c57600080fd5b505afa158015610440573d6000803e3d6000fd5b505050506040513d60e081101561045657600080fd5b505190506001600160a01b0381166104d057816001600160a01b031663f637731d846040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b1580156104b757600080fd5b505af11580156104cb573d6000803e3d6000fd5b505050505b505b949350505050565b604080516323f2ebc360e21b815233600482015230602482015260448101879052606481018690526001608482015260ff851660a482015260c4810184905260e4810183905290516001600160a01b03881691638fcbaf0c9161010480830192600092919082900301818387803b15801561055457600080fd5b505af1158015610568573d6000803e3d6000fd5b50505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60408051636eb1769f60e11b81523360048201523060248201529051600019916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b1580156105e957600080fd5b505afa1580156105fd573d6000803e3d6000fd5b505050506040513d602081101561061357600080fd5b50511015610629576106298686868686866104da565b505050505050565b60608167ffffffffffffffff8111801561064a57600080fd5b5060405190808252806020026020018201604052801561067e57816020015b60608152602001906001900390816106695790505b50905060005b8281101561076a576000803086868581811061069c57fe5b90506020028101906106ae9190611830565b6040516106bc92919061163f565b600060405180830381855af49150503d80600081146106f7576040519150601f19603f3d011682016040523d82523d6000602084013e6106fc565b606091505b5091509150816107485760448151101561071557600080fd5b6004810190508080602001905181019061072f919061149f565b60405162461bcd60e51b81526004016100e291906116e7565b8084848151811061075557fe5b60209081029190910101525050600101610684565b5092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60408051636eb1769f60e11b8152336004820152306024820152905186916001600160a01b0389169163dd62ed3e91604480820192602092909190829003018186803b1580156107e457600080fd5b505afa1580156107f8573d6000803e3d6000fd5b505050506040513d602081101561080e57600080fd5b5051101561062957610629868686868686610eb4565b7f000000000000000000000000000000000000000000000000000000000000000081565b600061085a60608301604084016115dc565b60ff161161087a5760405162461bcd60e51b81526004016100e2906116fa565b606461088c60608301604084016115dc565b60ff1611156108ad5760405162461bcd60e51b81526004016100e29061174b565b6108ba6020820182611302565b6001600160a01b03166323b872dd336108d66020850185611302565b84602001356040518463ffffffff1660e01b81526004016108f993929190611663565b602060405180830381600087803b15801561091357600080fd5b505af1158015610927573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094b9190611462565b5060008061095c6020840184611302565b6001600160a01b03166389afcb44306040518263ffffffff1660e01b8152600401610987919061164f565b6040805180830381600087803b1580156109a057600080fd5b505af11580156109b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d891906115b9565b9092509050600060646109fe6109f460608701604088016115dc565b859060ff16610f26565b81610a0557fe5b04905060006064610a1f6109f460608801604089016115dc565b81610a2657fe5b049050610a63610a3c6080870160608801611302565b7f000000000000000000000000000000000000000000000000000000000000000084610f50565b610a9d610a7660a0870160808801611302565b7f000000000000000000000000000000000000000000000000000000000000000083610f50565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663883164566040518061016001604052808a6060016020810190610aee9190611302565b6001600160a01b03168152602001610b0c60a08c0160808d01611302565b6001600160a01b03168152602001610b2a60c08c0160a08d0161154e565b62ffffff168152602001610b4460e08c0160c08d0161147e565b60020b8152602001610b5d6101008c0160e08d0161147e565b60020b815260208101889052604081018790526101008b013560608201526101208b0135608082015260a001610b9b6101608c016101408d01611302565b6001600160a01b031681526020018a61016001358152506040518263ffffffff1660e01b8152600401610bce9190611779565b608060405180830381600087803b158015610be857600080fd5b505af1158015610bfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c209190611568565b93509350505085821015610d805783821015610c7157610c71610c496080890160608a01611302565b7f00000000000000000000000000000000000000000000000000000000000000006000610f50565b818603610c866101a089016101808a01611446565b8015610cd257506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016610cc760808a0160608b01611302565b6001600160a01b0316145b15610d6457604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90610d23908490600401611827565b600060405180830381600087803b158015610d3d57600080fd5b505af1158015610d51573d6000803e3d6000fd5b50505050610d5f338261109e565b610d7e565b610d7e610d7760808a0160608b01611302565b3383611192565b505b84811015610eab5782811015610da357610da3610c4960a0890160808a01611302565b808503610db86101a089016101808a01611446565b8015610e0457506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016610df960a08a0160808b01611302565b6001600160a01b0316145b15610e9657604051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90610e55908490600401611827565b600060405180830381600087803b158015610e6f57600080fd5b505af1158015610e83573d6000803e3d6000fd5b50505050610e91338261109e565b610ea9565b610ea9610d7760a08a0160808b01611302565b505b50505050505050565b6040805163d505accf60e01b8152336004820152306024820152604481018790526064810186905260ff8516608482015260a4810184905260c4810183905290516001600160a01b0388169163d505accf9160e480830192600092919082900301818387803b15801561055457600080fd5b6000821580610f4157505081810281838281610f3e57fe5b04145b610f4a57600080fd5b92915050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1781529251825160009485949389169392918291908083835b60208310610fcc5780518252601f199092019160209182019101610fad565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461102e576040519150601f19603f3d011682016040523d82523d6000602084013e611033565b606091505b5091509150818015611061575080511580611061575080806020019051602081101561105e57600080fd5b50515b611097576040805162461bcd60e51b8152602060048201526002602482015261534160f01b604482015290519081900360640190fd5b5050505050565b604080516000808252602082019092526001600160a01b0384169083906040518082805190602001908083835b602083106110ea5780518252601f1990920191602091820191016110cb565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461114c576040519150601f19603f3d011682016040523d82523d6000602084013e611151565b606091505b505090508061118d576040805162461bcd60e51b815260206004820152600360248201526253544560e81b604482015290519081900360640190fd5b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b6020831061120e5780518252601f1990920191602091820191016111ef565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611270576040519150601f19603f3d011682016040523d82523d6000602084013e611275565b606091505b50915091508180156112a35750805115806112a357508080602001905160208110156112a057600080fd5b50515b611097576040805162461bcd60e51b815260206004820152600260248201526114d560f21b604482015290519081900360640190fd5b803562ffffff811681146112ec57600080fd5b919050565b803560ff811681146112ec57600080fd5b600060208284031215611313578081fd5b813561131e816118ac565b9392505050565b6000806000806080858703121561133a578283fd5b8435611345816118ac565b93506020850135611355816118ac565b9250611363604086016112d9565b91506060850135611373816118ac565b939692955090935050565b60008060008060008060c08789031215611396578182fd5b86356113a1816118ac565b955060208701359450604087013593506113bd606088016112f1565b92506080870135915060a087013590509295509295509295565b600080602083850312156113e9578182fd5b823567ffffffffffffffff80821115611400578384fd5b818501915085601f830112611413578384fd5b813581811115611421578485fd5b8660208083028501011115611434578485fd5b60209290920196919550909350505050565b600060208284031215611457578081fd5b813561131e816118c4565b600060208284031215611473578081fd5b815161131e816118c4565b60006020828403121561148f578081fd5b81358060020b811461131e578182fd5b6000602082840312156114b0578081fd5b815167ffffffffffffffff808211156114c7578283fd5b818401915084601f8301126114da578283fd5b8151818111156114e657fe5b604051601f8201601f19168101602001838111828210171561150457fe5b60405281815283820160200187101561151b578485fd5b61152c82602083016020870161187c565b9695505050505050565b60006101a08284031215611548578081fd5b50919050565b60006020828403121561155f578081fd5b61131e826112d9565b6000806000806080858703121561157d578384fd5b8451935060208501516fffffffffffffffffffffffffffffffff811681146115a3578384fd5b6040860151606090960151949790965092505050565b600080604083850312156115cb578182fd5b505080516020909101519092909150565b6000602082840312156115ed578081fd5b61131e826112f1565b6001600160a01b03169052565b6000815180845261161b81602086016020860161187c565b601f01601f19169290920160200192915050565b60020b9052565b62ffffff169052565b6000828483379101908152919050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000602080830181845280855180835260408601915060408482028701019250838701855b828110156116da57603f198886030184526116c8858351611603565b945092850192908501906001016116ac565b5092979650505050505050565b60006020825261131e6020830184611603565b60208082526014908201527314195c98d95b9d1859d9481d1bdbc81cdb585b1b60621b604082015260600190565b6020808252600990820152684e6f7420574554483960b81b604082015260600190565b60208082526014908201527350657263656e7461676520746f6f206c6172676560601b604082015260600190565b60006101608201905061178d8284516115f6565b602083015161179f60208401826115f6565b5060408301516117b26040840182611636565b5060608301516117c5606084018261162f565b5060808301516117d8608084018261162f565b5060a083015160a083015260c083015160c083015260e083015160e083015261010080840151818401525061012080840151611816828501826115f6565b505061014092830151919092015290565b90815260200190565b6000808335601e19843603018112611846578283fd5b83018035915067ffffffffffffffff821115611860578283fd5b60200191503681900382131561187557600080fd5b9250929050565b60005b8381101561189757818101518382015260200161187f565b838111156118a6576000848401525b50505050565b6001600160a01b03811681146118c157600080fd5b50565b80151581146118c157600080fdfea164736f6c6343000706000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.0; import {IPoolManager} from '../../protocols/v4-core/interfaces/IPoolManager.sol'; library PoolManagerDeployer { function deploy(address initialOwner) internal returns (IPoolManager manager) { bytes memory args = abi.encode(initialOwner); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { manager := create2(0, add(initcode_, 32), mload(initcode_), hex'00') } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: lib/v4-core/src/PoolManager.sol */ function initcode() internal pure returns (bytes memory) { return hex'60a03460a057601f615e8238819003918201601f19168301916001600160401b0383118484101760a45780849260209460405283398101031260a057516001600160a01b0381169081900360a0575f80546001600160a01b0319168217815560405191907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a330608052615dc990816100b98239608051816135260152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60a0806040526004361015610012575f80fd5b5f3560e01c908162fdd58e14612cd55750806301ffc9a714612c16578063095bcdb614612b6c5780630b0d9c0914612ae057806311da60b414612a85578063156e29f6146129d55780631e2eaeaf1461299b578063234266d7146126fc5780632d7713891461265157806335fd631a146125dd5780633dd45adb14612579578063426a8493146124f557806348c894911461226a5780635275965114612152578063558a72971461207b578063598af9e714611fe35780635a6bcfda1461144f5780636276cbbe14610f965780637e87ce7d14610e5957806380f0b44c14610d875780638161b87414610c315780638da5cb5b14610be157806397e8cd4e14610b7e5780639bf6645f14610b31578063a584119414610a66578063b6363cf2146109d5578063dbd035ff1461097f578063f02de3b21461092e578063f135baaa146108f4578063f2fde38b14610848578063f3cd914c146104ff578063f5298aca146103345763fe99049a14610186575f80fd5b346103305760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610330576101bd612d3f565b6101c5612d62565b90604435917f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac72885961027973ffffffffffffffffffffffffffffffffffffffff80606435951693843314158061030d575b610287575b845f52600460205260405f20875f5260205260405f2061023a878254612fed565b90551693845f52600460205260405f20865f5260205260405f2061025f828254612ffa565b905560408051338152602081019290925290918291820190565b0390a4602060405160018152f35b845f52600560205260405f208233165f5260205260405f20875f5260205260405f2054867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036102da575b5050610219565b6102e391612fed565b855f52600560205260405f208333165f5260205260405f20885f5260205260405f20555f866102d3565b50845f52600360205260405f208233165f5260205260ff60405f20541615610214565b5f80fd5b346103305761034236612d85565b7fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c156104d7577f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac7288596103ed73ffffffffffffffffffffffffffffffffffffffff805f9516956103bb6103b3866130aa565b3390896130f0565b169233841415806104a0575b6103f2575b8385526004602052604085208686526020526040852061025f828254612fed565b0390a4005b83855260056020526040852073ffffffffffffffffffffffffffffffffffffffff33168652602052604085208686526020526040852054817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610459575b50506103cc565b61046291612fed565b84865260056020526040862073ffffffffffffffffffffffffffffffffffffffff331687526020526040862087875260205260408620558681610452565b5083855260036020526040852073ffffffffffffffffffffffffffffffffffffffff3316865260205260ff604086205416156103c7565b7f54e3ca0d000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610330576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103305761053836612e81565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5c360112610330576040519061056f82612df6565b60a4358015158103610330578252602082019060c435825260e4359073ffffffffffffffffffffffffffffffffffffffff8216820361033057604084019182526101043567ffffffffffffffff8111610330576105d0903690600401612f4d565b9290937fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c156104d75761060261350f565b51156108205760a0822092835f52600660205260405f209061062382613576565b60808401958482828a8a5173ffffffffffffffffffffffffffffffffffffffff169361064e94613b44565b90949195606088015160020b908b511515905173ffffffffffffffffffffffffffffffffffffffff1691604051986106858a612e12565b895260208901526040880152606087015262ffffff166080860152885115155f149862ffffff6107a2986106db61078f9860209d6108005773ffffffffffffffffffffffffffffffffffffffff8b511695614959565b9492968291926107d3575b505073ffffffffffffffffffffffffffffffffffffffff845116938e6fffffffffffffffffffffffffffffffff60408301511691015160020b90604051958860801d600f0b875288600f0b60208801526040870152606086015260808501521660a08301527f40e9cecb9f5f1f1c5b9c97dec2917b7ee92e57ba5563708daca94dd84ad7112f60c03393a38673ffffffffffffffffffffffffffffffffffffffff8a5116613d81565b809491946107aa575b5050823391613652565b604051908152f35b73ffffffffffffffffffffffffffffffffffffffff6107cc9251169083613652565b8480610798565b73ffffffffffffffffffffffffffffffffffffffff165f5260018f5260405f209081540190558e806106e6565b73ffffffffffffffffffffffffffffffffffffffff8e8c01511695614959565b7fbe8b8507000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103305760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610330577fffffffffffffffffffffffff00000000000000000000000000000000000000006108a0612d3f565b73ffffffffffffffffffffffffffffffffffffffff5f54916108c58284163314613007565b1691829116175f55337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b346103305760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610330576004355c5f5260205ff35b34610330575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b346103305761098d36612f7b565b6040519160408360208152836020820152019160051b8301916020806040850193925b83355481520191019084838210156109cc5750602080916109b0565b60408186030190f35b346103305760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057610a0c612d3f565b73ffffffffffffffffffffffffffffffffffffffff610a29612d62565b91165f52600360205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f52602052602060ff60405f2054166040519015158152f35b346103305760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057610a9d612d3f565b73ffffffffffffffffffffffffffffffffffffffff81169081610ae15750505f7f27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b95d005b610aea90613a92565b907f27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b95d7f1e0745a7db1623981f0b2a5d4232364c00787266eb75ad546f190e6cebe9bd955d005b3461033057610b3f36612f7b565b6040519160408360208152836020820152019160051b8301916020806040850193925b83355c81520191019084838210156109cc575060208091610b62565b346103305760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103305773ffffffffffffffffffffffffffffffffffffffff610bca612d3f565b165f526001602052602060405f2054604051908152f35b34610330575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b346103305760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057610c68612d3f565b610c70612d62565b60443573ffffffffffffffffffffffffffffffffffffffff600254163303610d5f5773ffffffffffffffffffffffffffffffffffffffff821680151580610d1f575b610cf7576020936107a29280610cef5750815f526001855260405f20549384925b5f526001865260405f20610ce8848254612fed565b90556131f8565b938492610cd3565b7fc79e5948000000000000000000000000000000000000000000000000000000005f5260045ffd5b508073ffffffffffffffffffffffffffffffffffffffff7f27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b95c1614610cb2565b7f48f5c3ed000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103305760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057610dbe612d3f565b7fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c156104d757335f90815273ffffffffffffffffffffffffffffffffffffffff8216602052604090205c610e146024356130aa565b9081600f0b03610e3157610e2f9133915f03600f0b906130f0565b005b7fbda73abf000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103305760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057610e9136612e81565b610e99612e6f565b9073ffffffffffffffffffffffffffffffffffffffff600254163303610d5f57623e900062fff0008316106103e9610fff8416101615610f6557602060a07fe9c42593e71f84403b84352cd168d693e2c9fcd1fdbcc3feb21d92b43e6696f9922092835f526006825260405f20610f0f81613576565b805479ffffff00000000000000000000000000000000000000000000008360b81b16907fffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffff1617905562ffffff60405191168152a2005b62ffffff827fa7abe2f7000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b346103305760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057610fce36612e81565b60a4359073ffffffffffffffffffffffffffffffffffffffff821680830361033057610ff861350f565b6060820191825160020b617fff81136114245750825160020b600181126113f9575073ffffffffffffffffffffffffffffffffffffffff815116602082019073ffffffffffffffffffffffffffffffffffffffff825116808210156113c2575050608082019073ffffffffffffffffffffffffffffffffffffffff82511690604084019161108c62ffffff845116826139b7565b1561139757506110a162ffffff835116613a75565b96835173ffffffffffffffffffffffffffffffffffffffff8116908133036112e0575b505060a0852090815f52600660205260405f2090815473ffffffffffffffffffffffffffffffffffffffff166112b8576020997fdd466e674ea557f56295e2d0218a125ea4b4f0f6f3307b95f85e6110838d6438927cffffff000000000000000000000000000000000000000000000000000061114260a0946145fc565b9260d01b168a76ffffff000000000000000000000000000000000000000084861b161717905562ffffff73ffffffffffffffffffffffffffffffffffffffff808a5116965116965116995160020b73ffffffffffffffffffffffffffffffffffffffff885116906040519b8c528c8c015260408b01528860608b015260020b98896080820152a45173ffffffffffffffffffffffffffffffffffffffff8116908133036111f4575b8585604051908152f35b61100016611203575b806111ea565b6112af9261128d604051937f6fe7e6eb0000000000000000000000000000000000000000000000000000000088860152336024860152604485019073ffffffffffffffffffffffffffffffffffffffff6080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b60e48301528361010483015261010482526112aa61012483612e2e565b613f25565b508280806111fd565b7f7983c051000000000000000000000000000000000000000000000000000000005f5260045ffd5b612000166112ef575b806110c4565b61139090604051907fdc98354e00000000000000000000000000000000000000000000000000000000602083015233602483015261137a604483018973ffffffffffffffffffffffffffffffffffffffff6080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b8860e483015260e482526112aa61010483612e2e565b50886112e9565b7fe65af6a0000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b60449250604051917f6e6c983000000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b7fe9e90588000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7fb70024f8000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b34610330576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103305761148836612e81565b60807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5c36011261033057604051906114bf82612dda565b60a4358060020b810361033057825260c4358060020b810361033057602083015260e43560408301526101043560608301526101243567ffffffffffffffff811161033057611512903690600401612f4d565b90927fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c156104d75761154361350f565b60a0832093845f52600660205260405f20608052611562608051613576565b608084015173ffffffffffffffffffffffffffffffffffffffff811690813303611ede575b5050815160020b92602083015160020b916115a56040850151613785565b93606087015160020b9760608201516040519960c08b018b811067ffffffffffffffff821117611eb157604052338b528860208c01528660408c015287600f0b60608c015260808b015260a08a01525f9185881215611e7a577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff276188812611e4e57620d89e88613611e22576040519261163c84612dda565b5f84525f60208501525f60408501525f606085015287600f0b611b25575b600460805101978960020b5f528860205260405f20988860020b5f5260205260405f206080515460a01c60020b8b81125f14611acf575060028060018c0154600184015490039b015491015490039b5b60a073ffffffffffffffffffffffffffffffffffffffff825116910151906040519160268301528960068301528b600383015281525f603a600c83012091816040820152816020820152525f5260066080510160205260405f20976fffffffffffffffffffffffffffffffff8954169982600f0b155f14611a72578a15611a4a5761176f61176960409f9b61184e9c6118609e5b60018301956117616002611755848a548503615703565b95019283548503615703565b9655556130aa565b916130aa565b6fffffffffffffffffffffffffffffffff169060801b179a8b965f84600f0b126119dc575b5082600f0b611898575b5050506117c46117b58560801d8360801d01613785565b9185600f0b90600f0b01613785565b6fffffffffffffffffffffffffffffffff169060801b1791815160020b90602083015160020b8c8401516060850151918e5194855260208501528d84015260608301527ff208f4912782fd25c7f114ca3723a2d5dd6f3bcc3ac8db5af63baa85f711d5ec60803393a38873ffffffffffffffffffffffffffffffffffffffff60808201511661385b565b8094919461186c575b50833391613652565b82519182526020820152f35b6118929073ffffffffffffffffffffffffffffffffffffffff6080840151169083613652565b85611857565b60805154929350909173ffffffffffffffffffffffffffffffffffffffff81169060a01c60020b828112156118fe575050906118f2926118e76118dd6118ed94614158565b91600f0b92614158565b90614527565b613785565b60801b5b8b808061179e565b92809193125f146119a95761193d9161192a6118ed6118ed9361192488600f0b91614158565b87614527565b9361193886600f0b92614158565b6144ca565b6fffffffffffffffffffffffffffffffff169060801b17906fffffffffffffffffffffffffffffffff61197c60036080510192600f0b8284541661456e565b167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161790556118f6565b906118ed9250926119bf6118dd6119c595614158565b906144ca565b6fffffffffffffffffffffffffffffffff166118f6565b808f9151611a1e575b01516119f2575b8e611794565b611a198260805160049160020b5f52016020525f6002604082208281558260018201550155565b6119ec565b611a458360805160049160020b5f52016020525f6002604082208281558260018201550155565b6119e5565b7faefeb924000000000000000000000000000000000000000000000000000000005f5260045ffd5b61176f61176960409f9b61184e9c6118609e6fffffffffffffffffffffffffffffffff611aa289600f0b8361456e565b167fffffffffffffffffffffffffffffffff0000000000000000000000000000000084541617835561173e565b9099908913611af55760028060018c0154600184015490039b015491015490039b6116aa565b9860026001608051015460018c01549003600183015490039a81806080510154910154900391015490039b6116aa565b6004608051018960020b5f5280602052898960405f20611b7e81546fffffffffffffffffffffffffffffffff611b6181831695600f0b8661456e565b16931594858515141595611dee575b508d600f0b9060801d613d3a565b60801b82179055602087015285528760020b5f5260205260405f208054906fffffffffffffffffffffffffffffffff8216611bbc8b600f0b8261456e565b901592836fffffffffffffffffffffffffffffffff831615141593611dc1575b8b600f0b9060801d600f0b03916f7fffffffffffffffffffffffffffffff83137fffffffffffffffffffffffffffffffff80000000000000000000000000000000841217611d9457826fffffffffffffffffffffffffffffffff935060801b83831617905516606086015260408501525f88600f0b1215611ca1575b8351611c85575b60408401511561165a57611c8060808c015160020b8860056080510161410c565b61165a565b611c9c60808c015160020b8a60056080510161410c565b611c5f565b60808b015160020b6fffffffffffffffffffffffffffffffff600181602088015116925f817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff276180712817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27618050390620d89e8050301810416809111611d68576fffffffffffffffffffffffffffffffff6060860151161115611c5857867fb8e3c385000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b897fb8e3c385000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6080515460a01c60020b8b13611bdc57600160805101546001840155600260805101546002840155611bdc565b6080515460a01c60020b1215611e05575b8e611b70565b600160805101546001840155600260805101546002840155611dff565b857f1ad777f8000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b877fd5e2f7ab000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b60448887604051917fc4433ed500000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f604085015113808091611fd6575b15611f6b5750506040517f259982e5000000000000000000000000000000000000000000000000000000006020820152611f62916112aa82611f368887898c33602487016136cb565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101845283612e2e565b505b8580611587565b159081611fc8575b50611f7f575b50611f64565b6040517f21d0ee70000000000000000000000000000000000000000000000000000000006020820152611fc1916112aa82611f368887898c33602487016136cb565b5085611f79565b610200915016151587611f73565b5061080082161515611eed565b346103305760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103305761201a612d3f565b73ffffffffffffffffffffffffffffffffffffffff612037612d62565b91165f52600560205273ffffffffffffffffffffffffffffffffffffffff60405f2091165f5260205260405f206044355f52602052602060405f2054604051908152f35b346103305760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610330576120b2612d3f565b602435908115158092036103305773ffffffffffffffffffffffffffffffffffffffff90335f52600360205260405f208282165f5260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff851617905560405192835216907fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa26760203392a3602060405160018152f35b346103305760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103305761218a36612e81565b612192612e6f565b906280000062ffffff60408301511614801590612246575b61221e5760a0906121ba8361368e565b205f52600660205260405f20906121d082613576565b81547fffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffff1660d09190911b7cffffff000000000000000000000000000000000000000000000000000016179055005b7f30d21641000000000000000000000000000000000000000000000000000000005f5260045ffd5b5073ffffffffffffffffffffffffffffffffffffffff6080820151163314156121aa565b346103305760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103305760043567ffffffffffffffff8111610330576122b9903690600401612f4d565b7fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c6124cd57612345915f9160017fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235d60405193849283927f91dd734600000000000000000000000000000000000000000000000000000000845260206004850152602484019161306c565b038183335af19081156124c2575f9161241a575b507f7d4b3164c6e45b97e7d87b7125a44c5828d005af88f9d751cfd78729c5d99a0b5c6123f25760406020915f7fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f835194859381855280519182918282880152018686015e5f85828601015201168101030190f35b7f5212cba1000000000000000000000000000000000000000000000000000000005f5260045ffd5b90503d805f833e61242b8183612e2e565b8101906020818303126103305780519067ffffffffffffffff8211610330570181601f820112156103305780519067ffffffffffffffff8211611eb1576040519261249e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8601160185612e2e565b8284526020838301011161033057815f9260208093018386015e8301015281612359565b6040513d5f823e3d90fd5b7f5090d6c6000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103305773ffffffffffffffffffffffffffffffffffffffff61251836612d85565b91929092335f52600560205260405f208282165f5260205260405f20845f526020528260405f205560405192835216907fb3fd5071835887567a0671151121894ddccc2842f1d10bedad13e0d17cace9a760203392a4602060405160018152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610330576125ab612d3f565b7fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c156104d7576107a260209161342d565b346103305760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610330576024356004356040519160408360208152826020820152019060051b8301916001602060408501935b835481520191019084838210156109cc57506020600191612635565b346103305760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103305773ffffffffffffffffffffffffffffffffffffffff61269d612d3f565b6126ab825f54163314613007565b16807fffffffffffffffffffffffff000000000000000000000000000000000000000060025416176002557fb4bd8ef53df690b9943d3318996006dbb82a25f54719d8c8035b516a2a5b8acc5f80a2005b34610330576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103305761273536612e81565b60c4359060a43560e43567ffffffffffffffff81116103305761275c903690600401612f4d565b9190937fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c156104d75761278e61350f565b60a0842094855f52600660205260405f20946127a986613576565b60808101805173ffffffffffffffffffffffffffffffffffffffff811690813303612943575b50506fffffffffffffffffffffffffffffffff60038801541697881561291b576020986127fb876130aa565b5f03612806876130aa565b5f036fffffffffffffffffffffffffffffffff169060801b179887612907575b866128f2575b5050612839338985613652565b60405190868252858a8301527f29ef05caaff9404b7cb6d1c0e9bbae9eaa7ab2541feba1a9c4248594c08156cb60403393a3519273ffffffffffffffffffffffffffffffffffffffff841693843303612897575b8888604051908152f35b6010166128a5575b8061288d565b6128e6956112aa93611f36926040519788957fe1b4af69000000000000000000000000000000000000000000000000000000008d88015233602488016135bc565b5082808080808061289f565b600201908660801b048154019055898061282c565b60018101828960801b048154019055612826565b7fa74f97ab000000000000000000000000000000000000000000000000000000005f5260045ffd5b602016612951575b806127cf565b6040517fb6a8b0fa000000000000000000000000000000000000000000000000000000006020820152612994916112aa82611f368b898b8d8b33602488016135bc565b508861294b565b346103305760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057600435545f5260205ff35b34610330576129e336612d85565b907fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c156104d7577f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac7288596103ed73ffffffffffffffffffffffffffffffffffffffff805f941695612a62612a55876130aa565b8603600f0b3390896130f0565b16938484526004602052604084208685526020526040842061025f828254612ffa565b5f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610330577fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c156104d75760206107a23361342d565b346103305760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033057612b17612d3f565b612b1f612d62565b604435907fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab235c156104d757610e2f92612b67612b5a846130aa565b5f03600f0b3390836130f0565b6131f8565b346103305773ffffffffffffffffffffffffffffffffffffffff612b8f36612d85565b91929092335f52600460205260405f20845f5260205260405f20612bb4848254612fed565b90551690815f52600460205260405f20835f5260205260405f20612bd9828254612ffa565b9055604080513380825260208201939093527f1b3d7edb2e9c0b0e7c525b20aaaef0f5940d2ed71663c7d39266ecafac7288599181908101610279565b346103305760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610330576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361033057807f01ffc9a70000000000000000000000000000000000000000000000000000000060209214908115612cab575b506040519015158152f35b7f0f632fb30000000000000000000000000000000000000000000000000000000091501482612ca0565b346103305760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103305760209073ffffffffffffffffffffffffffffffffffffffff612d24612d3f565b165f526004825260405f206024355f52825260405f20548152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361033057565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361033057565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60609101126103305760043573ffffffffffffffffffffffffffffffffffffffff8116810361033057906024359060443590565b6080810190811067ffffffffffffffff821117611eb157604052565b6060810190811067ffffffffffffffff821117611eb157604052565b60a0810190811067ffffffffffffffff821117611eb157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117611eb157604052565b60a4359062ffffff8216820361033057565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a09101126103305760405190612eb882612e12565b8160043573ffffffffffffffffffffffffffffffffffffffff8116810361033057815260243573ffffffffffffffffffffffffffffffffffffffff8116810361033057602082015260443562ffffff811681036103305760408201526064358060020b81036103305760608201526084359073ffffffffffffffffffffffffffffffffffffffff821682036103305760800152565b9181601f840112156103305782359167ffffffffffffffff8311610330576020838186019501011161033057565b9060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103305760043567ffffffffffffffff811161033057826023820112156103305780600401359267ffffffffffffffff84116103305760248460051b83010111610330576024019190565b91908203918211611d9457565b91908201809211611d9457565b1561300e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152fd5b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b6f800000000000000000000000000000008110156130c857600f0b90565b7f93dafdf1000000000000000000000000000000000000000000000000000000005f5260045ffd5b9190600f0b9182156131f357613126919073ffffffffffffffffffffffffffffffffffffffff8092165f521660205260405f2090565b613132815c9283613b29565b80915d6131a357507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f7d4b3164c6e45b97e7d87b7125a44c5828d005af88f9d751cfd78729c5d99a0b5c017f7d4b3164c6e45b97e7d87b7125a44c5828d005af88f9d751cfd78729c5d99a0b5d5b565b156131aa57565b60017f7d4b3164c6e45b97e7d87b7125a44c5828d005af88f9d751cfd78729c5d99a0b5c017f7d4b3164c6e45b97e7d87b7125a44c5828d005af88f9d751cfd78729c5d99a0b5d565b505050565b90919073ffffffffffffffffffffffffffffffffffffffff811690816132ea5750505f80808093855af11561322a5750565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f3d011673ffffffffffffffffffffffffffffffffffffffff604051927f90bfb8650000000000000000000000000000000000000000000000000000000084521660048301525f6024830152608060448301528060a00160648301523d60848301523d5f60a484013e7ff4b3b1bc0000000000000000000000000000000000000000000000000000000060c4828401600460a4820152015260e40190fd5b60205f60448194968260409573ffffffffffffffffffffffffffffffffffffffff988751998a947fa9059cbb00000000000000000000000000000000000000000000000000000000865216600485015260248401525af13d15601f3d116001855114161716928281528260208201520152156133635750565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f3d0116604051917f90bfb86500000000000000000000000000000000000000000000000000000000835260048301527fa9059cbb000000000000000000000000000000000000000000000000000000006024830152608060448301528060a00160648301523d60848301523d5f60a484013e7ff27f64e40000000000000000000000000000000000000000000000000000000060c4828401600460a4820152015260e40190fd5b7f27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b95c919073ffffffffffffffffffffffffffffffffffffffff8316613482576131a19034935b61347c856130aa565b906130f0565b346134e7576131a1906134be7f1e0745a7db1623981f0b2a5d4232364c00787266eb75ad546f190e6cebe9bd955c6134b986613a92565b612fed565b935f7f27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b95d613473565b7fb0ec849e000000000000000000000000000000000000000000000000000000005f5260045ffd5b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016300361354e57565b7f0d89438e000000000000000000000000000000000000000000000000000000005f5260045ffd5b5473ffffffffffffffffffffffffffffffffffffffff161561359457565b7f486aa307000000000000000000000000000000000000000000000000000000005f5260045ffd5b91926136376101209473ffffffffffffffffffffffffffffffffffffffff61364f999794168552602085019073ffffffffffffffffffffffffffffffffffffffff6080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b60c083015260e082015281610100820152019161306c565b90565b9073ffffffffffffffffffffffffffffffffffffffff60206131a1949361368185848351168660801d906130f0565b01511690600f0b906130f0565b62ffffff16620f424081116136a05750565b7f14002113000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9061364f95936137486101609473ffffffffffffffffffffffffffffffffffffffff61377794168552602085019073ffffffffffffffffffffffffffffffffffffffff6080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b8051600290810b60c08501526020820151900b60e0840152604081015161010084015260600151610120830152565b81610140820152019161306c565b9081600f0b9182036130c857565b926138419061381261364f99979473ffffffffffffffffffffffffffffffffffffffff6101a09895168752602087019073ffffffffffffffffffffffffffffffffffffffff6080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b8051600290810b60c08701526020820151900b60e0860152604081015161010086015260600151610120850152565b61014083015261016082015281610180820152019161306c565b939590919296945f9673ffffffffffffffffffffffffffffffffffffffff861633146139ac57885f6040870151135f1461393b5761040087166138a2575b50505050505050565b61392e9799985092613927969594926138ef9261391b956040519788967f9f063efc0000000000000000000000000000000000000000000000000000000060208901523360248901613793565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612e2e565b6002821615159161459f565b80926145bf565b915f808080808080613899565b95949392919061010086166139535750505050505050565b61392e979950869850916138ef916139a09493613927986040519788967f6c2bbe7e0000000000000000000000000000000000000000000000000000000060208901523360248901613793565b6001821615159161459f565b505f96505050505050565b608081161580613a69575b613a3f57604081161580613a5d575b613a3f5761040081161580613a51575b613a3f5761010081161580613a45575b613a3f5773ffffffffffffffffffffffffffffffffffffffff8116613a1f575062ffffff1662800000141590565b613fff161590811591613a30575090565b62800000915062ffffff161490565b50505f90565b506001811615156139f1565b506002811615156139e1565b506004811615156139d1565b506008811615156139c2565b6280000062ffffff821614613a8d5761364f8161368e565b505f90565b73ffffffffffffffffffffffffffffffffffffffff1680613ab257504790565b6020602491604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa9081156124c2575f91613afa575090565b90506020813d602011613b21575b81613b1560209383612e2e565b81010312610330575190565b3d9150613b08565b9190915f8382019384129112908015821691151617611d9457565b6020830151955f9586959194913373ffffffffffffffffffffffffffffffffffffffff851614613d2d5760808416613b7e575b5050505050565b613c66926138ef613c6092613c4c946040519586947f575e24b4000000000000000000000000000000000000000000000000000000006020870152336024870152613c16604487018c73ffffffffffffffffffffffffffffffffffffffff6080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b8051151560e487015260208101516101048701526040015173ffffffffffffffffffffffffffffffffffffffff16610124860152565b61014061014485015261016484019161306c565b82613f25565b916060835103613d05576040015162ffffff166280000014613cf9575b600816613c94575b80808080613b77565b604001519250608083901d600f0b8015613c8b57613cb5905f861295613b29565b9315613cf1575f84135b613cc9575f613c8b565b7ffa0b71d6000000000000000000000000000000000000000000000000000000005f5260045ffd5b5f8412613cbf565b60608201519350613c83565b7f1e048e1d000000000000000000000000000000000000000000000000000000005f5260045ffd5b505f965086955050505050565b90600f0b90600f0b01907fffffffffffffffffffffffffffffffff8000000000000000000000000000000082126f7fffffffffffffffffffffffffffffff831317611d9457565b9196959394929473ffffffffffffffffffffffffffffffffffffffff83163314613f18578460801d94600f0b938860408516613e40575b50505050505f9481600f0b15801590613e34575b613dd8575b5050509190565b613e0f9395505f60208201511290511515145f14613e17576fffffffffffffffffffffffffffffffff169060801b175b80936145bf565b5f8080613dd1565b906fffffffffffffffffffffffffffffffff169060801b17613e08565b5082600f0b1515613dcc565b613efc613f08946138ef6118ed95613f0e999895613ee1613c16966040519788967fb47b2fb1000000000000000000000000000000000000000000000000000000006020890152336024890152604488019073ffffffffffffffffffffffffffffffffffffffff6080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b8c61014485015261016061016485015261018484019161306c565b6004821615159161459f565b90613d3a565b5f80808088613db8565b5050505050909150905f90565b9190918251925f8060208301958682865af115613fc3575050604051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f3d011683016040523d83523d9060208401915f833e6020845110918215613f8f575b5050613d0557565b5190517fffffffff000000000000000000000000000000000000000000000000000000009182169116141590505f80613f87565b5183517fffffffff00000000000000000000000000000000000000000000000000000000811691600481106140d7575b50507fffffffff000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f3d01169173ffffffffffffffffffffffffffffffffffffffff604051947f90bfb865000000000000000000000000000000000000000000000000000000008652166004850152166024830152608060448301528060a00160648301523d60848301523d5f60a484013e7fa9e35b2f0000000000000000000000000000000000000000000000000000000060c4828401600460a4820152015260e40190fd5b7fffffffff000000000000000000000000000000000000000000000000000000009250829060040360031b1b16168280613ff3565b919060020b9060020b9081810761413a5705908160081d5f52602052600160ff60405f2092161b8154189055565b601c906044926040519163d4d8f3e683526020830152604082015201fd5b60020b908160ff1d82810118620d89e8811161449e5763ffffffff9192600182167001fffcb933bd6fad37aa2d162d1a59400102700100000000000000000000000000000000189160028116614482575b60048116614466575b6008811661444a575b6010811661442e575b60208116614412575b604081166143f6575b608081166143da575b61010081166143be575b61020081166143a2575b6104008116614386575b610800811661436a575b611000811661434e575b6120008116614332575b6140008116614316575b61800081166142fa575b6201000081166142de575b6202000081166142c3575b6204000081166142a8575b620800001661428f575b5f12614268575b0160201c90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04614261565b6b048a170391f7dc42444e8fa290910260801c9061425a565b6d2216e584f5fa1ea926041bedfe9890920260801c91614250565b916e5d6af8dedb81196699c329225ee6040260801c91614245565b916f09aa508b5b7a84e1c677de54f3e99bc90260801c9161423a565b916f31be135f97d08fd981231505542fcfa60260801c9161422f565b916f70d869a156d2a1b890bb3df62baf32f70260801c91614225565b916fa9f746462d870fdf8a65dc1f90e061e50260801c9161421b565b916fd097f3bdfd2022b8845ad8f792aa58250260801c91614211565b916fe7159475a2c29b7443b29c7fa6e889d90260801c91614207565b916ff3392b0822b70005940c7a398e4b70f30260801c916141fd565b916ff987a7253ac413176f2b074cf7815e540260801c916141f3565b916ffcbe86c7900a88aedcffc83b479aa3a40260801c916141e9565b916ffe5dee046a99a2a811c461f1969c30530260801c916141df565b916fff2ea16466c96a3843ec78b326b528610260801c916141d6565b916fff973b41fa98c081472e6896dfb254c00260801c916141cd565b916fffcb9843d60f6159c9db58835c9266440260801c916141c4565b916fffe5caca7e10e4e61c3624eaa0941cd00260801c916141bb565b916ffff2e50f5f656932ef12357cf3c7fdcc0260801c916141b2565b916ffff97272373d413259a46990580e213a0260801c916141a9565b827f8b86327a000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b905f83600f0b125f146144ff576144f5925f036fffffffffffffffffffffffffffffffff1691615a3d565b5f81126130c85790565b61451b926fffffffffffffffffffffffffffffffff16916159e2565b5f81126130c8575f0390565b905f83600f0b125f14614552576144f5925f036fffffffffffffffffffffffffffffffff1691615b34565b61451b926fffffffffffffffffffffffffffffffff1691615a7d565b906fffffffffffffffffffffffffffffffff90600f0b911601908160801c61459257565b6393dafdf15f526004601cfd5b906145a991613f25565b9015613a8d576040815103613d05576040015190565b6145e2906145d48360801d8260801d03613785565b92600f0b90600f0b03613785565b6fffffffffffffffffffffffffffffffff169060801b1790565b73fffd8963efd1fc6a506488495d951d516396168273ffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffd895d830116116148e05777ffffffffffffffffffffffffffffffffffffffff000000008160201b168060ff61467983615bdb565b1691608083106148d457507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8182011c5b800280607f1c8160ff1c1c800280607f1c8160ff1c1c800280607f1c8160ff1c1c800280607f1c8160ff1c1c800280607f1c8160ff1c1c800280607f1c8160ff1c1c80029081607f1c8260ff1c1c80029283607f1c8460ff1c1c80029485607f1c8660ff1c1c80029687607f1c8860ff1c1c80029889607f1c8a60ff1c1c80029a8b607f1c8c60ff1c1c80029c8d80607f1c9060ff1c1c800260cd1c6604000000000000169d60cc1c6608000000000000169c60cb1c6610000000000000169b60ca1c6620000000000000169a60c91c6640000000000000169960c81c6680000000000000169860c71c670100000000000000169760c61c670200000000000000169660c51c670400000000000000169560c41c670800000000000000169460c31c671000000000000000169360c21c672000000000000000169260c11c674000000000000000169160c01c67800000000000000016907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160401b1717171717171717171717171717693627a301d71055774c85027ffffffffffffffffffffffffffffffffffd709b7e5480fba5a50fed5e62ffc556810160801d60020b906fdb2df09e81959a81455e260799a0632f0160801d60020b918282145f146148915750905090565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff6148c584614158565b16116148cf575090565b905090565b905081607f031b6146a9565b73ffffffffffffffffffffffffffffffffffffffff907f61487524000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b811561492c570490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b6040519290915f61496985612df6565b5f855260208501925f845260408601955f875280968654956040860151159586155f146156f557610fff8860b81c16945b8151925f948a73ffffffffffffffffffffffffffffffffffffffff16918288528b60a01c60020b90526fffffffffffffffffffffffffffffffff60038d0154169052608083015162400000811615155f146156e65762bfffff166149fd8161368e565b61ffff88166156cb575b8096620f424062ffffff8316101561569a575b8451156156845750508861562457606083019073ffffffffffffffffffffffffffffffffffffffff825116818110156155ed5750505173ffffffffffffffffffffffffffffffffffffffff166401000276a38111156155c257505b604051986101008a018a811067ffffffffffffffff821117611eb1576040525f8a525f60208b01525f60408b01525f60608b01525f60808b01525f60a08b01525f60c08b015288155f146155b45760018b0154949390945b60e08b01525b8015801561557a575b6154205788868d8c8e73ffffffffffffffffffffffffffffffffffffffff8351168252602083015160020b602089015160020b90815f8183071291050386155f14615275576fffffffffffffffffffffffffffffffff937ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2761860409460019484600560ff60609716938260020b60081d890b5f5201602052875f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8460ff031c9054169283151593845f146152635790614bb760ff92615bdb565b90031660020b900360020b0260020b5b905b15158684015260020b8060208401521315615238575b620d89e8602082015160020b121561522a575b73ffffffffffffffffffffffffffffffffffffffff614c17602083015160020b614158565b16918291015273ffffffffffffffffffffffffffffffffffffffff8551169673ffffffffffffffffffffffffffffffffffffffff60608c0151169283911516818310189118021892015116928d73ffffffffffffffffffffffffffffffffffffffff8316821015915f87125f1461507f5762ffffff8516620f424003614c9f81895f03615785565b94841561506e57614cb1888483615a7d565b955b868110614fb257509660a093929173ffffffffffffffffffffffffffffffffffffffff98978891620f424062ffffff8316145f14614f9e575050865b955b15614f905791614d0092615a3d565b925b60c0820152015260808d0152168c525f8351135f14614f605760a08a0151905f82126130c8570392614d3d60808b015160c08c015190612ffa565b5f81126130c8578103908113600116611d9457935b61ffff8716614f18575b6fffffffffffffffffffffffffffffffff60408d01511680614efe575b5073ffffffffffffffffffffffffffffffffffffffff8c511673ffffffffffffffffffffffffffffffffffffffff60608c01511681145f14614ec2575060408a0151614e10575b88614e03577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208b015160020b0160020b5b60020b60208d01525b9392614ad3565b60208a015160020b614df3565b88614e96576fffffffffffffffffffffffffffffffff614e7d8d8d8d600460e08201519260206002820154935b015160020b60020b5f520160205260405f2091600183019081549003905560028201908154900390555460801d908c15614e88575b60400151831661456e565b1660408d0152614dc0565b5f91909103600f0b90614e72565b6fffffffffffffffffffffffffffffffff614e7d8d8d8d6004600183015492602060e084015193614e3d565b73ffffffffffffffffffffffffffffffffffffffff8b51168103614ee7575b50614dfc565b614ef0906145fc565b60020b60208d01525f614ee1565b60c08b015160801b0460e08b01510160e08b01525f614d79565b9662ffffff861661ffff881603614f435760c08a0151905b8160c08c01510360c08c01520196614d5c565b620f424060808b015161ffff89169060c08d015101020490614f30565b60808a015160c08b015101905f82126130c857019260a08a01515f81126130c857614f8a91613b29565b93614d52565b614f9992615b34565b614d00565b62ffffff614fad921689615c68565b614cef565b9650505092505082918415811517615061578e60a09173ffffffffffffffffffffffffffffffffffffffff96845f14614ffc57614ff0878284615d07565b80978a015f0395614cf1565b87871161503a576150356150306150286fffffffffffffffffffffffffffffffff84168a60601b614922565b8a8516612ffa565b615d9b565b614ff0565b61503561503061505c6fffffffffffffffffffffffffffffffff84168a61588a565b615028565b634f2461b85f526004601cfd5b6150798882856159e2565b95614cb3565b9193509190831561521957615095858284615a3d565b915b8287106150f7579073ffffffffffffffffffffffffffffffffffffffff9560a09280965b156150e857916150ca92615a7d565b925b6150e362ffffff8d16620f42408190039086615c68565b614d02565b6150f1926159e2565b926150cc565b50915050838315821517615061578d83156151ef575073ffffffffffffffffffffffffffffffffffffffff851161519c578460601b6fffffffffffffffffffffffffffffffff851680820615159104015b73ffffffffffffffffffffffffffffffffffffffff8316928184111561518f578f939573ffffffffffffffffffffffffffffffffffffffff60a093819803165b80966150bb565b634323a5555f526004601cfd5b6fffffffffffffffffffffffffffffffff84166151c7816c0100000000000000000000000088615943565b90801561492c576c010000000000000000000000008709156151485760010180615148575f80fd5b9180856152148873ffffffffffffffffffffffffffffffffffffffff9860a095615c91565b615188565b615224858383615b34565b91615097565b620d89e86020820152614bf2565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff276186020820152614bdf565b5060020b900360020b0260020b614bc7565b60019194939650600592955001938460020b60081d60010b5f520160205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160ff86161b0119905416908d8b831592831597885f146153c15750505050610330578f9160018f8f96907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff276186060928f989560409660ff896fffffffffffffffffffffffffffffffff9a5f03166101e07f804040554300526644320000502061067405302602000010750620017611707760fc7fb6db6db6ddddddddd34d34d349249249210842108c6318c639ce739cffffffff840260f81c161b60f71c167e1f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405601f85851693831c63d76453e004161a17031660020b9060020b0160020b0260020b5b90614bc9565b90956fffffffffffffffffffffffffffffffff955060409450600193987ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27618918960ff6060969b811681031660020b9060020b0160020b0260020b6153bb565b949891955099969298919598602088015160a01b76ffffff0000000000000000000000000000000000000000167fffffffffffffffffff000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8a51169216171782556fffffffffffffffffffffffffffffffff6003830154166fffffffffffffffffffffffffffffffff604089015116809103615535575b5082156155265760e060029101519101555b825190155f82121461551057506154ee6154f69293613785565b925103613785565b6fffffffffffffffffffffffffffffffff169060801b1793565b6154f69250906155209103613785565b91613785565b60e060019101519101556154d4565b6fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff000000000000000000000000000000006003840154161760038301555f6154c2565b5073ffffffffffffffffffffffffffffffffffffffff8c511673ffffffffffffffffffffffffffffffffffffffff60608501511614614adc565b60028b015494939094614acd565b7f9e4d7cc7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b60449250604051917f7c9c6e8f00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b606083019073ffffffffffffffffffffffffffffffffffffffff825116818111156155ed5750505173ffffffffffffffffffffffffffffffffffffffff1673fffd8963efd1fc6a506488495d951d5263988d268110156155c25750614a75565b9a509a50509950505050505050505f925f929190565b5f85511315614a1a577f96206246000000000000000000000000000000000000000000000000000000005f5260045ffd5b62ffffff610fff89169116620f424081830204910103614a07565b508960d01c62ffffff166149fd565b610fff8860c41c169461499a565b90808202917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff828209918380841093039280840393847001000000000000000000000000000000001115610330571461577c57700100000000000000000000000000000000910990828211900360801b910360801c1790565b50505060801c90565b818102907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83820990828083109203918083039283620f424011156103305714615804577fde8f6cefed634549b62c77574f722e1ac57e23f24d8fd5cb790fb65668c2613993620f4240910990828211900360fa1b910360061c170290565b5050620f424091500490565b90808202917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff828209918380841093039280840393846c0100000000000000000000000011156103305714615881576c01000000000000000000000000910990828211900360a01b910360601c1790565b50505060601c90565b908160601b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6c01000000000000000000000000840992828085109403938085039485841115610330571461593c576c0100000000000000000000000082910981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b5091500490565b91818302917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8185099383808610950394808603958685111561033057146159da579082910981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b505091500490565b6fffffffffffffffffffffffffffffffff6c010000000000000000000000009173ffffffffffffffffffffffffffffffffffffffff80600195169116038060ff1d90810118931692615a348185615810565b93091515160190565b6fffffffffffffffffffffffffffffffff9073ffffffffffffffffffffffffffffffffffffffff8061364f9594169116038060ff1d908101189116615810565b9073ffffffffffffffffffffffffffffffffffffffff811673ffffffffffffffffffffffffffffffffffffffff831611615b2e575b73ffffffffffffffffffffffffffffffffffffffff8216928315615b22577bffffffffffffffffffffffffffffffff00000000000000000000000073ffffffffffffffffffffffffffffffffffffffff615b16948185169403169160601b16615c68565b90808206151591040190565b62bfc9215f526004601cfd5b90615ab2565b73ffffffffffffffffffffffffffffffffffffffff821673ffffffffffffffffffffffffffffffffffffffff821611615bd5575b73ffffffffffffffffffffffffffffffffffffffff8116918215615b225761364f937bffffffffffffffffffffffffffffffff00000000000000000000000073ffffffffffffffffffffffffffffffffffffffff615bd0948185169403169160601b16615943565b614922565b90615b68565b8015610330577f07060605060205000602030205040001060502050303040105050304000000006f8421084210842108cc6318c6db6d54be826fffffffffffffffffffffffffffffffff1060071b83811c67ffffffffffffffff1060061b1783811c63ffffffff1060051b1783811c61ffff1060041b1783811c60ff1060031b1792831c1c601f161a1790565b929190615c76828286615943565b93821561492c5709615c8457565b9060010190811561033057565b91908115615d02577bffffffffffffffffffffffffffffffff00000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9160601b169216918282029183838311918404141615615cf55761364f9261503092820391615c68565b63f5c787f15f526004601cfd5b505090565b90918015615d955773ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffffffffffffffffffff000000000000000000000000819460601b16921680820281615d578483614922565b14615d7d575b5090615d6c615d719284614922565b612ffa565b80820615159104011690565b8301838110615d5d579150615d9192615c68565b1690565b50905090565b9073ffffffffffffffffffffffffffffffffffffffff82169182036130c85756fea164736f6c634300081a000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.0; import {IPositionDescriptor} from '../../protocols/v4-periphery/interfaces/IPositionDescriptor.sol'; library PositionDescriptorDeployer { function deploy(address poolManager, address weth, bytes32 nativeCurrencyLabelBytes) internal returns (IPositionDescriptor descriptor) { bytes memory args = abi.encode(poolManager, weth, nativeCurrencyLabelBytes); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { descriptor := create2(0, add(initcode_, 32), mload(initcode_), hex'00') } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v4-periphery/src/PositionDescriptor.sol */ function initcode() internal pure returns (bytes memory) { return hex'60e0346100b357601f615ed138819003918201601f19168301916001600160401b038311848410176100b7578084926060946040528339810103126100b3578051906001600160a01b03821682036100b3576020810151906001600160a01b03821682036100b357604001519160c05260805260a052604051615e0590816100cc8239608051818181607a0152613f05015260a05181818161402c0152614082015260c0518181816101530152613d6c0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe610440806040526004361015610013575f80fd5b5f60a0525f3560e01c908163166c597814613dc257508063b7af3cdc14613d9b578063dc4c90d314613d57578063dee91a2c14613d0e578063e9dc6375146100af5763eb6d3a1114610063575f80fd5b346100a95760a0513660031901126100a9576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b60a05180fd5b34613c29576040366003190112613c29576004356001600160a01b03811690819003613c2957602460c081359260405192838092637ba03aad60e01b82528660048301525afa8015613c35575f915f91613c53575b5066ffffffffffffff19811615613c405760a08220604051602081019182526006604082015260408152610139606082613f42565b519020604051631e2eaeaf60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031693909290602084602481885afa938415613c35575f94613bfd575b50815160208301516001600160a01b039182169691166101b587613e2a565b6101be82613e2a565b129687159188613bf65780925b15613bee5750955b6101e46101de614001565b836140cb565b956101f66101f0614001565b896140cb565b6101ff84614254565b976102098a614254565b99606089015160020b9562ffffff60408b01511699608060018060a01b0391015116986040516102c0526101e06102c051016102c051811060018060401b03821117613b82576040526102c05152600160a01b60019003166102c05160200152600160a01b60019003166102c051604001526102c051606001526102c051608001526102c05160a0019660ff1687526102c05160c0019760ff1688526102c05160e0019889528060081c60020b6102c051610100015260201c60020b6102c051610120015260a01c60020b6102c05161014001526102c0516101600152826102c05161018001526102c0516101a001526102c0516101c0015261030b9061458d565b906102c0516060015161031d90614828565b916102c0516080015161032f90614828565b93855115805f149660036020600298602a82849a816103bc61046b9f9c60019b610388849f9c859d613bdd576101006102c051015160020b5b6101606102c051015160020b9160ff85511690159260ff87511692614d92565b9a51158015613bcb576101206102c051015160020b915b60ff806101606102c051015160020b925116921594511692614d92565b9a6040516103e0526902ab734b9bbb0b81016960b51b826103e0510152805191829101856103e051015e6103e05101906201016960ed1b84830152805192839101602d83015e010190602f60f81b84830152805192839101600483015e0101906201016960ed1b84830152805192839101600483015e010190611e1f60f11b84830152805192839101600583015e01015f828201526103e051900301601f1981016103e051526103e051613f42565b6105ec6002605961048260606102c0510151614828565b61049260806102c0510151614828565b90600160206104af828060a01b036101a06102c051015116615481565b604051610400527f54686973204e465420726570726573656e74732061206c697175696469747920826104005101527803837b9b4ba34b7b71034b71030902ab734b9bbb0b8103b1a1603d1b604061040051015285828551968187019780898561040051015e610400510190602d60f81b84830152805192839101605a83015e010190660103837b7b617160cd1b848301527f546865206f776e6572206f662074686973204e46542063616e206d6f646966796008830152791037b9103932b232b2b6903a3432903837b9b4ba34b7b7172e3760311b60288301527702e372837b7b61026b0b730b3b2b91020b2323932b9b99d160451b6042830152805192839101605a83015e010190612e3760f11b84830152518092605b83015e01015f8282015261040051900301601f198101610400515261040051613f42565b61085c60ac600c8060206106036102c0515161492e565b60108261061660806102c0510151614828565b6102c0518201516001600160a01b031680613bb95750600a826106376142d5565b925b6102c051604001516001600160a01b031680613ba8575060028261065b6142d5565b6102c0516101c001516001600160a01b031680613b965750602a8261067e6142f9565b955b8161069762ffffff6101806102c05101511661458d565b9a6040516103c0526901020b2323932b9b99d160b51b826103c0510152805191829101856103c051015e6103c0510190612e3760f11b84830152805192839101602c83015e0101906901020b2323932b9b99d160b51b848301528051928391018d83015e0101906f02e372437b7b59020b2323932b9b99d160851b84830152805192839101601a83015e0101906b02e372332b2902a34b2b91d160a51b84830152805192839101601c83015e0101906b02e372a37b5b2b71024a21d160a51b84830152805192839101601883015e0101632e372e3760e11b828201527fe29aa0efb88f20444953434c41494d45523a204475652064696c6967656e636560108201527f20697320696d7065726174697665207768656e20617373657373696e6720746860308201527f6973204e46542e204d616b6520737572652063757272656e637920616464726560508201527f73736573206d61746368207468652065787065637465642063757272656e636960708201527f65732c2061732063757272656e63792073796d626f6c73206d6179206265206960908201526736b4ba30ba32b21760c11b60b08201526103c051900301608c81016103c05152016103c051613f42565b6102c05160200151610876906001600160a01b0316615481565b6102c05160400151610890906001600160a01b0316615481565b610320526102c0516101c08101516001600160a01b03166102e05260608101516080820151610180909201519091906108cd9062ffffff1661458d565b6101006102c051015160020b916101206102c051015160020b610360526101606102c051015160020b610380526109136101406102c051015160020b610360518561553d565b610420526102c051519361093560018060a01b0360206102c051015116615564565b610300526102c05160400151610953906001600160a01b0316615564565b6102c05160200151909690610970906001600160a01b03166155c3565b610260526102c0516040015161098e906001600160a01b03166155c3565b610280526102c0516020810151905160ff916109af919060101c8316614a76565b6101026103a08190529190068181029181159183041417156137e25760ff610340526109e36109e891610340519004614527565b61492e565b6102a0526102c051604081015190516103405191610a14919060101c83166001600160901b0316614a76565b6101806102408190529190068181029181159183041417156137e2576103405115613b15576109e3610a4b91610340519004614535565b610220526102c05160208181015191516103405192610a75921c83166001600160801b0316614a76565b6103a0519190068181029181159183041417156137e2576103405115613b15576109e3610aa791610340519004614527565b610200526102c051604081015190516103405191610ad3919060201c83166001600160801b0316614a76565b610240519190068181029181159183041417156137e2576103405115613b15576109e3610b0591610340519004614535565b6101e0526102c051602081015190516103405191610b31919060301c83166001600160701b0316614a76565b6103a0519190068181029181159183041417156137e2576103405115613b15576109e3610b6391610340519004614527565b6101c0526102c051604081015190516103405191610b8f919060301c83166001600160701b0316614a76565b610240519190068181029181159183041417156137e2576103405115613b15576109e3610bc191610340519004614535565b6101a0526040516101808190526102a081019081106001600160401b03821117613b825760405261018051526103205160206101805101526102e05160406101805101526060610180510152608061018051015260a061018051015260c06101805101526103605160e061018051015261038051610100610180510152610420515f0b6101206101805101526101406101805101526103005161016061018051015261024051610180510152610260516101a0610180510152610280516101c06101805101526102a0516101e061018051015261022051610200610180510152610200516102206101805101526101e0516102406101805101526101c0516102606101805101526101a051610280610180510152611c206101e4610655603f6020610da36040515f80516020615cb9833981519152838201525f80516020615db983398151915260408201527f2f2f7777772e77332e6f72672f323030302f737667273e3c726563742077696460608201527f74683d27323930707827206865696768743d273530307078272066696c6c3d276080820152602360f81b60a0820152610d9e600960a1836103005151808861030051018484015e81016813979f1e17b9bb339f60b91b838201520301601619810184520182613f42565b614a89565b603e82610e4f81610d9e600960136101e0610180510151600685610200610180510151816102405161018051015191604051998a96610de3828901615661565b90805192839101825e019065272063793d2760d01b82528051928391018683015e0190722720723d273132307078272066696c6c3d272360681b84830152805192839101601983015e01016813979f1e17b9bb339f60b91b838201520301601619810184520182613f42565b8282610e8d81610d9e60096013610220610180510151600685610240610180510151816101a061018051015191604051998a96610de3828901615661565b60f382610f3881610d9e60096013610260610180510151600685610280610180510151816101c061018051015191604051998a96610ecc828901615661565b90805192839101825e019065272063793d2760d01b82528051928391018683015e0190722720723d273130307078272066696c6c3d272360681b84830152805192839101601983015e01016813979f1e17b9bb339f60b91b838201520301601619810184520182613f42565b95816101606101805101519a60405160c0527f3c7376672077696474683d2232393022206865696768743d22353030222076698260c05101527f6577426f783d2230203020323930203530302220786d6c6e733d22687474703a604060c0510152751797bbbbbb973b999737b933979918181817b9bb339160511b606060c05101527f20786d6c6e733a786c696e6b3d27687474703a2f2f7777772e77332e6f72672f607660c05101526b189c9c9c97bc3634b735939f60a11b609660c0510152651e3232b3399f60d11b60a260c05101527f3c66696c7465722069643d226631223e3c6665496d61676520726573756c743d60a860c05101527f2270302220786c696e6b3a687265663d22646174613a696d6167652f7376672b60c860c05101526a1e1b5b0ed8985cd94d8d0b60aa1b60e860c05101528051918291018560c051015e60c05101907f222f3e3c6665496d61676520726573756c743d2270312220786c696e6b3a6872848301525f80516020615c9983398151915261011383015280519283910161013183015e0101907f222f3e3c6665496d61676520726573756c743d2270322220786c696e6b3a6872848301525f80516020615c99833981519152605e830152805192839101607c83015e010190631110179f60e11b848301527f3c6665496d61676520726573756c743d2270332220786c696e6b3a687265663d60428301527a0899185d184e9a5b5859d94bdcdd99cade1b5b0ed8985cd94d8d0b602a1b6062830152805192839101607d83015e7f22202f3e3c6665426c656e64206d6f64653d226f7665726c61792220696e3d22910191909101848101919091527f70302220696e323d22703122202f3e3c6665426c656e64206d6f64653d226578605f8201527f636c7573696f6e2220696e323d22703222202f3e3c6665426c656e64206d6f64607f8201527f653d226f7665726c61792220696e323d2270332220726573756c743d22626c65609f820152780373227baba1110179f1e3332a3b0bab9b9b4b0b721363ab91603d1b60bf8201527f696e3d22626c656e644f75742220737464446576696174696f6e3d223432222060d88201527f2f3e3c2f66696c7465723e203c636c6970506174682069643d22636f726e657260f88201527f73223e3c726563742077696474683d2232393022206865696768743d223530306101188201527f222072783d223432222072793d22343222202f3e3c2f636c6970506174683e006101388201527f3c706174682069643d22746578742d706174682d612220643d224d34302031326101578201527f20483235302041323820323820302030203120323738203430205634363020416101778201527f32382032382030203020312032353020343838204834302041323820323820306101978201527f20302031203132203436302056343020413238203238203020302031203430206101b7820152671899103d1110179f60c11b6101d78201527f3c706174682069643d226d696e696d61702220643d224d3233342034343443326101df8201527f3334203435372e393439203234322e323120343633203235332034363322202f6101ff820152601f60f91b61021f8201527f3c66696c7465722069643d22746f702d726567696f6e2d626c7572223e3c66656102208201527f476175737369616e426c757220696e3d22536f757263654772617068696322206102408201527f737464446576696174696f6e3d22323422202f3e3c2f66696c7465723e0000006102608201527f3c6c696e6561724772616469656e742069643d22677261642d7570222078313d61027d8201527f2231222078323d2230222079313d2231222079323d2230223e3c73746f70206f61029d8201527f66667365743d22302e30222073746f702d636f6c6f723d2277686974652220736102bd820152713a37b816b7b830b1b4ba3c9e91189110179f60711b6102dd8201527f3c73746f70206f66667365743d222e39222073746f702d636f6c6f723d2277686102ef8201527f697465222073746f702d6f7061636974793d223022202f3e3c2f6c696e65617261030f8201526823b930b234b2b73a1f60b91b61032f8201527f3c6c696e6561724772616469656e742069643d22677261642d646f776e2220786103388201527f313d2230222078323d2231222079313d2230222079323d2231223e3c73746f706103588201527f206f66667365743d22302e30222073746f702d636f6c6f723d227768697465226103788201527f2073746f702d6f7061636974793d223122202f3e3c73746f70206f66667365746103988201527f3d22302e39222073746f702d636f6c6f723d227768697465222073746f702d6f6103b88201527f7061636974793d223022202f3e3c2f6c696e6561724772616469656e743e00006103d88201527f3c6d61736b2069643d22666164652d757022206d61736b436f6e74656e74556e6103f68201527f6974733d226f626a656374426f756e64696e67426f78223e3c726563742077696104168201527f6474683d223122206865696768743d2231222066696c6c3d2275726c282367726104368201527030b216bab8149110179f1e17b6b0b9b59f60791b6104568201527f3c6d61736b2069643d22666164652d646f776e22206d61736b436f6e74656e746104678201527f556e6974733d226f626a656374426f756e64696e67426f78223e3c72656374206104878201527f77696474683d223122206865696768743d2231222066696c6c3d2275726c28236104a78201527433b930b216b237bbb7149110179f1e17b6b0b9b59f60591b6104c78201527f3c6d61736b2069643d226e6f6e6522206d61736b436f6e74656e74556e6974736104dc8201527f3d226f626a656374426f756e64696e67426f78223e3c726563742077696474686104fc8201527f3d223122206865696768743d2231222066696c6c3d22776869746522202f3e3c61051c8201526517b6b0b9b59f60d11b61053c8201527f3c6c696e6561724772616469656e742069643d22677261642d73796d626f6c226105428201527f3e3c73746f70206f66667365743d22302e37222073746f702d636f6c6f723d226105628201527f7768697465222073746f702d6f7061636974793d223122202f3e3c73746f70206105828201527f6f66667365743d222e3935222073746f702d636f6c6f723d22776869746522206105a28201527f73746f702d6f7061636974793d223022202f3e3c2f6c696e65617247726164696105c28201526332b73a1f60e11b6105e28201527f3c6d61736b2069643d22666164652d73796d626f6c22206d61736b436f6e74656105e68201527f6e74556e6974733d227573657253706163654f6e557365223e3c7265637420776106068201527f696474683d22323930707822206865696768743d223230307078222066696c6c6106268201527f3d2275726c2823677261642d73796d626f6c2922202f3e3c2f6d61736b3e3c2f610646820152643232b3399f60d91b6106668201527f3c6720636c69702d706174683d2275726c2823636f726e65727329223e00000061066b8201526b1e3932b1ba103334b6361e9160a11b610688820152815192909183910161069483015e01017f2220783d223070782220793d22307078222077696474683d223239307078222082820152703432b4b3b43a1e911a9818383c1110179f60791b6106758201527f3c72656374207374796c653d2266696c7465723a2075726c28236631292220786106868201527f3d223070782220793d22307078222077696474683d22323930707822206865696106a68201526d33b43a1e911a9818383c1110179f60911b6106c68201527f203c67207374796c653d2266696c7465723a75726c2823746f702d726567696f6106d48201527f6e2d626c7572293b207472616e73666f726d3a7363616c6528312e35293b20746106f48201527f72616e73666f726d2d6f726967696e3a63656e74657220746f703b223e0000006107148201527f3c726563742066696c6c3d226e6f6e652220783d223070782220793d223070786107318201527f222077696474683d22323930707822206865696768743d22353030707822202f610751820152601f60f91b6107718201527f3c656c6c697073652063783d22353025222063793d22307078222072783d22316107728201527f38307078222072793d223132307078222066696c6c3d222330303022206f70616107928201527131b4ba3c9e9118171c1a9110179f1e17b39f60711b6107b28201527f3c7265637420783d22302220793d2230222077696474683d22323930222068656107c48201527f696768743d22353030222072783d223432222072793d223432222066696c6c3d6107e48201527f227267626128302c302c302c302922207374726f6b653d2272676261283235356108048201527416191a9a96191a9a96181719149110179f1e17b39f60591b61082482015260c0519003016101c4810160c051520160c051613f42565b61217f608b6005610100610180515160206101805101518360606101805101519160806101805101519060405186527f3c7465787420746578742d72656e646572696e673d226f7074696d697a6553706020875101526432b2b2111f60d91b6040875101527f3c74657874506174682073746172744f66667365743d222d31303025222066696045875101527f6c6c3d2277686974652220666f6e742d66616d696c793d2227436f75726965726065875101527f204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d223130706085875101527f782220786c696e6b3a687265663d2223746578742d706174682d61223e00000060a5875101528281516020830190808260c28b51015e8851019264010714051160dd1b60c285015260c285516020870195818760c783015e0101905f80516020615c79833981519152848301525f80516020615d5983398151915260258301525f80516020615d398339815191526045830152783832b0ba21b7bab73a1e9134b73232b334b734ba329110179f60391b60658301527f3c2f74657874506174683e203c74657874506174682073746172744f66667365607e8301527f743d223025222066696c6c3d2277686974652220666f6e742d66616d696c793d609e8301527f2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d60be8301527f73697a653d22313070782220786c696e6b3a687265663d2223746578742d706160de830152653a3416b0911f60d11b60fe83015251809261010483015e01019164010714051160dd1b6103405184015251809161010484015e610340519101015f80516020615c79833981519152828201525f80516020615d5983398151915260258201525f80516020615d3983398151915260458201527f70656174436f756e743d22696e646566696e69746522202f3e203c2f746578746065820152642830ba341f60d91b60858201527f3c74657874506174682073746172744f66667365743d22353025222066696c6c608a8201527f3d2277686974652220666f6e742d66616d696c793d2227436f7572696572204e60aa8201527f6577272c206d6f6e6f73706163652220666f6e742d73697a653d22313070782260ca8201527a103c3634b7359d343932b31e9111ba32bc3a16b830ba3416b0911f60291b60ea8201528184516020860192818461010583015e01019364010714051160dd1b868601528584516020860196818861010583015e0101905f80516020615c79833981519152848301525f80516020615d5983398151915260258301527f6f3d22313030252220626567696e3d22307322206475723d223330732200000060458301527f20726570656174436f756e743d22696e646566696e69746522202f3e3c2f746560628301527f7874506174683e3c74657874506174682073746172744f66667365743d222d3560828301527f3025222066696c6c3d2277686974652220666f6e742d66616d696c793d22274360a28301527f6f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a60c28301527f653d22313070782220786c696e6b3a687265663d2223746578742d706174682d60e28301526230911f60e91b6103a05183015251809261010583015e01019064010714051160dd1b8483015251809261010583015e01015f80516020615c79833981519152828201525f80516020615d5983398151915260258201525f80516020615d3983398151915260458201527f70656174436f756e743d22696e646566696e69746522202f3e3c2f746578745060658201526a30ba341f1e17ba32bc3a1f60a91b608582015261010051900301606b810161010051520161010051613f42565b6020612418607e60776060610180510151600185608061018051015160ed8260a0610180510151926040519a8b977f3c67206d61736b3d2275726c2823666164652d73796d626f6c29223e3c726563828a01527f742066696c6c3d226e6f6e652220783d223070782220793d223070782220776960408a01527f6474683d22323930707822206865696768743d22323030707822202f3e203c7460608a01527f65787420793d22373070782220783d2233327078222066696c6c3d227768697460808a01527f652220666f6e742d66616d696c793d2227436f7572696572204e6577272c206d60a08a01527f6f6e6f73706163652220666f6e742d7765696768743d223230302220666f6e7460c08a01526c16b9b4bd329e91199b383c111f60991b60e08a0152805191829101858a015e870190602f60f81b8483015280519283910160ee83015e0101907f3c2f746578743e3c7465787420793d2231313570782220783d22333270782220848301527f66696c6c3d2277686974652220666f6e742d66616d696c793d2227436f75726960218301527f6572204e6577272c206d6f6e6f73706163652220666f6e742d7765696768743d6041830152761119181811103337b73a16b9b4bd329e91199b383c111f60491b6061830152805192839101607883015e01016a1e17ba32bc3a1f1e17b39f60a91b838201527f3c7265637420783d2231362220793d223136222077696474683d22323538222060828201527f6865696768743d22343638222072783d223236222072793d223236222066696c60a28201527f6c3d227267626128302c302c302c302922207374726f6b653d2272676261283260c2820152721a9a96191a9a96191a9a96181719149110179f60691b60e28201520301605e810184520182613f42565b60c061018051015160020b9060e061018051015160020b9161010061018051015160020b906101206101805101515f0b90600182145f14613b2957604051612461604082613f42565b6008815267023666164652d75760c41b6020820152945b03627fffff198112627fffff8213176137e25760020b908215613b1557627fffff1982145f198414166137e25761293f926048920560020b600481136139365750607960206040516124cb604082613f42565b601a8152794d3120314334312034312031303520313035203134352031343560301b82820152925b60406101608190528051906125089082613f42565b6002815261373360f01b838201908152610160518051939061252a9085613f42565b60038452848401906203139360ec1b825261016051519261254e6101605185613f42565b60038452868401926232313760e81b84526101605151936125726101605186613f42565b6003855288850191620ccccd60ea1b8352600185146001860361392c575b15613840575050505092602786602a946008828196602c82809c6126c39c5f191493845f14613839578a5b85156138325782985b861561382a5750945b156138225750955b61016051516b1e31b4b931b6329031bc1e9160a11b8f8201528a51909e8f9b829101858d015e8a019067383c111031bc9e9160c11b84830152805192839101603483015e0101907f70782220723d22347078222066696c6c3d22776869746522202f3e3c63697263848301526636329031bc1e9160c91b6028830152805192839101602f83015e01019067383c111031bc9e9160c11b84830152805192839101602f83015e01017f70782220723d2232347078222066696c6c3d226e6f6e6522207374726f6b653d8382015269113bb434ba329110179f60b11b60288201520301600a810184520182613f42565b606561016051519889956c078ce40dac2e6d67a44eae4d85609b1b85880152858251868401908082602d8c015e89019361149160f11b602d8601525f80516020615dd9833981519152602f8601527f2c313839707829223e3c7265637420783d222d313670782220793d222d313670604f8601527f78222077696474683d22313830707822206865696768743d2231383070782220606f860152763334b6361e913737b7329110179f1e3830ba3410321e9160491b608f860152602d845189860196818860a683015e0101907f22207374726f6b653d227267626128302c302c302c302e332922207374726f6b848301527f652d77696474683d2233327078222066696c6c3d226e6f6e6522207374726f6b6099830152733296b634b732b1b0b81e913937bab7321110179f60611b60b9830152700785ece7c78ce40dac2e6d67a44eae4d85607b1b60cd83015251809260de83015e01019061149160f11b848301525f80516020615dd983398151915260678301526816189c1cb83c14911f60b91b60878301527f3c7265637420783d222d313670782220793d222d31367078222077696474683d60908301527f22313830707822206865696768743d223138307078222066696c6c3d226e6f6e60b083015264329110179f60d91b60d0830152681e3830ba3410321e9160b91b60d583015251809260de83015e0101907f22207374726f6b653d2272676261283235352c3235352c3235352c3129222066848301527f696c6c3d226e6f6e6522207374726f6b652d6c696e656361703d22726f756e646099830152671110179f1e17b39f60c11b60b983015280519283910160c183015e01015f838201520301601f198101845283613f42565b61295061014061018051015161492e565b60018060a01b0360406101805101511660c061018051015160020b9160e061018051015160020b9261298183615481565b60e05261298d8161591c565b6129968561591c565b928051946004860186116137e2576136bb576129b06142f9565b80519360058501928386116136a357845191600a83018084116136a357885195600a8701928388116136a35760049c6129e891615a45565b9c909b6008810191829101116136a357806007029060078204036136a357612a1160099161492e565b99018091116136a357806007029060078204036136a357612a33600e9161492e565b94018091116136a357806007029060078204036136a357612a55600e9161492e565b95018091116136a35760078181020481036136a357600702612a769061492e565b9561016051516080526080516020015f80516020615d9983398151915290526c1cb83c1610199a9a383c14911f60991b6101605160805101526c1e3932b1ba103bb4b23a341e9160991b608051604d015280516020819201608051605a015e60805101605a0160a0518152612aea906156bc565b5f80516020615cf98339815191528152602081015f80516020615cd983398151915290526101605181015f80516020615d798339815191529052606081015f80516020615d198339815191529052608081016c1f24a21d101e17ba39b830b71f60991b905281516020819301608d83015e6a1e17ba32bc3a1f1e17b39f60a91b608d92909101918201525f80516020615d9983398151915260988201526c1cb83c1610199c1a383c14911f60991b60b88201526c1e3932b1ba103bb4b23a341e9160991b60c5820152815191829060200160d283015e01608d0160450160a0518152612bd5906156bc565b5f80516020615cf98339815191528152602081015f80516020615cd983398151915290526101605181015f80516020615d798339815191529052606081015f80516020615d198339815191529052608081016e1f2437b7b59d101e17ba39b830b71f60891b905281516020819301608f83015e6a1e17ba32bc3a1f1e17b39f60a91b608f92909101918201525f80516020615d99833981519152609a8201526c1cb83c16101a189a383c14911f60991b60ba8201526c1e3932b1ba103bb4b23a341e9160991b60c7820152815191829060200160d483015e01608f0160450160a0518152612cc2906156bc565b5f80516020615cf98339815191528152602081015f80516020615cd983398151915290526101605181015f80516020615d798339815191529052606081015f80516020615d19833981519152905260808101721f26b4b7102a34b1b59d101e17ba39b830b71f60691b905281516020819301609383015e6a1e17ba32bc3a1f1e17b39f60a91b609392909101918201525f80516020615d99833981519152609e8201526c1cb83c16101a1a1a383c14911f60991b60be8201526c1e3932b1ba103bb4b23a341e9160991b60cb820152815191829060200160d883015e0160930160450160a0518152612db3906156bc565b5f80516020615cf98339815191528152602081015f80516020615cd983398151915290526101605181015f80516020615d798339815191529052606081015f80516020615d19833981519152905260808101721f26b0bc102a34b1b59d101e17ba39b830b71f60691b905281516020819301609383015e7f3c2f746578743e3c2f673e3c67207374796c653d227472616e73666f726d3a7460939290910191820152773930b739b630ba329419191b383c16101a1999b83c14911f60411b60b38201527f3c726563742077696474683d223336707822206865696768743d22333670782260cb8201527f2072783d22387078222072793d22387078222066696c6c3d226e6f6e6522207360eb8201527f74726f6b653d2272676261283235352c3235352c3235352c302e322922202f3e61010b8201527f3c70617468207374726f6b652d6c696e656361703d22726f756e642220643d2261012b8201527f4d38203943382e30303030342032322e393439342031362e323039392032382061014b8201527f3237203238222066696c6c3d226e6f6e6522207374726f6b653d22776869746561016b820152631110179f60e11b61018b8201527f3c636972636c65207374796c653d227472616e73666f726d3a7472616e736c6161018f820152640e8ca66c8560db1b6101af82015281519182906020016101b483015e016093016101218101630383c16160e51b90528151602081930161012583015e7f70782c2030707829222063783d22307078222063793d223070782220723d2234610125929091019182015275383c11103334b6361e913bb434ba3291179f1e17b39f60511b6101458201526080805161013b9281900392830190525161303b9161015b0190613f42565b61018051610140015191610180516040015160a0515060606101605151906020820192868452600160601b6001900319911b166101605182015260348152613084605482613f42565b5190209280156100a9578060018060801b031060071b81811c60018060401b031060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c610340511060031b17906f8421084210842108cc6318c6db6d54be7b01c1818141808140018080c0814100004181408140c0c100414140c160221b91831c1c601f161a1760011b6101fe811660fe8216036136a35760fe9060a0515016600101906103405182116136a3576103405182161561368b5761360f6020610d9e6002602761353c84610d9e6006829b83603d9b61366c9f61365e9e61034051165f1904115f14613670578161016051517f3c67207374796c653d227472616e73666f726d3a7472616e736c617465283232828201527f3670782c20333932707829223e3c726563742077696474683d22333670782220610160518201527f6865696768743d2233367078222072783d22387078222072793d22387078222060608201527f66696c6c3d226e6f6e6522207374726f6b653d2272676261283235352c32353560808201526c16191a9a96181719149110179f60991b60a08201527f3c673e3c70617468207374796c653d227472616e73666f726d3a7472616e736c60ad8201527f617465283670782c367078292220643d224d313220304c31322e36353232203960cd8201527f2e35363538374c313820312e363037374c31332e373831392031302e3231383160ed82015272026191917199c9919901b26189a171a199a189606d1b61010d8201527f31312e333437384c32342031324c31342e343334312031322e363532324c32326101208201527f2e333932332031384c31332e373831392031332e373831394c31382032322e336101408201527f3932334c31322e363532322031342e343334314c31322032344c31312e33343761016082015270382031342e343334314c362032322e333960781b610240518201527f32334c31302e323138312031332e373831394c312e363037372031384c392e356101918201527f363538372031322e363532324c302031324c392e35363538372031312e3334376101b18201527f384c312e3630373720364c31302e323138312031302e323138314c3620312e366101d18201527f3037374c31312e3334373820392e35363538374c313220305a222066696c6c3d6101f182015269113bb434ba329110179f60b11b6102118201527f3c616e696d6174655472616e73666f726d206174747269627574654e616d653d61021b8201527f227472616e73666f726d2220747970653d22726f74617465222066726f6d3d2261023b8201527f302031382031382220746f3d2233363020313820313822206475723d2231307361025b8201527f2220726570656174436f756e743d22696e646566696e697465222f3e3c2f673e61027b820152631e17b39f60e11b61029b82015261027f81526134ac61029f82613f42565b915b61016051519788958160c05151808260c05101838b015e88018181019060a051825261010051518092846101005101905e01019060a0518252805192839101825e019060a0518252805192839101825e0160a05181526080515190818460805101825e019060a0518252805192839101825e01651e17b9bb339f60d11b815203601919810184520182613f42565b6101605151948591683d913730b6b2911d1160b91b82840152601260296103e0515180856103e051018388015e850171111610113232b9b1b934b83a34b7b7111d1160711b8282015261040051519081866104005101603b83015e01018181019060a05182526103c051518092866103c05101905e0101906c1116101134b6b0b3b2911d101160991b82527919185d184e9a5b5859d94bdcdd99cade1b5b0ed8985cd94d8d0b60321b600d8301528051928391018583015e0161227d60f01b838201520301601d19810184520182613f42565b61016051519384917f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000828401528051918291018484015e810160a051838201520301601f198101835282613f42565b610160515191829182613e00565b0390f35b8161016051516136808282613f42565b60a0518152916134ae565b634e487b7160e01b60a051526012600452602460a051fd5b634e487b7160e01b60a051526011600452602460a051fd5b60055f60a0526136cb6005613f65565b610140526101605151610120526136e86101405161012051613f42565b600561012051526101205150601f196137016005613f65565b013660206101205101375f5b8181106137f65750505f60a052600361372581613f65565b61373461016051519182613f42565b818152601f1961374383613f65565b0136602083013760275b602a81106137ac5750602091816137a792508361016051519485926101205151808361012051018487015e8401906217171760e91b83830152805192839101602383015e01015f838201520301601f198101835282613f42565b6129b0565b60ff60f81b6137bd8260e051613fdc565b51169060261981018181116137e2576137db6001935f1a9185613fdc565b530161374d565b634e487b7160e01b5f52601160045260245ffd5b60019060ff60f81b61380a8260e051613fdc565b51165f1a61381b8261012051613fdc565b530161370d565b9050956125d5565b9050946125cd565b81986125c4565b879a6125bb565b61392797945060089591601b97602c88936027979c61016051519d8e9a6b1e31b4b931b6329031bc1e9160a11b60208d0152518091858d015e8a019067383c111031bc9e9160c11b84830152518092603483015e0101907a383c1110391e911a383c11103334b6361e913bb434ba329110179f60291b848301526b1e31b4b931b6329031bc1e9160a11b6023830152518092602f83015e01019067383c111031bc9e9160c11b84830152518092602f83015e01017a383c1110391e911a383c11103334b6361e913bb434ba329110179f60291b838201520301600419810184520182613f42565b6126c3565b505f198514612590565b6008811361397c575060796020604051613951604082613f42565b60198152784d31203143333320343920393720313133203134352031343560381b82820152926124f3565b601081136139c2575060796020604051613997604082613f42565b60198152784d31203143333320353720383920313133203134352031343560381b82820152926124f3565b60208113613a085750607960206040516139dd604082613f42565b60198152784d31203143323520363520383120313231203134352031343560381b82820152926124f3565b60408113613a4e575060796020604051613a23604082613f42565b60198152784d31203143313720373320373320313239203134352031343560381b82820152926124f3565b60808113613a93575060796020604051613a69604082613f42565b60188152774d312031433920383120363520313337203134352031343560401b82820152926124f3565b61010012613ad95760796020604051613aad604082613f42565b601a8152794d31203143312038392035372e3520313435203134352031343560301b82820152926124f3565b60796020604051613aeb604082613f42565b60188152774d312031433120393720343920313435203134352031343560401b82820152926124f3565b634e487b7160e01b5f52601260045260245ffd5b5f198203613b5d57604051613b3f604082613f42565b600a81526911b330b23296b237bbb760b11b60208201525b94612478565b604051613b6b604082613f42565b6005815264236e6f6e6560d81b6020820152613b57565b634e487b7160e01b5f52604160045260245ffd5b82613ba2602a92615481565b95610680565b82613bb4600292615481565b61065b565b82613bc5600a92615481565b92610639565b6101006102c051015160020b9161039f565b6101206102c051015160020b610368565b9050956101d3565b81926101cb565b9093506020813d602011613c2d575b81613c1960209383613f42565b81010312613c2957519285610196565b5f80fd5b3d9150613c0c565b6040513d5f823e3d90fd5b8263ed15e6cf60e01b5f5260045260245ffd5b9150508060c03d60c011613d07575b613c6c8183613f42565b81010360c08112613c295760a013613c29576040519060a082016001600160401b03811183821017613b8257604052613ca4816140b7565b8252613cb2602082016140b7565b6020830152604081015162ffffff81168103613c2957604083015260608101518060020b8103613c295760608301526080810151906001600160a01b0382168203613c295760a0916080840152015183610104565b503d613c62565b34613c29576040366003190112613c2957613d27613dea565b6024356001600160a01b0381168103613c2957613d4e613d48602093613e2a565b91613e2a565b12604051908152f35b34613c29575f366003190112613c29576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34613c29575f366003190112613c295761366c613db6614001565b60405191829182613e00565b34613c29576020366003190112613c2957602090613de6613de1613dea565b613e2a565b8152f35b600435906001600160a01b0382168203613c2957565b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b6001600160a01b031680158015613f02575b613efb5760014614613e4e575b505f90565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488103613e70575061012c90565b73dac17f958d2ee523a2206206994597c13d831ec78103613e91575060c890565b736b175474e89094c44da98b954eedeac495271d0f8103613eb25750606490565b738daebade922df735c38c80c7ebd708af50815faa8103613ed4575060c71990565b732260fac5e5542a773aa44fbcfedf7c193bc2c59914613ef4575f613e49565b61012b1990565b5060631990565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168114613e3c565b5f1981146137e25760010190565b601f909101601f19168101906001600160401b03821190821017613b8257604052565b6001600160401b038111613b8257601f01601f191660200190565b613f8a6006613f65565b90613f986040519283613f42565b6006825281601f19613faa6006613f65565b0190602036910137565b90613fbe82613f65565b613fcb6040519182613f42565b8281528092613faa601f1991613f65565b908151811015613fed570160200190565b634e487b7160e01b5f52603260045260245ffd5b5f5b602081108061407b575b156140205761401b90613f34565b614003565b61402981613fb4565b907f0000000000000000000000000000000000000000000000000000000000000000905f5b81811061405b5750505090565b6020811015613fed5780836001921a6140748287613fdc565b530161404e565b15613fed577f0000000000000000000000000000000000000000000000000000000000000000811a60f81b6001600160f81b031916151561400d565b51906001600160a01b0382168203613c2957565b6001600160a01b038116915f9190831561421e57506140e99061431e565b9182511561416b5750600c8251116140ff575090565b9061410a600c613f65565b916141186040519384613f42565b600c8352601f19614129600c613f65565b01366020850137805b600c81106141405750505090565b6001906001600160f81b03196141568286613fdc565b5116831a6141648287613fdc565b5301614132565b915050614176613f80565b905f5b6003811061418657505090565b80601303601381116137e2576001600160fd1b03811681036137e257829060031b1c9060f080600f198416161660ff8316039160ff83116137e257600f6141d09160041c1661561f565b600182901b926001600160ff1b03831683036137e2576141fc915f1a6141f68588613fdc565b5361561f565b91600181018091116137e2576142176001935f1a9186613fdc565b5301614179565b9250505090565b3d1561424f573d9061423682613f65565b916142446040519384613f42565b82523d5f602084013e565b606090565b6001600160a01b038116156142cf575f8091604051602081019063313ce56760e01b825260048152614287602482613f42565b51915afa614293614225565b9015613e49578051602081146142aa575b50505f90565b8160209181010312613c29576020015160ff8111156142c957806142a4565b60ff1690565b50601290565b604051906142e4604083613f42565b60068252654e617469766560d01b6020830152565b60405190614308604083613f42565b60078252664e6f20486f6f6b60c81b6020830152565b5f809160405160208101906395d89b4160e01b825260048152614342602482613f42565b51915afa61434e614225565b90156144ad57805160208103614420575060208151918180820193849201010312613c2957519060405191614384604084613f42565b602080845236848201375f905f5b602081106143e15750506143a581613fb4565b905f5b8181106143b6575090925050565b6001906001600160f81b03196143cc8288613fdc565b51165f1a6143da8286613fdc565b53016143a8565b81811a60f881901b6001600160f81b031916614401575b50600101614392565b83614419916144136001949689613fdc565b53613f34565b92906143f8565b6040811161443e575050604051614438602082613f42565b5f815290565b810190602081818401930312613c29576020810151906001600160401b038211613c29570181603f82011215613c295760208101519061447d82613f65565b9261448b6040519485613f42565b82845260408284010111613c2957815f926040602093018386015e8301015290565b50604051614438602082613f42565b60ff1660ff81146137e25760010190565b6040519061010082016001600160401b03811183821017613b82576040525f60e0838281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b919082039182116137e257565b90601082018092116137e257565b90606482018092116137e257565b919082018092116137e257565b60ff5f199116019060ff82116137e257565b60ff6004199116019060ff82116137e257565b604d81116137e257600a0a90565b8115613b15570490565b62ffffff8116906280000082146148015781156147df575f9262ffffff5f925b169182156146195760ff8116156145de57600a6145d66145d062ffffff936144bc565b96613f34565b9593046145ad565b9362ffffff600a8406166145fc575b600a6145d662ffffff92613f34565b93600a6145d661460f62ffffff936144bc565b96925050506145ed565b90939291506146266144cd565b916005841061475f5760ff8216916004614640848761451a565b106147565760ff5f5b169260041986018681116137e25760ff61466284614550565b1681101561473a57505f905b60808601918183526146808183614543565b5f198101939084116137e2576146b18760ff6146ab8180958d60a0836146bc9c169101525116614550565b16614543565b166040880152614543565b92600184018094116137e25760ff6146f292816146df6146ed946146f898614543565b1660208801525b168661451a565b614575565b90614583565b8152600160e0820152600482111561472d5760031982019182116137e25760ff8061472a93165b166060820152614be7565b90565b61472a915060ff5f61471f565b6147509060ff61474985614550565b169061451a565b9061466e565b60ff6001614649565b83600503600581116137e2576002608085015260028101908181116137e257600181019182116137e25760ff61479f921660a086015260ff841690614543565b600281018091116137e25760ff168060208501526001190160ff81116137e2576146ed60ff6146f894816146f294166040880152600160c08801526146e6565b50506040516147ef604082613f42565b6002815261302560f01b602082015290565b5050604051614811604082613f42565b600781526644796e616d696360c81b602082015290565b905f805b835160ff82169081101561488157614859906001600160f81b0319906148529087613fdc565b5116615413565b61486c575b614867906144bc565b61482c565b90614879614867916144bc565b91905061485e565b505060ff168061488e5750565b61489c6148a1918451614543565b613fb4565b5f925f5b815160ff8216908110156149265761490691906148ce6001600160f81b03196148528387613fdc565b61490b575b6001600160f81b0319906148e79085613fdc565b5116956149006148f682613f34565b975f1a9186613fdc565b536144bc565b6148a5565b605c61492061491989613f34565b9887613fdc565b536148d3565b509193505050565b5f908072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b811015614a53575b600a906904ee2d6d415b85acef8160201b811015614a37575b662386f26fc10000811015614a23575b6305f5e100811015614a12575b612710811015614a03575b60648110156149f5575b10156149ea575b600a60216149b260018501613fb4565b938401015b5f1901916f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530480156149e557600a90916149b7565b505090565b6001909101906149a2565b60646002910493019261499b565b61271060049104930192614991565b6305f5e10060089104930192614986565b662386f26fc1000060109104930192614979565b602093909301926904ee2d6d415b85acef8160201b9004614969565b506040915072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8104614950565b818102929181159184041417156137e257565b90815115614bc55760405191614aa0606084613f42565b604083527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208401527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f60408401528051600281018091116137e257600390046001600160fe1b03811681036137e257614b1d9060021b613fb4565b90602082019080815182019560208701908151925f83525b888110614b775750506003939495965052510680600114614b6557600214614b5b575090565b603d905f19015390565b50603d90815f19820153600119015390565b600360049199969901986001603f8b5182828260121c16870101518453828282600c1c16870101518385015382828260061c1687010151600285015316840101516003820153019497614b35565b9050604051614438602082613f42565b60ff60019116019060ff82116137e257565b614bf760ff602083015116613fb4565b9060e0810151614d1a575b60c0810151614cf6575b60ff6080820151165b60ff614c268160a085015116614bd5565b16811015614c4457806030614c3d60019386613fdc565b5301614c15565b50915b825115614cf15760ff6060840151168015159081614ce0575b50614cb4575b600a835106603001806030116137e257604084018051909160f81b6001600160f81b0319165f1a90614c9b9060ff1685613fdc565b5360ff5f198183511601169052600a8351048352614c47565b6040830160ff8151169081156137e2575f19820160ff169052602e90614cda9084613fdc565b53614c66565b905060ff604085015116145f614c60565b915090565b815115613fed5760306020830153815160011015613fed57602e6021830153614c0c565b81515f1981019081116137e257614d3360259184613fdc565b53614c02565b9060020b9060020b02908160020b9182036137e257565b60405190614d5f604083613f42565b600382526226a4a760e91b6020830152565b60405190614d80604083613f42565b600382526209a82b60eb1b6020830152565b909392938060020b8015613b1557614db08282620d89e71905614d39565b600293840b930b8303614dda57505050509050155f14614dd25761472a614d50565b61472a614d71565b90614de991620d89e805614d39565b60020b8103614e0c57505015159050614e045761472a614d71565b61472a614d50565b8060ff1d8181011890620d89e882116154015763ffffffff91600160801b7001fffcb933bd6fad37aa2d162d1a5940016001831602189190600281166153e5575b600481166153c9575b600881166153ad575b60108116615391575b60208116615375575b60408116615359575b6080811661533d575b6101008116615321575b6102008116615305575b61040081166152e9575b61080081166152cd575b61100081166152b1575b6120008116615295575b6140008116615279575b618000811661525d575b620100008116615241575b620200008116615226575b62040000811661520b575b62080000166151f2575b5f126151ea575b0160201c916151c5575b60ff80911692168083035f8212848212811690858313901516176137e2575f81126151b257925b831515806151a7575b156151955760019283929091111561516957614f6d90614f6085841c614575565b90838060a01b0316614a76565b92161461515b575b614f7f8180615826565b600160601b9190911190811561514c57614f98906158b9565b905b815f815b61513857614fac9150614550565b905f83600560ff85161161510c575b50600a6004818606119404936150fa575b620186a084146150ec575b6150dc575b614fe46144cd565b9181156150605760ff16602b039260ff84116137e25760ff84166007019360ff85116137e25760ff602085019516855260026080850152602b81116137e257600181018091116137e25761504760ff61472a968180941660a08801525116614550565b1660408401525b825260c08201525f60e0820152614be7565b60ff811690600982106150aa5750600319019260ff84116137e25760ff6150988161472a961680602087015260056080870152614550565b1660a08401526004604084015261504e565b61472a9491506150d16150cc60ff926006602088015260056040880152614562565b614bd5565b16606084015261504e565b906150e6906144bc565b90614fdc565b5091600a9004916001614fd7565b92600181018091116137e25792614fcc565b90935060ff61511a84614562565b1690604d82116137e25761513191600a0a90614583565b925f614fbb565b615143600a916144bc565b91049081614f9e565b6151559061586f565b90614f9a565b615164906157aa565b614f75565b6151859061517885841c614575565b90838060a01b0316614583565b921603614f75576151649061570b565b50506001600160a01b03169050614f75565b506012841115614f3f565b600160ff1b81146137e2575f0392614f36565b906001600160a01b03168015613b1557600160c01b046001600160a01b031690614f0f565b5f1904614f05565b6b048a170391f7dc42444e8fa290910260801c90614efe565b6d2216e584f5fa1ea926041bedfe9890920260801c91614ef4565b916e5d6af8dedb81196699c329225ee6040260801c91614ee9565b916f09aa508b5b7a84e1c677de54f3e99bc90260801c91614ede565b916f31be135f97d08fd981231505542fcfa60260801c91614ed3565b916f70d869a156d2a1b890bb3df62baf32f70260801c91614ec9565b916fa9f746462d870fdf8a65dc1f90e061e50260801c91614ebf565b916fd097f3bdfd2022b8845ad8f792aa58250260801c91614eb5565b916fe7159475a2c29b7443b29c7fa6e889d90260801c91614eab565b916ff3392b0822b70005940c7a398e4b70f30260801c91614ea1565b916ff987a7253ac413176f2b074cf7815e540260801c91614e97565b916ffcbe86c7900a88aedcffc83b479aa3a40260801c91614e8d565b916ffe5dee046a99a2a811c461f1969c30530260801c91614e83565b916fff2ea16466c96a3843ec78b326b528610260801c91614e7a565b916fff973b41fa98c081472e6896dfb254c00260801c91614e71565b916fffcb9843d60f6159c9db58835c9266440260801c91614e68565b916fffe5caca7e10e4e61c3624eaa0941cd00260801c91614e5f565b916ffff2e50f5f656932ef12357cf3c7fdcc0260801c91614e56565b916ffff97272373d413259a46990580e213a0260801c91614e4d565b6345c3193d60e11b5f5260045260245ffd5b60ff60f81b16601160f91b8114908115615467575b8115615459575b811561544b575b8115615440575090565b600960f81b14919050565b600d60f81b81149150615436565b600560f91b8114915061542f565b600360fa1b81149150615428565b80156137e2575f190190565b8061548c602a613f65565b9161549a6040519384613f42565b602a83526154a8602a613f65565b6020840190601f1901368237835115613fed5760309053825160011015613fed576078602184015360295b600181116154fb57506154e4575090565b63e22e27eb60e01b5f52600452601460245260445ffd5b90600f8116906010821015613fed57615538916f181899199a1a9b1b9c1cb0b131b232b360811b901a61552e8487613fdc565b5360041c91615475565b6154d3565b600292830b920b8212156155525750505f1990565b60020b121561556057600190565b5f90565b60881c61556f613f80565b90815190815b61557e57505090565b600f8116906010821015613fed575f1983018381116137e2576155bc926f181899199a1a9b1b9c1cb0b131b232b360811b901a9061552e9086613fdc565b9081615575565b6155cb613f80565b90815190815b6155da57505090565b600f8116906010821015613fed575f1983018381116137e257615618926f181899199a1a9b1b9c1cb0b131b232b360811b901a9061552e9086613fdc565b90816155d1565b60ff16600a8110156156465760300160ff81116137e25760f81b6001600160f81b03191690565b60370160ff81116137e25760f81b6001600160f81b03191690565b5f80516020615cb983398151915281525f80516020615db983398151915260208201527f2f2f7777772e77332e6f72672f323030302f737667273e3c636972636c652063604082015262783d2760e81b606082015260630190565b7f707822206865696768743d2232367078222072783d22387078222072793d223881527f7078222066696c6c3d227267626128302c302c302c302e362922202f3e0000006020820152603d0190565b608081901b5f19600160801b83098180821091039080820391827003298b075b4b6a5240945790619b37fd4a1115613c295714615791577f1f514b8ee5362595de309a65c03ce543f7e851e1625ea646b8fe88b81023b92d927003298b075b4b6a5240945790619b37fd4a90600160801b900990828211900360ff1b910360011c170290565b507003298b075b4b6a5240945790619b37fd4a91500490565b7003298b075b4b6a5240945790619b37fd4a8102905f197003298b075b4b6a5240945790619b37fd4a820990828083109203918083039283600160801b1115613c29571461581e57600160801b907003298b075b4b6a5240945790619b37fd4a900990828211900360801b910360801c1790565b505060801c90565b81810291905f1982820991838084109303928084039384600160401b1115613c29571461586657600160401b910990828211900360c01b910360401c1790565b50505060401c90565b620186a08102905f19620186a0820990828083109203918083039283600160801b1115613c29571461581e57600160801b90620186a0900990828211900360801b910360801c1790565b6c47bf19673df52e37f2410011d1602c1b81810291905f1990820990828083109203918083039283600160801b1115613c29571461581e57600160801b906c47bf19673df52e37f2410011d1602c1b900990828211900360801b910360801c1790565b60209060405161592c8382613f42565b5f8152828260020b5f8112615983575b508061594f62ffffff61472a951661492e565b6040519584879551918291018487015e8401908282015f8152815193849201905e01015f815203601f198101835282613f42565b925050505f038060020b9081036137e25761472a90828061594f62ffffff6040516159af604082613f42565b60018152602d60f81b84820152949550505061593c565b604051906159d5604083613f42565b6002825261323760f01b6020830152565b604051906159f5604083613f42565b6002825261323160f01b6020830152565b60405190615a15604083613f42565b6002825261062760f31b6020830152565b60405190615a35604083613f42565b60018252600760fb1b6020830152565b9060020b9060020b01627fffff198112627fffff8213176137e257600290810b0560020b6201e8471981125f14615a9f5750615a7f615a26565b90604051615a8e604082613f42565b60018152603760f81b602082015290565b620124f719811215615ad75750615ab4615a26565b90604051615ac3604082613f42565b600481526331302e3560e01b602082015290565b6161a719811215615b0f5750615aeb615a26565b90604051615afa604082613f42565b600581526431342e323560d81b602082015290565b61138719811215615b415750604051615b29604082613f42565b6002815261031360f41b60208201529061472a615a06565b5f811215615b705750604051615b58604082613f42565b6002815261313160f01b60208201529061472a6159e6565b611388811215615bb95750604051615b89604082613f42565b6002815261313360f01b602082015290604051615ba7604082613f42565b6002815261323360f01b602082015290565b6161a8811215615c025750604051615bd2604082613f42565b6002815261313560f01b602082015290604051615bf0604082613f42565b6002815261323560f01b602082015290565b620124f8811215615c375750615c16615a06565b90604051615c25604082613f42565b6002815261191b60f11b602082015290565b6201e8481315615c5257615c496159e6565b9061472a6159c6565b604051615c60604082613f42565b60028152610c8d60f21b60208201529061472a6159c656fe203c616e696d6174652061646469746976653d2273756d22206174747269627565663d22646174613a696d6167652f7376672b786d6c3b6261736536342c00003c7376672077696474683d2732393027206865696768743d2735303027207669696c793d2227436f7572696572204e6577272c206d6f6e6f73706163652220663c7465787420783d22313270782220793d22313770782220666f6e742d66616d70616e2066696c6c3d2272676261283235352c3235352c3235352c302e3629226f3d22313030252220626567696e3d22307322206475723d223330732220726574654e616d653d2273746172744f6666736574222066726f6d3d2230252220746f6e742d73697a653d2231317078222066696c6c3d227768697465223e3c7473203c67207374796c653d227472616e73666f726d3a7472616e736c61746528326577426f783d2730203020323930203530302720786d6c6e733d27687474703a207374796c653d227472616e73666f726d3a7472616e736c6174652837327078a164736f6c634300081a000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.0; import {IPositionManager} from '../../protocols/v4-periphery/interfaces/IPositionManager.sol'; library PositionManagerDeployer { function deploy( address poolManager, address permit2, uint256 unsubscribeGasLimit, address positionDescriptor, address weth ) internal returns (IPositionManager manager) { bytes memory args = abi.encode(poolManager, permit2, unsubscribeGasLimit, positionDescriptor, weth); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { manager := create2(0, add(initcode_, 32), mload(initcode_), hex'00') } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v4-periphery/src/PositionManager.sol */ function initcode() internal pure returns (bytes memory) { return hex'61018080604052346105365760a0816162a38038038091610020828561053a565b8339810103126105365780516001600160a01b03811681036105365760208201516001600160a01b03811681036105365760408301516060840151936001600160a01b03851685036105365760800151926001600160a01b03841684036105365760405161008f60408261053a565b6018815260208101907f556e697377617020763420506f736974696f6e73204e4654000000000000000082526040516100c960408261053a565b600b81526a554e492d56342d504f534d60a81b602082015281516001600160401b03811161044a575f54600181811c9116801561052c575b602082101461042c57601f81116104ca575b50806020601f8211600114610469575f9161045e575b508160011b915f199060031b1c1916175f555b8051906001600160401b03821161044a5760015490600182811c92168015610440575b602083101461042c5781601f8493116103be575b50602090601f8311600114610358575f9261034d575b50508160011b915f199060031b1c1916176001555b5190208060c0524660a05260405160208101917f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86683526040820152466060820152306080820152608081526101f460a08261053a565b51902060805260e052610100526101205261014052600160085561016052604051615d45908161055e8239608051816124d5015260a051816124af015260c05181612524015260e051818181610af601528181610eb501528181611174015281816118c001528181611c3c01528181611cd1015281816120a1015281816121980152818161295801528181612a2c01528181612f1b01528181613d4601528181613e3901528181613edc01528181613ff30152818161431b0152818161457401528181614ae901528181614c6601528181614de401528181614ec901528181614f59015261576f01526101005181818161144001526131fb01526101205181818161039c01528181610a0e01528181610dc90152614efa015261014051818181611482015281816129ca01528181613a4201528181613a9e01528181613bc20152613c4b0152610160518181816116350152611fab0152f35b015190505f80610189565b60015f9081528281209350601f198516905b8181106103a6575090846001959493921061038e575b505050811b0160015561019e565b01515f1960f88460031b161c191690555f8080610380565b9293602060018192878601518155019501930161036a565b60015f529091507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f840160051c81019160208510610422575b90601f859493920160051c01905b8181106104145750610173565b5f8155849350600101610407565b90915081906103f9565b634e487b7160e01b5f52602260045260245ffd5b91607f169161015f565b634e487b7160e01b5f52604160045260245ffd5b90508301515f610129565b5f8080528181209250601f198416905b8181106104b25750908360019493921061049a575b5050811b015f5561013c565b8501515f1960f88460031b161c191690555f8061048e565b9192602060018192868a015181550194019201610479565b5f80527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563601f830160051c81019160208410610522575b601f0160051c01905b8181106105175750610113565b5f815560010161050a565b9091508190610501565b90607f1690610101565b5f80fd5b601f909101601f19168101906001600160401b0382119082101761044a5760405256fe60806040526004361015610022575b3615610018575f80fd5b6100206129c0565b005b5f3560e01c80622a3e3a1461029057806301ffc9a71461028b57806305c1ee201461028657806306fdde0314610281578063081812fc1461027c578063095ea7b3146102775780630f5730f11461027257806312261ee71461026d57806316a24131146102685780631efeed331461026357806323b872dd1461025e5780632b67b570146102595780632b9261de146102545780633644e5151461024f5780633aea60f01461024a57806342842e0e146102455780634767565f146102405780634aa4a4fc1461023b5780634afe393c14610236578063502e1a16146102315780635a9d7a681461022c5780636352211e1461022757806370a082311461022257806375794a3c1461021d5780637ba03aad1461021857806386b6be7d1461021357806389097a6a1461020e57806391dd73461461020957806395d89b4114610204578063a22cb465146101ff578063ac9650d8146101fa578063ad0b27fb146101f5578063b88d4fde146101f0578063c87b56dd146101eb578063d737d0c7146101e6578063dc4c90d3146101e1578063dd46508f146101dc578063e985e9c5146101d75763f70204050361000e576122ae565b612248565b6120c5565b612082565b61203d565b611f56565b611c7c565b611c28565b611b2b565b611a7b565b6119c6565b611884565b61185a565b6117be565b61174f565b611732565b611688565b611659565b611616565b6115cc565b6114d7565b611463565b611429565b611161565b611088565b611057565b610e72565b610d58565b610ae2565b610a65565b610a32565b6109ef565b6108e0565b610839565b610806565b6106ef565b61063e565b61056c565b61033c565b6001600160a01b038116036102a657565b5f80fd5b35906102b582610295565b565b9181601f840112156102a65782359167ffffffffffffffff83116102a657602083818601950101116102a657565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b9060206103399281815201906102e5565b90565b60606003193601126102a65760043561035481610295565b6024359067ffffffffffffffff82116102a6578136039160606003198401126102a65760443567ffffffffffffffff81116102a6576103979036906004016102b7565b6060947f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031693909290843b156102a6576001600160a01b03604051967f2a2d80d10000000000000000000000000000000000000000000000000000000088521660048701526060602487015260c48601937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd826004013591018112156102a65781016024600482013591019467ffffffffffffffff82116102a6578160071b360386136102a65760606064890152819052869460e48601949392915f5b81811061051a575050506104cb5f9694869488946044856104b36104a360248b99016102aa565b6001600160a01b03166084890152565b013560a48601526003198584030160448601526123c0565b03925af19081610500575b506104f757506104f36104e7612466565b60405191829182610328565b0390f35b6104f3906104e7565b8061050e5f610514936106ae565b80610656565b5f6104d6565b91965091929394608080826105316001948b612361565b01970191019188969594939261047c565b7fffffffff000000000000000000000000000000000000000000000000000000008116036102a657565b346102a65760206003193601126102a65760207fffffffff000000000000000000000000000000000000000000000000000000006004356105ac81610542565b167f01ffc9a7000000000000000000000000000000000000000000000000000000008114908115610614575b81156105ea575b506040519015158152f35b7f5b5e139f000000000000000000000000000000000000000000000000000000009150145f6105df565b7f80ac58cd00000000000000000000000000000000000000000000000000000000811491506105d8565b60206003193601126102a65761002060043533612a54565b5f9103126102a657565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60a0810190811067ffffffffffffffff8211176106a957604052565b610660565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176106a957604052565b346102a6575f6003193601126102a6576040515f80548060011c90600181169081156107fc575b6020831082146107cf5782855260208501919081156107985750600114610748575b6104f3846104e7818603826106ae565b5f8080529250907f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b818410610784575050016104e782610738565b805484840152602090930192600101610771565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682525090151560051b0190506104e782610738565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f1691610716565b346102a65760206003193601126102a6576004355f52600460205260206001600160a01b0360405f205416604051908152f35b346102a65760406003193601126102a65760043561085681610295565b602435805f5260026020526001600160a01b0360405f2054169182331415806108af575b6108875761002092612ab5565b7f82b42900000000000000000000000000000000000000000000000000000000005f5260045ffd5b50825f52600560205260ff6108d83360405f20906001600160a01b03165f5260205260405f2090565b54161561087a565b60a06003193601126102a6576004356108f881610295565b602435604435916064359260843567ffffffffffffffff81116102a6576109239036906004016102b7565b948242116109c7576109bc856109c293610020986109b6885f8099868252600260205281896001600160a01b036040832054169c8d9981604051977f49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad89526001600160a01b0360208a01911681526040890192835260608901948552608089019687528160a08a20995252525252612b2c565b91612be5565b82612a54565b612ab5565b7f5a9165ff000000000000000000000000000000000000000000000000000000005f5260045ffd5b346102a6575f6003193601126102a65760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102a65760206003193601126102a6576004355f52600760205260206001600160a01b0360405f205416604051908152f35b346102a65760206003193601126102a6576020610a9c600435610a8781612669565b919082851c60020b9260081c60020b91612e68565b6fffffffffffffffffffffffffffffffff60405191168152f35b60031960609101126102a657600435610ace81610295565b90602435610adb81610295565b9060443590565b346102a657610af036610ab6565b91610b1a7f0000000000000000000000000000000000000000000000000000000000000000612f9c565b610d30578291610c41610b54610b48610b3b865f52600260205260405f2090565b546001600160a01b031690565b6001600160a01b031690565b91610b6a6001600160a01b03851693841461302f565b610bb46001600160a01b03821694610b83861515613094565b8433148015610cf2575b8015610ccd575b610b9d906130f9565b6001600160a01b03165f52600360205260405f2090565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055610bf5816001600160a01b03165f52600360205260405f2090565b80546001019055610c0e855f52600260205260405f2090565b906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b610c7e610c56845f52600460205260405f2090565b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4610cbe610cb7825f52600960205260405f2090565b5460ff1690565b610cc457005b6100209061315e565b50610b9d610ce9610b48610b3b8a5f52600460205260405f2090565b33149050610b94565b50610d2b610cb733610d15846001600160a01b03165f52600560205260405f2090565b906001600160a01b03165f5260205260405f2090565b610b8d565b7fd4b05fe0000000000000000000000000000000000000000000000000000000005f5260045ffd5b6101006003193601126102a657600435610d7181610295565b60c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126102a65760e43567ffffffffffffffff81116102a657610dbb9036906004016102b7565b916060926001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803b156102a6576001600160a01b035f80946104cb604051978896879586947f2b67b570000000000000000000000000000000000000000000000000000000008652166004850152610e3d602485016122f6565b6001600160a01b0360a435610e5181610295565b1660a485015260c43560c485015261010060e48501526101048401916123c0565b60606003193601126102a657602435600435610e8d82610295565b60443567ffffffffffffffff81116102a657610ead9036906004016102b7565b610ed99391937f0000000000000000000000000000000000000000000000000000000000000000612f9c565b610d3057610ee783336132b6565b1561102b576001600160a01b03610f09610b3b855f52600760205260405f2090565b1680610fef57505f83815260096020526040902080546001179055610fbf90610fbb90610fb56001600160a01b03851696610f5088610c0e895f52600760205260405f2090565b610f896040519384927f8d57f6b20000000000000000000000000000000000000000000000000000000060208501528960248501612495565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826106ae565b8361334b565b1590565b610fea57507f9709492381f90bdc5938bb4e3b8e35b7e0eac8af058619e27191c5a40ce79fa95f80a3005b61338c565b7f25fbd8be000000000000000000000000000000000000000000000000000000005f5260048490526001600160a01b031660245260445ffd5b5ffd5b7f0ca968d8000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b346102a6575f6003193601126102a65760206110716124ac565b604051908152f35b6044359081151582036102a657565b60c06003193601126102a6576004356110a081610295565b6024356110ac81610295565b6110b4611079565b906064359260843560a43567ffffffffffffffff81116102a6576110dc9036906004016102b7565b8692919242116109c7578361115c936109bc926109b6885f6100209c8189818f81604051977f6673cb397ee2a50b6b8401653d3638b4ac8b3db9c28aa6870ffceb7574ec2f7689526001600160a01b0360208a0191168152600160408a019316835260608901948552608089019687528160a08a20995252525252612b2c565b6136b8565b346102a65761116f36610ab6565b6111987f0000000000000000000000000000000000000000000000000000000000000000612f9c565b610d30576111b4610b48610b3b835f52600260205260405f2090565b916111ca6001600160a01b03851693841461302f565b816001600160a01b03821680946111e2821515613094565b8033148015611401575b80156113dc575b6111fc906130f9565b611217876001600160a01b03165f52600360205260405f2090565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055611258846001600160a01b03165f52600360205260405f2090565b8054600101905561127584610c0e855f52600260205260405f2090565b61128a610c56845f52600460205260405f2090565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a46112c3610cb7835f52600960205260405f2090565b6113ce575b3b159182156112db575b6100208361257e565b6040517f150b7a020000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b039490941660248501526044840191909152608060648401525f6084840181905260209250839160a49183915af180156113c9577fffffffff000000000000000000000000000000000000000000000000000000007f150b7a020000000000000000000000000000000000000000000000000000000091610020935f9161139a575b5016145f806112d2565b6113bc915060203d6020116113c2575b6113b481836106ae565b810190612569565b5f611390565b503d6113aa565b6123fe565b6113d78261315e565b6112c8565b506111fc6113f8610b48610b3b865f52600460205260405f2090565b331490506111f3565b50611424610cb733610d158a6001600160a01b03165f52600560205260405f2090565b6111ec565b346102a6575f6003193601126102a65760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346102a6575f6003193601126102a65760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b9181601f840112156102a65782359167ffffffffffffffff83116102a6576020808501948460051b0101116102a657565b60406003193601126102a65760043567ffffffffffffffff81116102a6576115039036906004016102b7565b60243567ffffffffffffffff81116102a6576115239036906004016114a6565b916001600160a01b037f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c166115a45761157f93337f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5d61376b565b5f7f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5d005b7f6f5ffb7e000000000000000000000000000000000000000000000000000000005f5260045ffd5b346102a65760406003193601126102a6576004356115e981610295565b6001600160a01b0360243591165f52600660205260405f20905f52602052602060405f2054604051908152f35b346102a6575f6003193601126102a65760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102a65760206003193601126102a6576020611677600435612648565b6001600160a01b0360405191168152f35b346102a65760206003193601126102a6576001600160a01b036004356116ad81610295565b1680156116d4575f5260036020526104f360405f2054604051918291829190602083019252565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a45524f5f4144445245535300000000000000000000000000000000000000006044820152fd5b346102a6575f6003193601126102a6576020600854604051908152f35b346102a65760206003193601126102a65760c061176d600435612669565b6117b760405180936001600160a01b036080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b60a0820152f35b346102a65760206003193601126102a6576004357fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000081168091036102a6575f908152600a60209081526040918290208054600182015460029283015485516001600160a01b0393841681528383169581019590955260a082811c62ffffff169686019690965260b89190911c90920b6060840152166080820152f35b346102a65760206003193601126102a6576004355f526009602052602060405f2054604051908152f35b346102a65760206003193601126102a65760043567ffffffffffffffff81116102a6576118b59036906004016102b7565b906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016330361199e5760408135189063ffffffff60408201351663ffffffe0601f8201169260608401602084013518179282019260608401359483641fffffffe08760051b16805f905b8881831061196f5790506080929150010191011017611962576060608063ffffffff61195796169401920161376b565b6104f36104e7612452565b633b99b53d5f526004601cfd5b8294509263ffffffe0601f60808060209687969801013599848b1817998d010135011601019201869291611927565b7fae18210a000000000000000000000000000000000000000000000000000000005f5260045ffd5b346102a6575f6003193601126102a6576040515f6001548060011c9060018116908115611a71575b6020831082146107cf5782855260208501919081156107985750600114611a1f576104f3846104e7818603826106ae565b60015f9081529250907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b818410611a5d575050016104e782610738565b805484840152602090930192600101611a4a565b91607f16916119ee565b346102a65760406003193601126102a657600435611a9881610295565b60243580151581036102a65761002091336136b8565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310611ae057505050505090565b9091929394602080611b1c837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0866001960301875289516102e5565b97019301930191939290611ad1565b60206003193601126102a65760043567ffffffffffffffff81116102a657611b579036906004016114a6565b90611b6182612747565b91611b6f60405193846106ae565b8083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611b9c82612747565b015f5b818110611c175750505f5b818110611bbf57604051806104f38682611aae565b5f80611bcc83858761278c565b90611bdc604051809381936127f1565b0390305af4611be9612466565b9015611c0f5790600191611bfd82876127fe565b52611c0881866127fe565b5001611baa565b602081519101fd5b806060602080938801015201611b9f565b60206003193601126102a657600435611c607f0000000000000000000000000000000000000000000000000000000000000000612f9c565b610d3057611c6e81336132b6565b1561102b576100209061315e565b346102a65760806003193601126102a657600435611c9981610295565b60243590611ca682610295565b60443560643567ffffffffffffffff81116102a657611cc99036906004016102b7565b939091611cf57f0000000000000000000000000000000000000000000000000000000000000000612f9c565b610d3057611d11610b48610b3b835f52600260205260405f2090565b91611d276001600160a01b03861693841461302f565b816001600160a01b0382168094611d3f821515613094565b8033148015611f2e575b8015611f09575b611d59906130f9565b611d74886001600160a01b03165f52600360205260405f2090565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055611db5846001600160a01b03165f52600360205260405f2090565b80546001019055611dd284610c0e855f52600260205260405f2090565b611de7610c56845f52600460205260405f2090565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5f80a4611e20610cb7835f52600960205260405f2090565b611efb575b3b15938415611e38575b6100208561257e565b602094505f90611e78604051978896879586947f150b7a020000000000000000000000000000000000000000000000000000000086523360048701612812565b03925af180156113c9577fffffffff000000000000000000000000000000000000000000000000000000007f150b7a020000000000000000000000000000000000000000000000000000000091610020935f91611edc575b5016145f808080611e2f565b611ef5915060203d6020116113c2576113b481836106ae565b5f611ed0565b611f048261315e565b611e25565b50611d59611f25610b48610b3b865f52600460205260405f2090565b33149050611d50565b50611f51610cb733610d158b6001600160a01b03165f52600560205260405f2090565b611d49565b346102a65760206003193601126102a657600435604051907fe9dc637500000000000000000000000000000000000000000000000000000000825230600483015260248201525f816044816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa80156113c9575f90611fea575b6104f39060405191829182610328565b503d805f833e611ffa81836106ae565b8101906020818303126102a65780519067ffffffffffffffff82116102a6570181601f820112156102a6576104f39181602061203893519101612840565b611fda565b346102a6575f6003193601126102a65760207f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c6001600160a01b0360405191168152f35b346102a6575f6003193601126102a65760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b60406003193601126102a65760043567ffffffffffffffff81116102a6576120f19036906004016102b7565b6024356001600160a01b037f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c166115a457337f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5d80421161221d576040517f48c89491000000000000000000000000000000000000000000000000000000008152602060048201525f818061218b6024820187896123c0565b0381836001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af180156113c9576121cd575b610020613746565b3d805f833e6121dc81836106ae565b8101906020818303126102a65780519067ffffffffffffffff82116102a657019080601f830112156102a657815161221692602001612840565b50806121c5565b7fbfb22adf000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b346102a65760406003193601126102a657602060ff6122a260043561226c81610295565b6001600160a01b036024359161228183610295565b165f526005845260405f20906001600160a01b03165f5260205260405f2090565b54166040519015158152f35b600319360160c081126102a65760a0136102a65760206122d860a4356122d381610295565b6128a3565b6040519060020b8152f35b359065ffffffffffff821682036102a657565b6001600160a01b0360243561230a81610295565b1681526001600160a01b0360443561232181610295565b16602082015260643565ffffffffffff81168091036102a657604082015260843565ffffffffffff811681036102a65765ffffffffffff60609116910152565b65ffffffffffff6123ba606080936001600160a01b03813561238281610295565b1686526001600160a01b03602082013561239b81610295565b166020870152836123ae604083016122e3565b166040870152016122e3565b16910152565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b6040513d5f823e3d90fd5b604051906102b56080836106ae565b67ffffffffffffffff81116106a957601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b604051906124616020836106ae565b5f8252565b3d15612490573d9061247782612418565b9161248560405193846106ae565b82523d5f602084013e565b606090565b6040906103399492815281602082015201916123c0565b467f0000000000000000000000000000000000000000000000000000000000000000036124f7577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86682527f000000000000000000000000000000000000000000000000000000000000000060408201524660608201523060808201526080815261256360a0826106ae565b51902090565b908160209103126102a6575161033981610542565b1561258557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152fd5b156125ea57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152fd5b5f5260026020526001600160a01b0360405f205416906102b58215156125e3565b5f60806040516126788161068d565b82815282602082015282604082015282606082015201525f52600960205260405f2054807fffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000165f52600a60205260405f206127446127346002604051936126de8561068d565b6001600160a01b03815416855261272661271c60018301546001600160a01b038116602089015262ffffff8160a01c16604089015260b81c60020b90565b60020b6060870152565b01546001600160a01b031690565b6001600160a01b03166080830152565b91565b67ffffffffffffffff81116106a95760051b60200190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b91908110156127ec5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156102a657019081359167ffffffffffffffff83116102a65760200182360381136102a6579190565b61275f565b908092918237015f815290565b80518210156127ec5760209160051b010190565b90926001600160a01b03608093816103399896168452166020830152604082015281606082015201916123c0565b92919261284c82612418565b9161285a60405193846106ae565b8294818452818301116102a6578281602093845f96015e010152565b8060020b036102a657565b908160209103126102a6575161033981612876565b62ffffff8116036102a657565b6001600160a01b03604051917f6276cbbe000000000000000000000000000000000000000000000000000000008352816004356128df81610295565b166004840152816024356128f281610295565b16602484015262ffffff60443561290881612896565b16604484015260643561291a81612876565b60020b606484015261294160843561293181610295565b6001600160a01b03166084850152565b1660a482015260208160c4815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af15f918161298f575b506103395750627fffff90565b6129b291925060203d6020116129b9575b6129aa81836106ae565b810190612881565b905f612982565b503d6129a0565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633141580612a21575b6129f957565b7f38bbd576000000000000000000000000000000000000000000000000000000005f5260045ffd5b506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163314156129f3565b906001600160a01b03600160ff83161b92165f52600660205260405f209060081c5f5260205260405f20818154188091551615612a8d57565b7f1fb09b80000000000000000000000000000000000000000000000000000000005f5260045ffd5b906001600160a01b038091845f526004602052612b038160405f20906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b1691167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9255f80a4565b90612b356124ac565b91604051927f19010000000000000000000000000000000000000000000000000000000000008452600284015260228301525f604060428420938281528260208201520152565b91908260409103126102a6576020823592013590565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b60ff601b9116019060ff8211612bd157565b612b92565b90604010156127ec5760400190565b90833b612d7a5760418103612cee5790602092612c6e83612c46612c40612c1a612c125f98880188612b7c565b949097612bd6565b357fff000000000000000000000000000000000000000000000000000000000000001690565b60f81c90565b935b604051948594859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa156113c9576001600160a01b035f5116908115612cc6576001600160a01b031603612c9e57565b7f815e1d64000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f8baa579f000000000000000000000000000000000000000000000000000000005f5260045ffd5b9060408203612d5257602092612d0b825f94612c6e940190612b7c565b929092612d4c612d47612d417f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84169360ff1c90565b60ff1690565b612bbf565b93612c48565b7f4be6321b000000000000000000000000000000000000000000000000000000005f5260045ffd5b9092612dc1936001600160a01b03602094604051968795869485937f1626ba7e00000000000000000000000000000000000000000000000000000000855260048501612495565b0392165afa9081156113c9577f1626ba7e00000000000000000000000000000000000000000000000000000000917fffffffff00000000000000000000000000000000000000000000000000000000915f91612e49575b501603612e2157565b7fb0669cbc000000000000000000000000000000000000000000000000000000005f5260045ffd5b612e62915060203d6020116113c2576113b481836106ae565b5f612e18565b9290612ea39260a092604051956026870152600686015260038501523084525f603a600c860120948160408201528160208201525220614bbf565b60068101809111612bd15760408051602081810194855291810192909252612f0f929091612ed48160608101610f89565b519020604051809381927f1e2eaeaf000000000000000000000000000000000000000000000000000000008352600483019190602083019252565b03816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa80156113c9576fffffffffffffffffffffffffffffffff915f91612f6057501690565b612f82915060203d602011612f86575b612f7a81836106ae565b810190612f8d565b1690565b503d612f70565b908160209103126102a6575190565b60206001600160a01b03916024604051809481937ff135baaa0000000000000000000000000000000000000000000000000000000083527fc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab236004840152165afa9081156113c9575f91613010575b50151590565b613029915060203d602011612f8657612f7a81836106ae565b5f61300a565b1561303657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f57524f4e475f46524f4d000000000000000000000000000000000000000000006044820152fd5b1561309b57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152fd5b1561310057565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152fd5b6001600160a01b0361317b610b3b835f52600760205260405f2090565b1690811561328e575f81815260096020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556131cb610c56825f52600760205260405f2090565b813b6131f8575b7fa0ebb1de82db929a9153472f37d3a66dbede4436258311ad0f52a35a2c91d1505f80a3565b5a7f000000000000000000000000000000000000000000000000000000000000000080911061328957823b156102a6575f60405180927faf45dd140000000000000000000000000000000000000000000000000000000082528183878261326789600483019190602083019252565b0393f1613275575b506131d2565b8061050e5f613283936106ae565b5f61326f565b6137d4565b7f237e6c28000000000000000000000000000000000000000000000000000000005f5260045ffd5b6001600160a01b036132c783612648565b16916001600160a01b03821692831492831561332a575b5082156132ea57505090565b60ff9250906001600160a01b0361330361332593612648565b165f52600560205260405f20906001600160a01b03165f5260205260405f2090565b541690565b908093505f5260046020526001600160a01b0360405f20541614915f6132de565b803b1561336457815f92918360208194519301915af190565b7f7c402b21000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f3d01166001600160a01b03604051927f90bfb8650000000000000000000000000000000000000000000000000000000084521660048301527f8d57f6b2000000000000000000000000000000000000000000000000000000006024830152608060448301528060a00160648301523d60848301523d5f60a484013e7f81ea5e9e0000000000000000000000000000000000000000000000000000000060c4828401600460a4820152015260e40190fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f3d01166001600160a01b03604051927f90bfb8650000000000000000000000000000000000000000000000000000000084521660048301527fa9059cbb000000000000000000000000000000000000000000000000000000006024830152608060448301528060a00160648301523d60848301523d5f60a484013e7ff27f64e40000000000000000000000000000000000000000000000000000000060c4828401600460a4820152015260e40190fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f3d01166001600160a01b03604051927f90bfb8650000000000000000000000000000000000000000000000000000000084521660048301525f6024830152608060448301528060a00160648301523d60848301523d5f60a484013e7ff4b3b1bc0000000000000000000000000000000000000000000000000000000060c4828401600460a4820152015260e40190fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f3d01166001600160a01b03604051927f90bfb8650000000000000000000000000000000000000000000000000000000084521660048301527fb1a9116f000000000000000000000000000000000000000000000000000000006024830152608060448301528060a00160648301523d60848301523d5f60a484013e7face944810000000000000000000000000000000000000000000000000000000060c4828401600460a4820152015260e40190fd5b60206001600160a01b03807f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31931693845f526005835261370c8160405f20906001600160a01b03165f5260205260405f2090565b951515957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff88161790556040519586521693a3565b5f7f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5d565b909291938284036137ac575f5b848110156137a45760019061379e81850161379483888b61278c565b913560f81c6137fc565b01613778565b509350505050565b7faaad13f7000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fed43c3a6000000000000000000000000000000000000000000000000000000005f5260045ffd5b909190600b8110156139175780613827575061381b906102b5926149cc565b94939093929192614b63565b60048103613846575061383d906102b592614185565b93929092614a79565b60018103613868575061385c906102b5926149cc565b94939093929192614a0e565b600281036138975750613881613891916102b5936145df565b9890979691959295949394613cc2565b9561478a565b600581036138c357506138b06138bd916102b593614481565b9790969591949294613cc2565b94614543565b91600383146138ff57505061102891505b7f5cda29d7000000000000000000000000000000000000000000000000000000005f52600452602490565b6102b592509061390e91614185565b939290926141c1565b600d8103613933575061392d906102b592613caf565b90614147565b6011810361395b575061394c613955916102b593613e9e565b92909192613cc2565b9161412c565b600b810361398f5750613989613977613983926102b594613e9e565b93829493929193613f73565b92613fa1565b91613fe2565b600e81036139c157506139b56139ab6139bb926102b594613e9e565b9282949291613cc2565b92613eb6565b91613eca565b601281036139dc57506139d7906102b592613ac8565b613e32565b601381036139f857506139f2906102b592613caf565b90613d25565b60148103613a1f5750613a11613a19916102b593613caf565b919091613cc2565b90613d07565b60158103613a6d5750613a38613a68916102b593613ac8565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690613b54565b613c39565b9160168314613a8257505061102891506138d4565b6102b59250613ac391613a9491613ac8565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016613ad4565b613bb0565b90602011611962573590565b613adf903090614bdf565b7f80000000000000000000000000000000000000000000000000000000000000008214613b4f578115613b3e575b8111613b165790565b7ff4d678b8000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050613b495f614c5f565b90613b0d565b905090565b90613b5f305f614bdf565b907f80000000000000000000000000000000000000000000000000000000000000008314613baa578215613b98575b508111613b165790565b613ba3919250614c5f565b905f613b8e565b50905090565b80613bb85750565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690813b156102a6575f916024839260405194859384927f2e1a7d4d00000000000000000000000000000000000000000000000000000000845260048401525af180156113c957613c2f5750565b5f6102b5916106ae565b80613c415750565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803b156102a6575f906004604051809481937fd0e30db00000000000000000000000000000000000000000000000000000000083525af180156113c957613c2f5750565b9190604011611962576020823592013590565b6001600160a01b03811660018103613cfb5750507f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c90565b60020361033957503090565b90613d1182614cd1565b9081613d1c57505050565b6102b592614d37565b90613d2f82614ddd565b908115613e01578111613dd5576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691823b156102a6575f9283926040519485809481937f80f0b44c0000000000000000000000000000000000000000000000000000000083526020600484016001600160a01b036040820194168152015203925af180156113c957613dc75750565b8061050e5f6102b5936106ae565b6102b5917f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c90613eca565b505050565b7f80000000000000000000000000000000000000000000000000000000000000008114612bd1575f0390565b613e5d81307f0000000000000000000000000000000000000000000000000000000000000000614e49565b907f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c5f831215613e94576139896102b593613e06565b6102b59291613eca565b90606011611962578035916040602083013592013590565b9081613ec6576103399150614ddd565b5090565b90918015613e01576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803b156102a6575f92836064926001600160a01b03948560405198899788967f0b0d9c0900000000000000000000000000000000000000000000000000000000885216600487015216602485015260448401525af180156113c957613f5e5750565b80613f6a5f80936106ae565b8003126102a657565b15613f9d577f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c90565b3090565b907f80000000000000000000000000000000000000000000000000000000000000008203613fd3576103399150614cd1565b81613ec6576103399150614c5f565b908215613e01576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691823b156102a6576040517fa58411940000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201525f8160248183885af180156113c957614118575b506001600160a01b0381166140ce5750506020906004604051809481937f11da60b40000000000000000000000000000000000000000000000000000000083525af180156113c9576140b35750565b6140cb9060203d602011612f8657612f7a81836106ae565b50565b5f93602093926140dd92614ea7565b6004604051809481937f11da60b40000000000000000000000000000000000000000000000000000000083525af180156113c9576140b35750565b8061050e5f614126936106ae565b5f614064565b9161413e6102b593826139bb82614ddd565b6139bb82614ddd565b906102b59161417c7f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c918261398982614c5f565b61398982614c5f565b919082359260208101359260408201359263ffffffff60608401351683019063ffffffff82351693602080840193860101910110611962579190565b939290927f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c6141f186826132b6565b156143ae575061420085612669565b9290938360081c60020b958460201c60020b9661423761422289838a8d612e68565b6fffffffffffffffffffffffffffffffff1690565b966142418a612648565b955f6142558c5f52600960205260405f2090565b5561425f8b614faa565b5f9989614291575b505050505050508160ff1661427e575b5050505050565b614287946151b4565b5f80808080614277565b60409495969a509061430e916142d16142b16142ac8d61507e565b613e06565b916142c76142bd612409565b97889060020b9052565b60020b6020870152565b858501528b606085015284519a8b9485947f5a6bcfda000000000000000000000000000000000000000000000000000000008652600486016143f9565b03815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af180156113c9575f965f9161436e575b509061435d826143629493986150b0565b6150ed565b5f808080808080614267565b61435d97506143629392915061439b9060403d6040116143a7575b61439381836106ae565b8101906143e3565b9790979192935061434c565b503d614389565b6001600160a01b03907f0ca968d8000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b91908260409103126102a6576020825192015190565b6060610339959361444a83610140956001600160a01b036080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b805160020b60a0840152602081015160020b60c0840152604081015160e084015201516101008201528161012082015201916123c0565b91908260a08101359260c08201359260e083013592610100810135926101208201359263ffffffff6101408401351683019063ffffffff82351693602080840193860101910110611962579190565b91908260a09103126102a6576040516144e88161068d565b608080829480356144f881610295565b8452602081013561450881610295565b6020850152604081013561451b81612896565b6040850152606081013561452e81612876565b606085015201359161453f83610295565b0152565b90916102b59796959493926fffffffffffffffffffffffffffffffff6145d861459860a061457136886144d0565b207f0000000000000000000000000000000000000000000000000000000000000000615264565b5050506145a484615303565b6145ad86615303565b6145c088356145bb81610295565b614ddd565b916145d260208a01356145bb81610295565b9361564f565b169261478a565b9091819260a08301359260c08101359260e08201359261010083013592610120810135926101408201359263ffffffff6101608401351683019063ffffffff82351693602080840193860101910110611962579190565b600260806102b593614680813561464c81610295565b85906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b600184016146c9602083013561469581610295565b82906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b60408201356146d781612896565b81547fffffffffffff000000000000ffffffffffffffffffffffffffffffffffffffff76ffffff0000000000000000000000000000000000000000606086013561472081612876565b60b81b79ffffff0000000000000000000000000000000000000000000000169360a01b1691161717905501359161475683610295565b01906001600160a01b03167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b90919496929793959760085492600184016008556001600160a01b038a16996147b48b1515613094565b845f5260026020526001600160a01b0360405f20541661496e5761488a6149259861491f93876102b59e61481986614800614917986001600160a01b03165f52600360205260405f2090565b80546001019055610c0e845f52600260205260405f2090565b5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a461484836886144d0565b63ffffff007fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000060a066ffffff000000009320169260081b169260201b16171790565b928361489e875f52600960205260405f2090565b55837fffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000168561490760016148fc847fffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000165f52600a60205260405f2090565b015460b81c60020b90565b60020b1561492b575b505061507e565b9236906144d0565b906156fc565b506157de565b614962614967927fffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000165f52600a60205260405f2090565b614636565b5f85614910565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f414c52454144595f4d494e5445440000000000000000000000000000000000006044820152fd5b909181359260208301359260408101359260608201359263ffffffff60808401351683019063ffffffff82351693602080840193860101910110611962579190565b90959495939192937f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c614a4283826132b6565b156143ae57509561435d92826142ac6102b59899614a6d614a65614a7397612669565b93909261507e565b916156fc565b906150b0565b949394929091927f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c614aac82826132b6565b156143ae57506102b59495614b5e9282614ac8614a7394612669565b90614a6d6fffffffffffffffffffffffffffffffff614b58614b0d60a085207f0000000000000000000000000000000000000000000000000000000000000000615264565b505050614b1f8660081c60020b615303565b614b2e8760201c60020b615303565b614b416001600160a01b03885116614ddd565b916145d26001600160a01b0360208a015116614ddd565b1661507e565b6157de565b90959495939192937f0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a5c614b9783826132b6565b156143ae575095614b5e9282614a6d6102b59899614bb7614a7396612669565b92909161507e565b6040516020810191825260066040820152604081526125636060826106ae565b6001600160a01b038116614bf257503190565b906001600160a01b0360246020928260405195869485937f70a08231000000000000000000000000000000000000000000000000000000008552166004840152165afa9081156113c9575f91614c46575090565b610339915060203d602011612f8657612f7a81836106ae565b614c8a81307f0000000000000000000000000000000000000000000000000000000000000000614e49565b905f8213614c9c575061033990613e06565b6001600160a01b03907f3351b260000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b6001600160a01b038116614ce457504790565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290602090829060249082906001600160a01b03165afa9081156113c9575f91614c46575090565b9091906001600160a01b038116614d6457505f808080614d5894865af11590565b614d5f5750565b613532565b91906001600160a01b03604051927fa9059cbb00000000000000000000000000000000000000000000000000000000845216600483015260248201525f604060208260448582885af13d15601f3d11600185511416171692828152826020820152015215614dcf5750565b6001600160a01b031661345f565b614e0881307f0000000000000000000000000000000000000000000000000000000000000000614e49565b905f8212614e14575090565b6001600160a01b03907f4c085bf1000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b6001600160a01b03809381602094165f52168252602460405f2060405194859384927ff135baaa0000000000000000000000000000000000000000000000000000000084526004840152165afa9081156113c9575f91614c46575090565b9091906001600160a01b0383163003614eef576102b592506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690614d37565b906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803b156102a6576040517f36c785160000000000000000000000000000000000000000000000000000000081526001600160a01b0394851660048201527f00000000000000000000000000000000000000000000000000000000000000008516602482015291841660448301529190921660648301525f908290608490829084905af180156113c957613dc75750565b805f5260026020525f6001600160a01b03604082205416614fcc8115156125e3565b8082526003602052604082207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8154019055615010835f52600260205260405f2090565b80548360031b906001600160a01b03808616831b921b191617905561503d835f52600460205260405f2090565b80548360031b906001600160a01b03808616831b921b19161790557fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8280a4565b905f821261508857565b7f93dafdf1000000000000000000000000000000000000000000000000000000005f5260045ffd5b6150d3906150c58360801d8260801d0361592c565b92600f0b90600f0b0361592c565b6fffffffffffffffffffffffffffffffff169060801b1790565b929190926fffffffffffffffffffffffffffffffff8160801d94816151118761593a565b9116918291161061519957506fffffffffffffffffffffffffffffffff929350600f0b908261513f8361593a565b9116928391161061514e575050565b906151696fffffffffffffffffffffffffffffffff9261593a565b907f12816f22000000000000000000000000000000000000000000000000000000005f526004521660245260445ffd5b6fffffffffffffffffffffffffffffffff906151698661593a565b5f81815260076020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000081169091556001600160a01b039081169561525895610fbb959394919390929091604051957fb1a9116f00000000000000000000000000000000000000000000000000000000602088015260248701521660448501526064840152608483015260a482015260a48152610fb560c4826106ae565b61525f5750565b6135e5565b602090602461527b6001600160a01b039594614bbf565b60405195869384927f1e2eaeaf0000000000000000000000000000000000000000000000000000000084526004840152165afa9182156113c9575f926152e2575b506001600160a01b038216918060a01c60020b9162ffffff808360b81c169260d01c1690565b6152fc91925060203d602011612f8657612f7a81836106ae565b905f6152bc565b60020b908160ff1d82810118620d89e881116156495763ffffffff9192600182167001fffcb933bd6fad37aa2d162d1a5940010270010000000000000000000000000000000018916002811661562d575b60048116615611575b600881166155f5575b601081166155d9575b602081166155bd575b604081166155a1575b60808116615585575b6101008116615569575b610200811661554d575b6104008116615531575b6108008116615515575b61100081166154f9575b61200081166154dd575b61400081166154c1575b61800081166154a5575b620100008116615489575b62020000811661546e575b620400008116615453575b620800001661543a575b5f12615413575b0160201c90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0461540c565b6b048a170391f7dc42444e8fa290910260801c90615405565b6d2216e584f5fa1ea926041bedfe9890920260801c916153fb565b916e5d6af8dedb81196699c329225ee6040260801c916153f0565b916f09aa508b5b7a84e1c677de54f3e99bc90260801c916153e5565b916f31be135f97d08fd981231505542fcfa60260801c916153da565b916f70d869a156d2a1b890bb3df62baf32f70260801c916153d0565b916fa9f746462d870fdf8a65dc1f90e061e50260801c916153c6565b916fd097f3bdfd2022b8845ad8f792aa58250260801c916153bc565b916fe7159475a2c29b7443b29c7fa6e889d90260801c916153b2565b916ff3392b0822b70005940c7a398e4b70f30260801c916153a8565b916ff987a7253ac413176f2b074cf7815e540260801c9161539e565b916ffcbe86c7900a88aedcffc83b479aa3a40260801c91615394565b916ffe5dee046a99a2a811c461f1969c30530260801c9161538a565b916fff2ea16466c96a3843ec78b326b528610260801c91615381565b916fff973b41fa98c081472e6896dfb254c00260801c91615378565b916fffcb9843d60f6159c9db58835c9266440260801c9161536f565b916fffe5caca7e10e4e61c3624eaa0941cd00260801c91615366565b916ffff2e50f5f656932ef12357cf3c7fdcc0260801c9161535d565b916ffff97272373d413259a46990580e213a0260801c91615354565b82615959565b936001600160a01b0383166001600160a01b038316116156f4575b6001600160a01b0385811695908316861161568b57505061033993506159b7565b92909391946001600160a01b038216115f146156e85782916156b1916156b795946159b7565b93615987565b6fffffffffffffffffffffffffffffffff81166fffffffffffffffffffffffffffffffff8316105f14613b4f575090565b91505061033992615987565b90919061566a565b95939460409161576261570d612409565b60088a901c60020b81529260208a811c60020b908501528585850152866060850152845198899485947f5a6bcfda000000000000000000000000000000000000000000000000000000008652600486016143f9565b03815f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19081156113c9575f945f926157ba575b5081949560ff166157b157505050565b6102b592615a00565b9094506157d6915060403d6040116143a75761439381836106ae565b90935f6157a1565b908160801d600f0b91600f0b915f8112806158f7575b6158955750505f81128061585e575b61580b575050565b9061581b61422261102893613e06565b7f31e30ad0000000000000000000000000000000000000000000000000000000005f526fffffffffffffffffffffffffffffffff91821660045216602452604490565b506fffffffffffffffffffffffffffffffff8061587a83613e06565b16166fffffffffffffffffffffffffffffffff831610615803565b906fffffffffffffffffffffffffffffffff6158b361102893613e06565b7f31e30ad0000000000000000000000000000000000000000000000000000000005f526fffffffffffffffffffffffffffffffff9283166004521616602452604490565b506fffffffffffffffffffffffffffffffff61591282613e06565b166fffffffffffffffffffffffffffffffff8316106157f4565b9081600f0b91820361508857565b5f81600f0b12615088576fffffffffffffffffffffffffffffffff1690565b7f8b86327a000000000000000000000000000000000000000000000000000000005f5260020b60045260245ffd5b916001600160a01b03610339936159ac93828116838316116159b1575b031690615b43565b615d1b565b906159a4565b916159ac91610339936001600160a01b0382166001600160a01b038216116159fa575b6001600160a01b03906159f1828416838316615bff565b92031691615c79565b906159da565b615a6a9192815f5260076020526001600160a01b0360405f20541693604051927fd8865c2700000000000000000000000000000000000000000000000000000000602085015260248401526044830152606482015260648152615a646084826106ae565b8261334b565b15615a725750565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f3d0116604051917f90bfb86500000000000000000000000000000000000000000000000000000000835260048301527fd8865c27000000000000000000000000000000000000000000000000000000006024830152608060448301528060a00160648301523d60848301523d5f60a484013e7fe94f10e20000000000000000000000000000000000000000000000000000000060c4828401600460a4820152015260e40190fd5b156102a657565b908160601b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6c010000000000000000000000008409928280851094039380850394615b91868511615b3c565b14615bf8576c0100000000000000000000000082910981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b5091500490565b90808202917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff828209918380841093039280840393846c0100000000000000000000000011156102a65714615c70576c01000000000000000000000000910990828211900360a01b910360601c1790565b50505060601c90565b91818302917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818509938380861095039480860395615cb9878611615b3c565b14615d13579082910981805f03168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b505091500490565b906fffffffffffffffffffffffffffffffff82168092036150885756fea164736f6c634300081a000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.0; library StateViewDeployer { function deploy(address poolManager) internal returns (address stateview) { bytes memory args = abi.encode(poolManager); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { stateview := create2(0, add(initcode_, 32), mload(initcode_), hex'00') } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v4-periphery/src/lens/StateView.sol */ function initcode() internal pure returns (bytes memory) { return hex'60a03460b357601f610e9738819003918201601f19168301916001600160401b0383118484101760b75780849260209460405283398101031260b357516001600160a01b038116810360b357608052604051610dcb90816100cc823960805181818161012b01528181610246015281816102db0152818161039e0152818161048101528181610549015281816105db01528181610622015281816106870152818161073401528181610810015261096a0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c80631c7ccb4c146108ac57806353e9c1fb146107c95780637c40f1fe146106ab5780638a2bb9e61461064657806397fd7b421461060b5780639ec538c8146105a2578063c815641c1461050b578063caedab54146103f6578063dacf1d2f146102ff578063dc4c90d314610291578063f0928f29146101e65763fa6793d51461009d575f80fd5b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576100d7600435610d2f565b600381018091116101b957604051907f1e2eaeaf000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa80156101ae575f90610177575b6020906fffffffffffffffffffffffffffffffff60405191168152f35b506020813d6020116101a6575b8161019160209383610a2b565b810103126101a2576020905161015a565b5f80fd5b3d9150610184565b6040513d5f823e3d90fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b346101a2576101fd6101f7366109f7565b90610d8b565b604051907f1e2eaeaf000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa80156101ae575f90610177576020906fffffffffffffffffffffffffffffffff60405191168152f35b346101a2575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101a25760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25760243573ffffffffffffffffffffffffffffffffffffffff811681036101a2576103566109e7565b6064358060020b81036101a2576103f2926103c2926040519260843560268501526006840152600383015281525f603a600c83012091816040820152816020820152526004357f0000000000000000000000000000000000000000000000000000000000000000610bc0565b604080516fffffffffffffffffffffffffffffffff90941684526020840192909252908201529081906060820190565b0390f35b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576104386104306109d7565b600435610d55565b604051907f1e2eaeaf000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa80156101ae575f906104d8575b6040908151906fffffffffffffffffffffffffffffffff8116825260801d600f0b6020820152f35b506020813d602011610503575b816104f260209383610a2b565b810103126101a257604090516104b0565b3d91506104e5565b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a257608062ffffff8061056d6004357f0000000000000000000000000000000000000000000000000000000000000000610c63565b92949173ffffffffffffffffffffffffffffffffffffffff6040519616865260020b6020860152166040840152166060820152f35b346101a25760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25760406105ff6004357f0000000000000000000000000000000000000000000000000000000000000000610c58565b82519182526020820152f35b346101a2576103f26103c261061f366109f7565b907f0000000000000000000000000000000000000000000000000000000000000000610bc0565b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25760406105ff6106826109d7565b6004357f0000000000000000000000000000000000000000000000000000000000000000610b1e565b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576106e56104306109d7565b604051907f35fd631a0000000000000000000000000000000000000000000000000000000082526004820152600360248201525f8160448173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa80156101ae576080915f916107a7575b506020810151906060604082015191015190604051926fffffffffffffffffffffffffffffffff81168452841d600f0b602084015260408301526060820152f35b6107c391503d805f833e6107bb8183610a2b565b810190610a99565b82610766565b346101a25760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a25760406004356108056109d7565b9061080e6109e7565b7f00000000000000000000000000000000000000000000000000000000000000009061083a8383610c58565b90610846868686610b1e565b96909361085f610857828989610b1e565b989097610c63565b5050905060020b9160020b82125f14610885575050505003910382519182526020820152f35b95969593949360020b1361089d5750500391036105ff565b949392909403039203036105ff565b346101a25760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a2576024358060010b8091036101a2576108f4600435610d2f565b600581018091116101b957604051906020820192835260408201526040815261091e606082610a2b565b519020604051907f1e2eaeaf000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa80156101ae575f906109a4575b602090604051908152f35b506020813d6020116109cf575b816109be60209383610a2b565b810103126101a25760209051610999565b3d91506109b1565b602435908160020b82036101a257565b604435908160020b82036101a257565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60409101126101a2576004359060243590565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610a6c57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6020818303126101a25780519067ffffffffffffffff82116101a257019080601f830112156101a25781519167ffffffffffffffff8311610a6c578260051b9060405193610aea6020840186610a2b565b84526020808501928201019283116101a257602001905b828210610b0e5750505090565b8151815260209182019101610b01565b9291610b2991610d55565b600181018091116101b95773ffffffffffffffffffffffffffffffffffffffff9260445f9260405195869384927f35fd631a000000000000000000000000000000000000000000000000000000008452600484015260026024840152165afa9182156101ae575f92610ba4575b506040602083015192015190565b610bb99192503d805f833e6107bb8183610a2b565b905f610b96565b6044610be273ffffffffffffffffffffffffffffffffffffffff945f94610d8b565b60405194859384927f35fd631a000000000000000000000000000000000000000000000000000000008452600484015260036024840152165afa9081156101ae575f91610c3e575b506020810151916060604083015192015190565b610c5291503d805f833e6107bb8183610a2b565b5f610c2a565b9190610b2990610d2f565b6020906024610c8773ffffffffffffffffffffffffffffffffffffffff9594610d2f565b60405195869384927f1e2eaeaf0000000000000000000000000000000000000000000000000000000084526004840152165afa9182156101ae575f92610cfb575b5073ffffffffffffffffffffffffffffffffffffffff8216918060a01c60020b9162ffffff808360b81c169260d01c1690565b9091506020813d602011610d27575b81610d1760209383610a2b565b810103126101a25751905f610cc8565b3d9150610d0a565b604051602081019182526006604082015260408152610d4f606082610a2b565b51902090565b610d5e90610d2f565b600481018091116101b95760405190602082019260020b8352604082015260408152610d4f606082610a2b565b610d9490610d2f565b600681018091116101b9576040519060208201928352604082015260408152610d4f606082610a2b56fea164736f6c634300081a000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.0; import {IV4Quoter} from '../../protocols/v4-periphery/interfaces/IV4Quoter.sol'; library V4QuoterDeployer { function deploy(address poolManager) internal returns (IV4Quoter v4quoter) { bytes memory args = abi.encode(poolManager); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { v4quoter := create2(0, add(initcode_, 32), mload(initcode_), hex'00') } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/v4-periphery/src/lens/V4Quoter.sol */ function initcode() internal pure returns (bytes memory) { return hex'60a034607b57601f61175038819003918201601f19168301916001600160401b03831184841017607f57808492602094604052833981010312607b57516001600160a01b0381168103607b576080526040516116bc908161009482396080518181816101b5015281816102ab015281816105b001526114910152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c8063147d2af91461087f578063587330731461082d578063595323f5146107815780636a36a38c1461065657806391dd73461461052c578063aa2f15011461037f578063aa9d21cb1461032d578063ca253dc9146101d9578063dc4c90d31461016b5763eebe0c6a14610087575f80fd5b346101675761009536610d77565b30330361013f57806101016100fb6100f660a06fffffffffffffffffffffffffffffffff9501936100c5856110fd565b6100de876100d560c0850161110a565b16600f0b611289565b906100ec60e0840184611127565b9490933690610c2a565b61134b565b916110fd565b156101355781165b7fecbd9804000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b60801d8116610109565b7f29c3b7ee000000000000000000000000000000000000000000000000000000005f5260045ffd5b5f80fd5b34610167575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261016757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101675760406101e936610a53565b5f806102915f61022b6102575a9688519283917f6a36a38c00000000000000000000000000000000000000000000000000000000602084015260248301610e99565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610936565b8651809381927f48c89491000000000000000000000000000000000000000000000000000000008352602060048401526024830190610de7565b03818373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af1908161030d575b506103055750506102f76102f16102e9611020565b925a9061104f565b916112b5565b905b82519182526020820152f35b9091506102f9565b610328903d805f833e6103208183610936565b810190610fbd565b6102d4565b3461016757604061033d36610c93565b5f806102915f61022b6102575a9688519283917feebe0c6a0000000000000000000000000000000000000000000000000000000060208401526024830161105c565b346101675761038d36610e2a565b30330361013f57602081016103a281836111a7565b90506103b06040840161110a565b916103ba846111fb565b9190815b610400576fffffffffffffffffffffffffffffffff847fecbd9804000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b90919261040d82866111a7565b91907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85018581116104dc5761046561045e6fffffffffffffffffffffffffffffffff926104ac966104819561121c565b9788611588565b939061047460808a018a611127565b939092169085159061134b565b90156105095761049390600f0b611178565b6fffffffffffffffffffffffffffffffff165b936111fb565b9180156104dc577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190816103be565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6105159060801d611178565b6fffffffffffffffffffffffffffffffff166104a6565b346101675760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101675760043567ffffffffffffffff811161016757366023820112156101675780600401359067ffffffffffffffff82116101675736602483830101116101675773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361062e575f6024819284806040519384930183378101838152039082305af16105f9611020565b9061060657602081519101fd5b7fe0752a5a000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fae18210a000000000000000000000000000000000000000000000000000000005f5260045ffd5b346101675761066436610e2a565b30330361013f57602081019061067a82826111a7565b90506106886040830161110a565b91610692816111fb565b935f915b8383106106db576fffffffffffffffffffffffffffffffff857fecbd9804000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b9091929361075c6fffffffffffffffffffffffffffffffff61073d61072860019461071a6107138a61070d8b8b6111a7565b9061121c565b9b8c611588565b948593919216600f0b611289565b61073560808d018d611127565b93909261134b565b9015610767576fffffffffffffffffffffffffffffffff165b966111fb565b959493019190610696565b60801d6fffffffffffffffffffffffffffffffff16610756565b346101675761078f36610d77565b30330361013f57806107db6100fb6100f660a06fffffffffffffffffffffffffffffffff9501936107bf856110fd565b866107cc60c0840161110a565b16906100ec60e0840184611127565b1561081a576107ec9060801d611178565b81167fecbd9804000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b61082690600f0b611178565b8116610109565b3461016757604061083d36610c93565b5f806102915f61022b6102575a9688519283917f595323f50000000000000000000000000000000000000000000000000000000060208401526024830161105c565b3461016757604061088f36610a53565b5f806102915f61022b6102575a9688519283917faa2f150100000000000000000000000000000000000000000000000000000000602084015260248301610e99565b6060810190811067ffffffffffffffff8211176108ed57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60a0810190811067ffffffffffffffff8211176108ed57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108ed57604052565b359073ffffffffffffffffffffffffffffffffffffffff8216820361016757565b359062ffffff8216820361016757565b35908160020b820361016757565b67ffffffffffffffff81116108ed57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b81601f8201121561016757803590610a07826109b6565b92610a156040519485610936565b8284526020838301011161016757815f926020809301838601378301015290565b35906fffffffffffffffffffffffffffffffff8216820361016757565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101675760043567ffffffffffffffff81116101675760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82840301126101675760405191610ac8836108d1565b610ad482600401610977565b8352602482013567ffffffffffffffff811161016757820190806023830112156101675760048201359167ffffffffffffffff83116108ed578260051b60405193610b226020830186610936565b845281016024019060208401908383116101675760248101915b838310610b615750505050506020830152610b5990604401610a36565b604082015290565b823567ffffffffffffffff8111610167576004908301019060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083880301126101675760405190610bb28261091a565b610bbe60208401610977565b8252610bcc60408401610998565b6020830152610bdd606084016109a8565b6040830152610bee60808401610977565b606083015260a08301359167ffffffffffffffff831161016757610c1a886020809695819601016109f0565b6080820152815201920191610b3c565b91908260a091031261016757604051610c428161091a565b6080610c8e818395610c5381610977565b8552610c6160208201610977565b6020860152610c7260408201610998565b6040860152610c83606082016109a8565b606086015201610977565b910152565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101675760043567ffffffffffffffff8111610167576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc828403011261016757604051916080830183811067ffffffffffffffff8211176108ed57604052610d278183600401610c2a565b835260a48201358015158103610167576020840152610d4860c48301610a36565b604084015260e48201359167ffffffffffffffff831161016757610d6f92016004016109f0565b606082015290565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610167576004359067ffffffffffffffff8211610167577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82610100920301126101675760040190565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610167576004359067ffffffffffffffff8211610167577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc826060920301126101675760040190565b60208152608081019173ffffffffffffffffffffffffffffffffffffffff815116602083015260208101519260606040840152835180915260a0830190602060a08260051b8601019501915f905b828210610f1157505050506fffffffffffffffffffffffffffffffff604060609201511691015290565b90919295602080610faf837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608a6001960301865260a060808c5173ffffffffffffffffffffffffffffffffffffffff815116845262ffffff868201511686850152604081015160020b604085015273ffffffffffffffffffffffffffffffffffffffff60608201511660608501520151918160808201520190610de7565b980192019201909291610ee7565b6020818303126101675780519067ffffffffffffffff8211610167570181601f8201121561016757805190610ff1826109b6565b92610fff6040519485610936565b8284526020838301011161016757815f9260208093018386015e8301015290565b3d1561104a573d90611031826109b6565b9161103f6040519384610936565b82523d5f602084013e565b606090565b919082039182116104dc57565b61012060606110fa93602084526110c160208501825173ffffffffffffffffffffffffffffffffffffffff6080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b6020810151151560c08501526fffffffffffffffffffffffffffffffff60408201511660e0850152015191610100808201520190610de7565b90565b3580151581036101675790565b356fffffffffffffffffffffffffffffffff811681036101675790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610167570180359067ffffffffffffffff82116101675760200191813603831361016757565b600f0b7fffffffffffffffffffffffffffffffff8000000000000000000000000000000081146104dc575f0390565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610167570180359067ffffffffffffffff821161016757602001918160051b3603831361016757565b3573ffffffffffffffffffffffffffffffffffffffff811681036101675790565b919081101561125c5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6181360301821215610167570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f800000000000000000000000000000000000000000000000000000000000000081146104dc575f0390565b7fecbd9804000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000060208301511603611309576024015190565b611347906040519182917f6190b2b0000000000000000000000000000000000000000000000000000000008352602060048401526024830190610de7565b0390fd5b92949390801561156d576401000276a4915b806040519261136b846108d1565b1515978884526020840194868652604085019073ffffffffffffffffffffffffffffffffffffffff1681526040519586957ff3cd914c00000000000000000000000000000000000000000000000000000000875260048701611417908b73ffffffffffffffffffffffffffffffffffffffff6080809282815116855282602082015116602086015262ffffff6040820151166040860152606081015160020b6060860152015116910152565b51151560a48701525160c48601525173ffffffffffffffffffffffffffffffffffffffff1660e48501526101048401610120905281610124850152610144840137808201610144015f9052601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01681010361014401817f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1691815a6020945f91f1908115611562575f91611530575b5080945f8312145f146115285760801d5b600f0b036114f95750565b60a090207f7a5ed734000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b600f0b6114ee565b90506020813d60201161155a575b8161154b60209383610936565b8101031261016757515f6114dd565b3d915061153e565b6040513d5f823e3d90fd5b73fffd8963efd1fc6a506488495d951d5263988d259161135d565b905f60806040516115988161091a565b82815282602082015282604082015282606082015201526115b8826111fb565b73ffffffffffffffffffffffffffffffffffffffff82169173ffffffffffffffffffffffffffffffffffffffff82168084105f14611690575073ffffffffffffffffffffffffffffffffffffffff905b1680921492602081013562ffffff8116809103610167576040820135918260020b80930361016757606001359273ffffffffffffffffffffffffffffffffffffffff84168094036101675773ffffffffffffffffffffffffffffffffffffffff90604051956116768761091a565b865216602085015260408401526060830152608082015291565b91505073ffffffffffffffffffffffffffffffffffffffff829161160856fea164736f6c634300081a000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.7.0; import {IQuoter} from '../../protocols/view-quoter-v3/interfaces/IQuoter.sol'; library QuoterDeployer { function deploy(address factory) internal returns (IQuoter quoter) { bytes memory args = abi.encode(factory); bytes memory initcode_ = abi.encodePacked(initcode(), args); assembly { quoter := create(0, add(initcode_, 32), mload(initcode_)) } } /** * @dev autogenerated - run `./script/util/create_briefcase.sh` to generate current initcode * * @notice This initcode is generated from the following contract: * - Source Contract: src/pkgs/view-quoter-v3/contracts/Quoter.sol */ function initcode() internal pure returns (bytes memory) { return hex'60a06040523480156200001157600080fd5b50604051620029ca380380620029ca83398101604081905262000034916200004a565b60601b6001600160601b0319166080526200007a565b6000602082840312156200005c578081fd5b81516001600160a01b038116811462000073578182fd5b9392505050565b60805160601c61292d6200009d600039806104d45280610cff525061292d6000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063c45a01551161005b578063c45a0155146100e4578063c6a5026a146100f9578063cdca17531461010c578063d85c3d631461011f5761007d565b80632f80bb1d1461008257806386e3a7cf146100ae578063bd21704a146100d1575b600080fd5b6100956100903660046124db565b610132565b6040516100a5949392919061281f565b60405180910390f35b6100c16100bc366004612635565b6102e9565b6040516100a594939291906128ba565b6100c16100df366004612583565b61042a565b6100ec6104d2565b6040516100a591906127fd565b6100c1610107366004612583565b6104f6565b61009561011a3660046124db565b61058b565b6100c161012d36600461259e565b610720565b6000606080600061014286610818565b67ffffffffffffffff8111801561015857600080fd5b50604051908082528060200260200182016040528015610182578160200160208202803683370190505b50925061018e86610818565b67ffffffffffffffff811180156101a457600080fd5b506040519080825280602002602001820160405280156101ce578160200160208202803683370190505b50915060005b60008060006101e28a610829565b925092509250600080600061023d6040518060a00160405280876001600160a01b03168152602001886001600160a01b031681526020018e81526020018662ffffff16815260200160006001600160a01b031681525061042a565b50925092509250818a888151811061025157fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508089888151811061027e57fe5b602002602001019063ffffffff16908163ffffffff1681525050829b5086806001019750506102ac8d61085a565b156102c1576102ba8d610862565b9c506102d5565b508a9950600096506102e095505050505050565b5050505050506101d4565b92959194509250565b60008060008060008060008088602001516001600160a01b031689600001516001600160a01b031610905060008960800151905060008a60a001516001600160a01b03166000141561033c575060408a01515b6000604051806080016040528085151581526020016001151581526020018d6060015162ffffff1681526020018d60a001516001600160a01b0316600014610388578d60a001516103ae565b856103a75773fffd8963efd1fc6a506488495d951d5263988d256103ae565b6401000276a45b6001600160a01b031681525090506103d6836103cd8e6040015161087f565b60000383610895565b909c509a509097509550600087136103ee57856103f0565b865b9a50600087136104035786600003610408565b856000035b9450811561041c5781851461041c57600080fd5b505050505050509193509193565b6000806000806000610449866000015187602001518860600151610cf8565b905060006040518060c0016040528088600001516001600160a01b0316815260200188602001516001600160a01b0316815260200188604001518152602001886060015162ffffff168152602001836001600160a01b0316815260200160006001600160a01b031681525090506104bf816102e9565b5091999098509096509294509192505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806000806000610515866000015187602001518860600151610cf8565b905060006040518060c0016040528088600001516001600160a01b0316815260200188602001516001600160a01b0316815260200188604001518152602001836001600160a01b03168152602001886060015162ffffff16815260200160006001600160a01b031681525090506104bf81610720565b6000606080600061059b86610818565b67ffffffffffffffff811180156105b157600080fd5b506040519080825280602002602001820160405280156105db578160200160208202803683370190505b5092506105e786610818565b67ffffffffffffffff811180156105fd57600080fd5b50604051908082528060200260200182016040528015610627578160200160208202803683370190505b50915060005b600080600061063b8a610829565b92509250925060008060006106966040518060a00160405280886001600160a01b03168152602001876001600160a01b031681526020018e81526020018662ffffff16815260200160006001600160a01b03168152506104f6565b50925092509250818a88815181106106aa57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050808988815181106106d757fe5b602002602001019063ffffffff16908163ffffffff1681525050829b5086806001019750506107058d61085a565b156102c1576107138d610862565b9c5050505050505061062d565b600080600080600080600087602001516001600160a01b031688600001516001600160a01b03161090506000886060015190506000604051806080016040528084151581526020016000151581526020018b6080015162ffffff1681526020018b60a001516001600160a01b031660001461079f578b60a001516107c5565b846107be5773fffd8963efd1fc6a506488495d951d5263988d256107c5565b6401000276a45b6001600160a01b031681525090506107ea826107e48c6040015161087f565b83610895565b909a509850909550935060008513610805578460000361080a565b836000035b985050505050509193509193565b80516017601319909101045b919050565b600080806108378482610d36565b9250610844846014610de6565b9050610851846017610d36565b91509193909250565b516042111590565b805160609061087990839060179060161901610e8d565b92915050565b6000600160ff1b821061089157600080fd5b5090565b6000808313602083015280806001816108ad88610fe0565b905060006040518060e001604052808981526020016000815260200183600001516001600160a01b03168152602001836020015160020b81526020016000815260200160006001600160801b031681526020018a6001600160a01b0316631a6865026040518163ffffffff1660e01b815260040160206040518083038186803b15801561093957600080fd5b505afa15801561094d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097191906126af565b6001600160801b0316905290505b8051158015906109a9575086606001516001600160a01b031681604001516001600160a01b031614155b15610cb4576109b661238c565b6040808301516001600160a01b03168252830151606083015189516109de928d9290916110fb565b15156040830152600290810b810b60208301819052620d89e719910b1215610a0f57620d89e7196020820152610a2e565b6020810151620d89e860029190910b1315610a2e57620d89e860208201525b610a3b81602001516112f7565b6001600160a01b0316606082015260408201518851610abe9190610a7b5789606001516001600160a01b031683606001516001600160a01b031611610a99565b89606001516001600160a01b031683606001516001600160a01b0316105b610aa7578260600151610aad565b89606001515b60c0850151855160408d0151611629565b60c085015260a084015260808301526001600160a01b03166040830152602088015115610b2457610af88160c0015182608001510161087f565b825103825260a0810151610b1a90610b0f9061087f565b60208401519061181b565b6020830152610b5f565b610b318160a0015161087f565b825101825260c08101516080820151610b5991610b4e910161087f565b602084015190611831565b60208301525b80606001516001600160a01b031682604001516001600160a01b03161415610c7357806040015115610c4957602081015160405163f30dba9360e01b81526000916001600160a01b038d169163f30dba9391610bbd91600401612811565b6101006040518083038186803b158015610bd657600080fd5b505afa158015610bea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0e91906126c9565b505050505050915050886000015115610c25576000035b610c338360c0015182611847565b6001600160801b031660c0840152506001909301925b8751610c59578060200151610c62565b60018160200151035b600290810b900b6060830152610cae565b80600001516001600160a01b031682604001516001600160a01b031614610cae57610ca182604001516118fd565b600290810b900b60608301525b5061097f565b60208701518751151590151514610cd357602081015181518903610ce0565b8060000151880381602001515b604090920151909a9199509750919550909350505050565b6000610d2e7f0000000000000000000000000000000000000000000000000000000000000000610d29868686611c1c565b611c72565b949350505050565b600081826014011015610d85576040805162461bcd60e51b8152602060048201526012602482015271746f416464726573735f6f766572666c6f7760701b604482015290519081900360640190fd5b8160140183511015610dd6576040805162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b604482015290519081900360640190fd5b500160200151600160601b900490565b600081826003011015610e34576040805162461bcd60e51b8152602060048201526011602482015270746f55696e7432345f6f766572666c6f7760781b604482015290519081900360640190fd5b8160030183511015610e84576040805162461bcd60e51b8152602060048201526014602482015273746f55696e7432345f6f75744f66426f756e647360601b604482015290519081900360640190fd5b50016003015190565b60608182601f011015610ed8576040805162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015290519081900360640190fd5b828284011015610f20576040805162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015290519081900360640190fd5b81830184511015610f6c576040805162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015290519081900360640190fd5b606082158015610f8b5760405191506000825260208201604052610fd5565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015610fc4578051835260209283019201610fac565b5050858452601f01601f1916604052505b5090505b9392505050565b610fe86123c8565b816001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561102157600080fd5b505afa158015611035573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611059919061276f565b5050505050600290810b900b6020808401919091526001600160a01b039182168352604080516334324e9f60e21b815290519285169263d0c93a7c92600480840193919291829003018186803b1580156110b257600080fd5b505afa1580156110c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ea9190612569565b600290810b900b6040820152919050565b60008060008560020b8560020b8161110f57fe5b05905060008560020b12801561113657508560020b8560020b8161112f57fe5b0760020b15155b1561114057600019015b83156112175760008061115283611d56565b6040805163299ce14b60e11b8152600184810b6004830152915193955091935060ff84161b8001600019019160009183916001600160a01b038e1691635339c296916024808301926020929190829003018186803b1580156111b357600080fd5b505afa1580156111c7573d6000803e3d6000fd5b505050506040513d60208110156111dd57600080fd5b50511680151596509050856111f957898360ff1686030261120c565b8961120382611d68565b840360ff168603025b9650505050506112ed565b60008061122683600101611d56565b91509150600060018260ff166001901b031990506000818b6001600160a01b0316635339c296866040518263ffffffff1660e01b8152600401808260010b815260200191505060206040518083038186803b15801561128457600080fd5b505afa158015611298573d6000803e3d6000fd5b505050506040513d60208110156112ae57600080fd5b50511680151596509050856112d057898360ff0360ff168660010101026112e6565b89836112db83611e08565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b1261130e578260020b611316565b8260020b6000035b9050620d89e8811115611354576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b60006001821661136857600160801b61137a565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156113ae576ffff97272373d413259a46990580e213a0260801c5b60048216156113cd576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b60088216156113ec576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b601082161561140b576fffcb9843d60f6159c9db58835c9266440260801c5b602082161561142a576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615611449576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615611468576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615611488576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156114a8576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156114c8576ff3392b0822b70005940c7a398e4b70f30260801c5b6108008216156114e8576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615611508576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615611528576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615611548576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615611568576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615611589576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156115a9576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156115c8576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156115e5576b048a170391f7dc42444e8fa20260801c5b60008460020b13156116005780600019816115fc57fe5b0490505b640100000000810615611614576001611617565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906116ae5760006116628989620f42400362ffffff16620f4240611ef2565b90508261167b576116768c8c8c6001611fa1565b611688565b6116888b8d8c600161201a565b9550858110611699578a96506116a8565b6116a58c8b83866120c5565b96505b506116f8565b816116c5576116c08b8b8b600061201a565b6116d2565b6116d28a8c8b6000611fa1565b93508388600003106116e6578995506116f8565b6116f58b8a8a60000385612111565b95505b6001600160a01b038a811690871614821561175b578080156117175750815b61172d57611728878d8c600161201a565b61172f565b855b955080801561173c575081155b6117525761174d878d8c6000611fa1565b611754565b845b94506117a5565b8080156117655750815b61177b576117768c888c6001611fa1565b61177d565b855b955080801561178a575081155b6117a05761179b8c888c600061201a565b6117a2565b845b94505b811580156117b557508860000385115b156117c1578860000394505b8180156117e057508a6001600160a01b0316876001600160a01b031614155b156117ef57858903935061180c565b611809868962ffffff168a620f42400362ffffff1661215d565b93505b50505095509550955095915050565b8082038281131560008312151461087957600080fd5b8181018281121560008312151461087957600080fd5b60008082600f0b12156118ac57826001600160801b03168260000384039150816001600160801b0316106118a7576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b610879565b826001600160801b03168284019150816001600160801b03161015610879576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b03831610801590611939575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b61196e576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b640100000000600160c01b03602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c97908811961790941790921717909117171760808110611a0257607f810383901c9150611a0c565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b14611c0d57886001600160a01b0316611bf1826112f7565b6001600160a01b03161115611c065781611c08565b805b611c0f565b815b9998505050505050505050565b611c246123c8565b826001600160a01b0316846001600160a01b03161115611c42579192915b50604080516060810182526001600160a01b03948516815292909316602083015262ffffff169181019190915290565b600081602001516001600160a01b031682600001516001600160a01b031610611c9a57600080fd5b50805160208083015160409384015184516001600160a01b0394851681850152939091168385015262ffffff166060808401919091528351808403820181526080840185528051908301206001600160f81b031960a085015294901b6bffffffffffffffffffffffff191660a183015260b58201939093527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460d5808301919091528251808303909101815260f5909101909152805191012090565b60020b600881901d9161010090910790565b6000808211611d7657600080fd5b600160801b8210611d8957608091821c91015b680100000000000000008210611da157604091821c91015b6401000000008210611db557602091821c91015b620100008210611dc757601091821c91015b6101008210611dd857600891821c91015b60108210611de857600491821c91015b60048210611df857600291821c91015b6002821061082457600101919050565b6000808211611e1657600080fd5b5060ff6001600160801b03821615611e3157607f1901611e39565b608082901c91505b67ffffffffffffffff821615611e5257603f1901611e5a565b604082901c91505b63ffffffff821615611e6f57601f1901611e77565b602082901c91505b61ffff821615611e8a57600f1901611e92565b601082901c91505b60ff821615611ea45760071901611eac565b600882901c91505b600f821615611ebe5760031901611ec6565b600482901c91505b6003821615611ed85760011901611ee0565b600282901c91505b60018216156108245760001901919050565b6000808060001985870986860292508281109083900303905080611f285760008411611f1d57600080fd5b508290049050610fd9565b808411611f3457600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b6000836001600160a01b0316856001600160a01b03161115611fc1579293925b81611fee57611fe9836001600160801b03168686036001600160a01b0316600160601b611ef2565b612011565b612011836001600160801b03168686036001600160a01b0316600160601b61215d565b95945050505050565b6000836001600160a01b0316856001600160a01b0316111561203a579293925b600160601b600160e01b03606084901b166001600160a01b03868603811690871661206457600080fd5b8361209457866001600160a01b03166120878383896001600160a01b0316611ef2565b8161208e57fe5b046120ba565b6120ba6120ab8383896001600160a01b031661215d565b886001600160a01b0316612197565b979650505050505050565b600080856001600160a01b0316116120dc57600080fd5b6000846001600160801b0316116120f257600080fd5b8161210457611fe985858560016121a2565b6120118585856001612283565b600080856001600160a01b03161161212857600080fd5b6000846001600160801b03161161213e57600080fd5b8161215057611fe98585856000612283565b61201185858560006121a2565b600061216a848484611ef2565b90506000828061217657fe5b8486091115610fd957600019811061218d57600080fd5b6001019392505050565b808204910615150190565b600081156122155760006001600160a01b038411156121d8576121d384600160601b876001600160801b0316611ef2565b6121f0565b6001600160801b038516606085901b816121ee57fe5b045b905061220d6122086001600160a01b03881683612366565b612376565b915050610d2e565b60006001600160a01b038411156122435761223e84600160601b876001600160801b031661215d565b61225a565b61225a606085901b6001600160801b038716612197565b905080866001600160a01b03161161227157600080fd5b6001600160a01b038616039050610d2e565b600082612291575083610d2e565b600160601b600160e01b03606085901b16821561231f576001600160a01b038616848102908582816122bf57fe5b0414156122f0578181018281106122ee576122e483896001600160a01b03168361215d565b9350505050610d2e565b505b61231682612311878a6001600160a01b0316868161230a57fe5b0490612366565b612197565b92505050610d2e565b6001600160a01b0386168481029085828161233657fe5b0414801561234357508082115b61234c57600080fd5b8082036122e4612208846001600160a01b038b168461215d565b8082018281101561087957600080fd5b806001600160a01b038116811461082457600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080516060810182526000808252602082018190529181019190915290565b803561082481612908565b8051801515811461082457600080fd5b8051600281900b811461082457600080fd5b600060a08284031215612426578081fd5b60405160a0810181811067ffffffffffffffff8211171561244357fe5b604052905080823561245481612908565b8152602083013561246481612908565b60208201526040838101359082015261247f606084016124c8565b6060820152608083013561249281612908565b6080919091015292915050565b80516001600160801b038116811461082457600080fd5b805161ffff8116811461082457600080fd5b803562ffffff8116811461082457600080fd5b600080604083850312156124ed578182fd5b823567ffffffffffffffff80821115612504578384fd5b818501915085601f830112612517578384fd5b813560208282111561252557fe5b612537601f8301601f191682016128e4565b9250818352878183860101111561254c578586fd5b818185018285013790820181019490945295939092013593505050565b60006020828403121561257a578081fd5b610fd982612403565b600060a08284031215612594578081fd5b610fd98383612415565b600060c082840312156125af578081fd5b60405160c0810181811067ffffffffffffffff821117156125cc57fe5b60405282356125da81612908565b815260208301356125ea81612908565b602082015260408381013590820152606083013561260781612908565b6060820152612618608084016124c8565b608082015261262960a084016123e8565b60a08201529392505050565b600060c08284031215612646578081fd5b60405160c0810181811067ffffffffffffffff8211171561266357fe5b604052823561267181612908565b8152602083013561268181612908565b60208201526040838101359082015261269c606084016124c8565b6060820152608083013561261881612908565b6000602082840312156126c0578081fd5b610fd98261249f565b600080600080600080600080610100898b0312156126e5578384fd5b6126ee8961249f565b9750602089015180600f0b8114612703578485fd5b80975050604089015195506060890151945060808901518060060b8114612728578485fd5b60a08a015190945061273981612908565b60c08a015190935063ffffffff81168114612752578283fd5b915061276060e08a016123f3565b90509295985092959890939650565b600080600080600080600060e0888a031215612789578081fd5b875161279481612908565b96506127a260208901612403565b95506127b0604089016124b6565b94506127be606089016124b6565b93506127cc608089016124b6565b925060a088015160ff811681146127e1578182fd5b91506127ef60c089016123f3565b905092959891949750929550565b6001600160a01b0391909116815260200190565b60029190910b815260200190565b600060808201868352602060808185015281875180845260a0860191508289019350845b818110156128685784516001600160a01b031683529383019391830191600101612843565b505084810360408601528651808252908201925081870190845b818110156128a457825163ffffffff1685529383019391830191600101612882565b5050505060609290920192909252949350505050565b9384526001600160a01b0392909216602084015263ffffffff166040830152606082015260800190565b60405181810167ffffffffffffffff8111828210171561290057fe5b604052919050565b6001600160a01b038116811461291d57600080fd5b5056fea164736f6c6343000706000a'; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IERC165} from '../../introspection/IERC165.sol'; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IERC721} from './IERC721.sol'; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IERC721} from './IERC721.sol'; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol, uint8 _decimals) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual { require(deadline >= block.timestamp, 'PERMIT_DEADLINE_EXPIRED'); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( '\x19\x01', DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( 'Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)' ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, 'INVALID_SIGNER'); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), keccak256(bytes(name)), keccak256('1'), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IEIP712} from './IEIP712.sol'; /// @title AllowanceTransfer /// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts /// @dev Requires user's token approval on the Permit2 contract interface IAllowanceTransfer is IEIP712 { /// @notice Thrown when an allowance on a token has expired. /// @param deadline The timestamp at which the allowed amount is no longer valid error AllowanceExpired(uint256 deadline); /// @notice Thrown when an allowance on a token has been depleted. /// @param amount The maximum amount allowed error InsufficientAllowance(uint256 amount); /// @notice Thrown when too many nonces are invalidated. error ExcessiveInvalidation(); /// @notice Emits an event when the owner successfully invalidates an ordered nonce. event NonceInvalidation( address indexed owner, address indexed token, address indexed spender, uint48 newNonce, uint48 oldNonce ); /// @notice Emits an event when the owner successfully sets permissions on a token for the spender. event Approval( address indexed owner, address indexed token, address indexed spender, uint160 amount, uint48 expiration ); /// @notice Emits an event when the owner successfully sets permissions using a permit signature on a token for the spender. event Permit( address indexed owner, address indexed token, address indexed spender, uint160 amount, uint48 expiration, uint48 nonce ); /// @notice Emits an event when the owner sets the allowance back to 0 with the lockdown function. event Lockdown(address indexed owner, address token, address spender); /// @notice The permit data for a token struct PermitDetails { // ERC20 token address address token; // the maximum amount allowed to spend uint160 amount; // timestamp at which a spender's token allowances become invalid uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } /// @notice The permit message signed for a single token allowance struct PermitSingle { // the permit data for a single token alownce PermitDetails details; // address permissioned on the allowed tokens address spender; // deadline on the permit signature uint256 sigDeadline; } /// @notice The permit message signed for multiple token allowances struct PermitBatch { // the permit data for multiple token allowances PermitDetails[] details; // address permissioned on the allowed tokens address spender; // deadline on the permit signature uint256 sigDeadline; } /// @notice The saved permissions /// @dev This info is saved per owner, per token, per spender and all signed over in the permit message /// @dev Setting amount to type(uint160).max sets an unlimited approval struct PackedAllowance { // amount allowed uint160 amount; // permission expiry uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } /// @notice A token spender pair. struct TokenSpenderPair { // the token the spender is approved address token; // the spender address address spender; } /// @notice Details for a token transfer. struct AllowanceTransferDetails { // the owner of the token address from; // the recipient of the token address to; // the amount of the token uint160 amount; // the token to be transferred address token; } /// @notice A mapping from owner address to token address to spender address to PackedAllowance struct, which contains details and conditions of the approval. /// @notice The mapping is indexed in the above order see: allowance[ownerAddress][tokenAddress][spenderAddress] /// @dev The packed slot holds the allowed amount, expiration at which the allowed amount is no longer valid, and current nonce thats updated on any signature based approvals. function allowance(address user, address token, address spender) external view returns (uint160 amount, uint48 expiration, uint48 nonce); /// @notice Approves the spender to use up to amount of the specified token up until the expiration /// @param token The token to approve /// @param spender The spender address to approve /// @param amount The approved amount of the token /// @param expiration The timestamp at which the approval is no longer valid /// @dev The packed allowance also holds a nonce, which will stay unchanged in approve /// @dev Setting amount to type(uint160).max sets an unlimited approval function approve(address token, address spender, uint160 amount, uint48 expiration) external; /// @notice Permit a spender to a given amount of the owners token via the owner's EIP-712 signature /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce /// @param owner The owner of the tokens being approved /// @param permitSingle Data signed over by the owner specifying the terms of approval /// @param signature The owner's signature over the permit data function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external; /// @notice Permit a spender to the signed amounts of the owners tokens via the owner's EIP-712 signature /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce /// @param owner The owner of the tokens being approved /// @param permitBatch Data signed over by the owner specifying the terms of approval /// @param signature The owner's signature over the permit data function permit(address owner, PermitBatch memory permitBatch, bytes calldata signature) external; /// @notice Transfer approved tokens from one address to another /// @param from The address to transfer from /// @param to The address of the recipient /// @param amount The amount of the token to transfer /// @param token The token address to transfer /// @dev Requires the from address to have approved at least the desired amount /// of tokens to msg.sender. function transferFrom(address from, address to, uint160 amount, address token) external; /// @notice Transfer approved tokens in a batch /// @param transferDetails Array of owners, recipients, amounts, and tokens for the transfers /// @dev Requires the from addresses to have approved at least the desired amount /// of tokens to msg.sender. function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external; /// @notice Enables performing a "lockdown" of the sender's Permit2 identity /// by batch revoking approvals /// @param approvals Array of approvals to revoke. function lockdown(TokenSpenderPair[] calldata approvals) external; /// @notice Invalidate nonces for a given (token, spender) pair /// @param token The token to invalidate nonces for /// @param spender The spender to invalidate nonces for /// @param newNonce The new nonce to set. Invalidates all nonces less than it. /// @dev Can't invalidate more than 2**16 nonces per transaction. function invalidateNonces(address token, address spender, uint48 newNonce) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; interface IEIP712 { function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IAllowanceTransfer} from './IAllowanceTransfer.sol'; import {ISignatureTransfer} from './ISignatureTransfer.sol'; /// @notice Permit2 handles signature-based transfers in SignatureTransfer and allowance-based transfers in AllowanceTransfer. /// @dev Users must approve Permit2 before calling any of the transfer functions. interface IPermit2 is ISignatureTransfer, IAllowanceTransfer { // IPermit2 unifies the two interfaces so users have maximal flexibility with their approval. }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IEIP712} from './IEIP712.sol'; /// @title SignatureTransfer /// @notice Handles ERC20 token transfers through signature based actions /// @dev Requires user's token approval on the Permit2 contract interface ISignatureTransfer is IEIP712 { /// @notice Thrown when the requested amount for a transfer is larger than the permissioned amount /// @param maxAmount The maximum amount a spender can request to transfer error InvalidAmount(uint256 maxAmount); /// @notice Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred /// @dev If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred error LengthMismatch(); /// @notice Emits an event when the owner successfully invalidates an unordered nonce. event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask); /// @notice The token and amount details for a transfer signed in the permit transfer signature struct TokenPermissions { // ERC20 token address address token; // the maximum amount that can be spent uint256 amount; } /// @notice The signed permit message for a single token transfer struct PermitTransferFrom { TokenPermissions permitted; // a unique value for every token owner's signature to prevent signature replays uint256 nonce; // deadline on the permit signature uint256 deadline; } /// @notice Specifies the recipient address and amount for batched transfers. /// @dev Recipients and amounts correspond to the index of the signed token permissions array. /// @dev Reverts if the requested amount is greater than the permitted signed amount. struct SignatureTransferDetails { // recipient address address to; // spender requested amount uint256 requestedAmount; } /// @notice Used to reconstruct the signed permit message for multiple token transfers /// @dev Do not need to pass in spender address as it is required that it is msg.sender /// @dev Note that a user still signs over a spender address struct PermitBatchTransferFrom { // the tokens and corresponding amounts permitted for a transfer TokenPermissions[] permitted; // a unique value for every token owner's signature to prevent signature replays uint256 nonce; // deadline on the permit signature uint256 deadline; } /// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection /// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order /// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce /// @dev It returns a uint256 bitmap /// @dev The index, or wordPosition is capped at type(uint248).max function nonceBitmap(address, uint256) external view returns (uint256); /// @notice Transfers a token using a signed permit message /// @dev Reverts if the requested amount is greater than the permitted signed amount /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails The spender's requested transfer details for the permitted token /// @param signature The signature to verify function permitTransferFrom( PermitTransferFrom memory permit, SignatureTransferDetails calldata transferDetails, address owner, bytes calldata signature ) external; /// @notice Transfers a token using a signed permit message /// @notice Includes extra data provided by the caller to verify signature over /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition /// @dev Reverts if the requested amount is greater than the permitted signed amount /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails The spender's requested transfer details for the permitted token /// @param witness Extra data to include when checking the user signature /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash /// @param signature The signature to verify function permitWitnessTransferFrom( PermitTransferFrom memory permit, SignatureTransferDetails calldata transferDetails, address owner, bytes32 witness, string calldata witnessTypeString, bytes calldata signature ) external; /// @notice Transfers multiple tokens using a signed permit message /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails Specifies the recipient and requested amount for the token transfer /// @param signature The signature to verify function permitTransferFrom( PermitBatchTransferFrom memory permit, SignatureTransferDetails[] calldata transferDetails, address owner, bytes calldata signature ) external; /// @notice Transfers multiple tokens using a signed permit message /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition /// @notice Includes extra data provided by the caller to verify signature over /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails Specifies the recipient and requested amount for the token transfer /// @param witness Extra data to include when checking the user signature /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash /// @param signature The signature to verify function permitWitnessTransferFrom( PermitBatchTransferFrom memory permit, SignatureTransferDetails[] calldata transferDetails, address owner, bytes32 witness, string calldata witnessTypeString, bytes calldata signature ) external; /// @notice Invalidates the bits specified in mask for the bitmap at the word position /// @dev The wordPos is maxed at type(uint248).max /// @param wordPos A number to index the nonceBitmap at /// @param mask A bitmap masked against msg.sender's current bitmap at the word position function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; interface IApproveAndCall { enum ApprovalType { NOT_REQUIRED, MAX, MAX_MINUS_ONE, ZERO_THEN_MAX, ZERO_THEN_MAX_MINUS_ONE } /// @dev Lens to be called off-chain to determine which (if any) of the relevant approval functions should be called /// @param token The token to approve /// @param amount The amount to approve /// @return The required approval type function getApprovalType(address token, uint256 amount) external returns (ApprovalType); /// @notice Approves a token for the maximum possible amount /// @param token The token to approve function approveMax(address token) external payable; /// @notice Approves a token for the maximum possible amount minus one /// @param token The token to approve function approveMaxMinusOne(address token) external payable; /// @notice Approves a token for zero, then the maximum possible amount /// @param token The token to approve function approveZeroThenMax(address token) external payable; /// @notice Approves a token for zero, then the maximum possible amount minus one /// @param token The token to approve function approveZeroThenMaxMinusOne(address token) external payable; /// @notice Calls the position manager with arbitrary calldata /// @param data Calldata to pass along to the position manager /// @return result The result from the call function callPositionManager(bytes memory data) external payable returns (bytes memory result); struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Min; uint256 amount1Min; address recipient; } /// @notice Calls the position manager's mint function /// @param params Calldata to pass along to the position manager /// @return result The result from the call function mint(MintParams calldata params) external payable returns (bytes memory result); struct IncreaseLiquidityParams { address token0; address token1; uint256 tokenId; uint256 amount0Min; uint256 amount1Min; } /// @notice Calls the position manager's increaseLiquidity function /// @param params Calldata to pass along to the position manager /// @return result The result from the call function increaseLiquidity(IncreaseLiquidityParams calldata params) external payable returns (bytes memory result); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; import {IMulticall} from '../../v3-periphery/interfaces/IMulticall.sol'; /// @title MulticallExtended interface /// @notice Enables calling multiple methods in a single call to the contract with optional validation interface IMulticallExtended is IMulticall { /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` should not be trusted for any method callable from multicall. /// @param deadline The time by which this function must be called before failing /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(uint256 deadline, bytes[] calldata data) external payable returns (bytes[] memory results); /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` should not be trusted for any method callable from multicall. /// @param previousBlockhash The expected parent blockHash /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(bytes32 previousBlockhash, bytes[] calldata data) external payable returns (bytes[] memory results); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; import {ISelfPermit} from '../../v3-periphery/interfaces/ISelfPermit.sol'; import {IApproveAndCall} from './IApproveAndCall.sol'; import {IMulticallExtended} from './IMulticallExtended.sol'; import {IV2SwapRouter} from './IV2SwapRouter.sol'; import {IV3SwapRouter} from './IV3SwapRouter.sol'; /// @title Router token swapping functionality interface ISwapRouter02 is IV2SwapRouter, IV3SwapRouter, IApproveAndCall, IMulticallExtended, ISelfPermit {}
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V2 interface IV2SwapRouter { /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, /// and swap the entire amount, enabling contracts to send tokens before calling this function. /// @param amountIn The amount of token to swap /// @param amountOutMin The minimum amount of output that must be received /// @param path The ordered list of tokens to swap through /// @param to The recipient address /// @return amountOut The amount of the received token function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to) external payable returns (uint256 amountOut); /// @notice Swaps as little as possible of one token for an exact amount of another token /// @param amountOut The amount of token to swap for /// @param amountInMax The maximum amount of input that the caller will pay /// @param path The ordered list of tokens to swap through /// @param to The recipient address /// @return amountIn The amount of token to pay function swapTokensForExactTokens(uint256 amountOut, uint256 amountInMax, address[] calldata path, address to) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; import {IUniswapV3SwapCallback} from '../../v3-core/interfaces/callback/IUniswapV3SwapCallback.sol'; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface IV3SwapRouter is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, /// and swap the entire amount, enabling contracts to send tokens before calling this function. /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, /// and swap the entire amount, enabling contracts to send tokens before calling this function. /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// that may remain in the router after the swap. /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// that may remain in the router after the swap. /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.2; interface IUniversalRouter { /// @notice Thrown when a required command has failed error ExecutionFailed(uint256 commandIndex, bytes message); /// @notice Thrown when attempting to send ETH directly to the contract error ETHNotAccepted(); /// @notice Thrown when executing commands with an expired deadline error TransactionDeadlinePassed(); /// @notice Thrown when attempting to execute commands and an incorrect number of inputs are provided error LengthMismatch(); // @notice Thrown when an address that isn't WETH tries to send ETH to the router without calldata error InvalidEthSender(); /// @notice Executes encoded commands along with provided inputs. Reverts if deadline has expired. /// @param commands A set of concatenated commands, each 1 byte in length /// @param inputs An array of byte strings containing abi encoded inputs for each command /// @param deadline The deadline by which the transaction must be executed function execute(bytes calldata commands, bytes[] calldata inputs, uint256 deadline) external payable; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.2; struct RouterParameters { // Payment parameters address permit2; address weth9; // Uniswap swapping parameters address v2Factory; address v3Factory; bytes32 pairInitCodeHash; bytes32 poolInitCodeHash; address v4PoolManager; // Uniswap v3->v4 migration parameters address v3NFTPositionManager; address v4PositionManager; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IEIP712} from './IEIP712.sol'; /// @title AllowanceTransfer /// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts /// @dev Requires user's token approval on the Permit2 contract interface IAllowanceTransfer is IEIP712 { /// @notice A token spender pair. struct TokenSpenderPair { // the token the spender is approved address token; // the spender address address spender; } /// @notice A mapping from owner address to token address to spender address to PackedAllowance struct, which contains details and conditions of the approval. /// @notice The mapping is indexed in the above order see: allowance[ownerAddress][tokenAddress][spenderAddress] /// @dev The packed slot holds the allowed amount, expiration at which the allowed amount is no longer valid, and current nonce thats updated on any signature based approvals. function allowance(address user, address token, address spender) external view returns (uint160 amount, uint48 expiration, uint48 nonce); /// @notice Approves the spender to use up to amount of the specified token up until the expiration /// @param token The token to approve /// @param spender The spender address to approve /// @param amount The approved amount of the token /// @param expiration The timestamp at which the approval is no longer valid /// @dev The packed allowance also holds a nonce, which will stay unchanged in approve /// @dev Setting amount to type(uint160).max sets an unlimited approval function approve(address token, address spender, uint160 amount, uint48 expiration) external; /// @notice Enables performing a "lockdown" of the sender's Permit2 identity /// by batch revoking approvals /// @param approvals Array of approvals to revoke. function lockdown(TokenSpenderPair[] calldata approvals) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; interface IEIP712 { function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; import {ERC20} from '../../lib-external/solmate/src/tokens/ERC20.sol'; import {IAllowanceTransfer} from '../external/IAllowanceTransfer.sol'; /// @notice The collector of protocol fees that will be used to swap and send to a fee recipient address. interface IFeeCollector { /// @notice Error thrown when the call to UniversalRouter fails. error UniversalRouterCallFailed(); /// @notice Emitted when the UniversalRouter address is changed. /// @param oldUniversalRouter The old router address. /// @param newUniversalRouter The new router address. event UniversalRouterChanged(address oldUniversalRouter, address newUniversalRouter); /// @notice Swaps the contract balance. /// @param swapData The bytes call data to be forwarded to UniversalRouter. /// @param nativeValue The amount of native currency to send to UniversalRouter. function swapBalance(bytes calldata swapData, uint256 nativeValue) external; /// @notice Approves tokens for swapping and then swaps the contract balance. /// @param swapData The bytes call data to be forwarded to UniversalRouter. /// @param nativeValue The amount of native currency to send to UniversalRouter. /// @param tokensToApprove An array of ERC20 tokens to approve for spending. function swapBalance(bytes calldata swapData, uint256 nativeValue, ERC20[] calldata tokensToApprove) external; /// @notice Revokes approvals on tokens by setting their allowance to 0. /// @param tokensToRevoke The token to revoke the approval for. function revokeTokenApprovals(ERC20[] calldata tokensToRevoke) external; /// @notice Revokes the permit2 allowance of a spender by setting token allowances to 0. /// @param approvals The approvals to revoke. function revokePermit2Approvals(IAllowanceTransfer.TokenSpenderPair[] calldata approvals) external; /// @notice Transfers the fee token balance from this contract to the fee recipient. /// @param feeRecipient The address to send the fee token balance to. /// @param amount The amount to withdraw. function withdrawFeeToken(address feeRecipient, uint256 amount) external; /// @notice Sets the address of the UniversalRouter contract. /// @param _universalRouter The address of the UniversalRouter contract. function setUniversalRouter(address _universalRouter) external; }
pragma solidity >=0.5.0; interface IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint256); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint256) external view returns (address pair); function allPairsLength() external view returns (uint256); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; }
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity); function addLiquidityETH( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity); function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETH( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountToken, uint256 amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETHWithPermit( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountToken, uint256 amountETH); function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactETHForTokens(uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external payable returns (uint256[] memory amounts); function swapTokensForExactETH( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactTokensForETH( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapETHForExactTokens(uint256 amountOut, address[] calldata path, address to, uint256 deadline) external payable returns (uint256[] memory amounts); function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) external pure returns (uint256 amountB); function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut) external pure returns (uint256 amountOut); function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut) external pure returns (uint256 amountIn); function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts); }
pragma solidity >=0.6.2; import {IUniswapV2Router01} from './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title The interface for the Uniswap V3 Factory /// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees interface IUniswapV3Factory { /// @notice Emitted when the owner of the factory is changed /// @param oldOwner The owner before the owner was changed /// @param newOwner The owner after the owner was changed event OwnerChanged(address indexed oldOwner, address indexed newOwner); /// @notice Emitted when a pool is created /// @param token0 The first token of the pool by address sort order /// @param token1 The second token of the pool by address sort order /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @param tickSpacing The minimum number of ticks between initialized ticks /// @param pool The address of the created pool event PoolCreated( address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool ); /// @notice Emitted when a new fee amount is enabled for pool creation via the factory /// @param fee The enabled fee, denominated in hundredths of a bip /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing); /// @notice Returns the current owner of the factory /// @dev Can be changed by the current owner via setOwner /// @return The address of the factory owner function owner() external view returns (address); /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee /// @return The tick spacing function feeAmountTickSpacing(uint24 fee) external view returns (int24); /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order /// @param tokenA The contract address of either token0 or token1 /// @param tokenB The contract address of the other token /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @return pool The pool address function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address pool); /// @notice Creates a pool for the given two tokens and fee /// @param tokenA One of the two tokens in the desired pool /// @param tokenB The other of the two tokens in the desired pool /// @param fee The desired fee for the pool /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments /// are invalid. /// @return pool The address of the newly created pool function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool); /// @notice Updates the owner of the factory /// @dev Must be called by the current owner /// @param _owner The new owner of the factory function setOwner(address _owner) external; /// @notice Enables a fee amount with the given tickSpacing /// @dev Fee amounts may never be removed once enabled /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6) /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount function enableFeeAmount(uint24 fee, int24 tickSpacing) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; import {IERC721} from '../../lib-external/oz-v3.4-solc-0.7/contracts/token/ERC721/IERC721.sol'; /// @title ERC721 with permit /// @notice Extension to ERC721 that includes a permit function for signature based approvals interface IERC721Permit is IERC721 { /// @notice The permit typehash used in the permit signature /// @return The typehash for the permit function PERMIT_TYPEHASH() external pure returns (bytes32); /// @notice The domain separator used in the permit signature /// @return The domain seperator used in encoding of permit signature function DOMAIN_SEPARATOR() external view returns (bytes32); /// @notice Approve of a specific token ID for spending by spender via signature /// @param spender The account that is being approved /// @param tokenId The ID of the token that is being approved for spending /// @param deadline The deadline timestamp by which the call must be mined for the approve to work /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; /// @title Multicall interface /// @notice Enables calling multiple methods in a single call to the contract interface IMulticall { /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` should not be trusted for any method callable from multicall. /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; import {IERC721Enumerable} from '../../lib-external/oz-v3.4-solc-0.7/contracts/token/ERC721/IERC721Enumerable.sol'; import {IERC721Metadata} from '../../lib-external/oz-v3.4-solc-0.7/contracts/token/ERC721/IERC721Metadata.sol'; import {IERC721Permit} from './IERC721Permit.sol'; import {IPeripheryImmutableState} from './IPeripheryImmutableState.sol'; import {IPeripheryPayments} from './IPeripheryPayments.sol'; import {IPoolInitializer} from './IPoolInitializer.sol'; /// @title Non-fungible token for positions /// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred /// and authorized. interface INonfungiblePositionManager is IPoolInitializer, IPeripheryPayments, IPeripheryImmutableState, IERC721Metadata, IERC721Enumerable, IERC721Permit { /// @notice Emitted when liquidity is increased for a position NFT /// @dev Also emitted when a token is minted /// @param tokenId The ID of the token for which liquidity was increased /// @param liquidity The amount by which liquidity for the NFT position was increased /// @param amount0 The amount of token0 that was paid for the increase in liquidity /// @param amount1 The amount of token1 that was paid for the increase in liquidity event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); /// @notice Emitted when liquidity is decreased for a position NFT /// @param tokenId The ID of the token for which liquidity was decreased /// @param liquidity The amount by which liquidity for the NFT position was decreased /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); /// @notice Emitted when tokens are collected for a position NFT /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior /// @param tokenId The ID of the token for which underlying tokens were collected /// @param recipient The address of the account that received the collected tokens /// @param amount0 The amount of token0 owed to the position that was collected /// @param amount1 The amount of token1 owed to the position that was collected event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1); /// @notice Returns the position information associated with a given token ID. /// @dev Throws if the token ID is not valid. /// @param tokenId The ID of the token that represents the position /// @return nonce The nonce for permits /// @return operator The address that is approved for spending /// @return token0 The address of the token0 for a specific pool /// @return token1 The address of the token1 for a specific pool /// @return fee The fee associated with the pool /// @return tickLower The lower end of the tick range for the position /// @return tickUpper The higher end of the tick range for the position /// @return liquidity The liquidity of the position /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation function positions(uint256 tokenId) external view returns ( uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1 ); struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; } /// @notice Creates a new position wrapped in a NFT /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized /// a method does not exist, i.e. the pool is assumed to be initialized. /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata /// @return tokenId The ID of the token that represents the minted position /// @return liquidity The amount of liquidity for this position /// @return amount0 The amount of token0 /// @return amount1 The amount of token1 function mint(MintParams calldata params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); struct IncreaseLiquidityParams { uint256 tokenId; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender` /// @param params tokenId The ID of the token for which liquidity is being increased, /// amount0Desired The desired amount of token0 to be spent, /// amount1Desired The desired amount of token1 to be spent, /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check, /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check, /// deadline The time by which the transaction must be included to effect the change /// @return liquidity The new liquidity amount as a result of the increase /// @return amount0 The amount of token0 to acheive resulting liquidity /// @return amount1 The amount of token1 to acheive resulting liquidity function increaseLiquidity(IncreaseLiquidityParams calldata params) external payable returns (uint128 liquidity, uint256 amount0, uint256 amount1); struct DecreaseLiquidityParams { uint256 tokenId; uint128 liquidity; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } /// @notice Decreases the amount of liquidity in a position and accounts it to the position /// @param params tokenId The ID of the token for which liquidity is being decreased, /// amount The amount by which liquidity will be decreased, /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity, /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity, /// deadline The time by which the transaction must be included to effect the change /// @return amount0 The amount of token0 accounted to the position's tokens owed /// @return amount1 The amount of token1 accounted to the position's tokens owed function decreaseLiquidity(DecreaseLiquidityParams calldata params) external payable returns (uint256 amount0, uint256 amount1); struct CollectParams { uint256 tokenId; address recipient; uint128 amount0Max; uint128 amount1Max; } /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient /// @param params tokenId The ID of the NFT for which tokens are being collected, /// recipient The account that should receive the tokens, /// amount0Max The maximum amount of token0 to collect, /// amount1Max The maximum amount of token1 to collect /// @return amount0 The amount of fees collected in token0 /// @return amount1 The amount of fees collected in token1 function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1); /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens /// must be collected first. /// @param tokenId The ID of the token that is being burned function burn(uint256 tokenId) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import {INonfungiblePositionManager} from './INonfungiblePositionManager.sol'; /// @title Describes position NFT tokens via URI interface INonfungibleTokenPositionDescriptor { /// @notice Produces the URI describing a particular token ID for a position manager /// @dev Note this URI may be a data: URI with the JSON contents directly inlined /// @param positionManager The position manager for which to describe the token /// @param tokenId The ID of the token for which to produce a description, which may not be valid /// @return The URI of the ERC721-compliant metadata function tokenURI(INonfungiblePositionManager positionManager, uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Immutable state /// @notice Functions that return immutable state of the router interface IPeripheryImmutableState { /// @return Returns the address of the Uniswap V3 factory function factory() external view returns (address); /// @return Returns the address of WETH9 function WETH9() external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; /// @title Periphery Payments /// @notice Functions to ease deposits and withdrawals of ETH interface IPeripheryPayments { /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH. /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users. /// @param amountMinimum The minimum amount of WETH9 to unwrap /// @param recipient The address receiving ETH function unwrapWETH9(uint256 amountMinimum, address recipient) external payable; /// @notice Refunds any ETH balance held by this contract to the `msg.sender` /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps /// that use ether for the input amount function refundETH() external payable; /// @notice Transfers the full amount of a token held by this contract to recipient /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users /// @param token The contract address of the token which will be transferred to `recipient` /// @param amountMinimum The minimum amount of token required for a transfer /// @param recipient The destination address of the token function sweepToken(address token, uint256 amountMinimum, address recipient) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; /// @title Creates and initializes V3 Pools /// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that /// require the pool to exist. interface IPoolInitializer { /// @notice Creates a new pool if it does not exist, then initializes if not initialized /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool /// @param token0 The contract address of token0 of the pool /// @param token1 The contract address of token1 of the pool /// @param fee The fee amount of the v3 pool for the specified token pair /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary function createAndInitializePoolIfNecessary(address token0, address token1, uint24 fee, uint160 sqrtPriceX96) external payable returns (address pool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; /// @title QuoterV2 Interface /// @notice Supports quoting the calculated amounts from exact input or exact output swaps. /// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap. /// @dev These functions are not marked view because they rely on calling non-view functions and reverting /// to compute the result. They are also not gas efficient and should not be called on-chain. interface IQuoterV2 { /// @notice Returns the amount out received for a given exact input swap without executing the swap /// @param path The path of the swap, i.e. each token pair and the pool fee /// @param amountIn The amount of the first token to swap /// @return amountOut The amount of the last token that would be received /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path /// @return gasEstimate The estimate of the gas that the swap consumes function quoteExactInput(bytes memory path, uint256 amountIn) external returns ( uint256 amountOut, uint160[] memory sqrtPriceX96AfterList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate ); struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; uint24 fee; uint160 sqrtPriceLimitX96; } /// @notice Returns the amount out received for a given exact input but for a swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactInputSingleParams` /// tokenIn The token being swapped in /// tokenOut The token being swapped out /// fee The fee of the token pool to consider for the pair /// amountIn The desired input amount /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap /// @return amountOut The amount of `tokenOut` that would be received /// @return sqrtPriceX96After The sqrt price of the pool after the swap /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed /// @return gasEstimate The estimate of the gas that the swap consumes function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate); /// @notice Returns the amount in required for a given exact output swap without executing the swap /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order /// @param amountOut The amount of the last token to receive /// @return amountIn The amount of first token required to be paid /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path /// @return gasEstimate The estimate of the gas that the swap consumes function quoteExactOutput(bytes memory path, uint256 amountOut) external returns ( uint256 amountIn, uint160[] memory sqrtPriceX96AfterList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate ); struct QuoteExactOutputSingleParams { address tokenIn; address tokenOut; uint256 amount; uint24 fee; uint160 sqrtPriceLimitX96; } /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactOutputSingleParams` /// tokenIn The token being swapped in /// tokenOut The token being swapped out /// fee The fee of the token pool to consider for the pair /// amountOut The desired output amount /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap /// @return amountIn The amount required as the input for the swap in order to receive `amountOut` /// @return sqrtPriceX96After The sqrt price of the pool after the swap /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed /// @return gasEstimate The estimate of the gas that the swap consumes function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params) external returns (uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; /// @title Self Permit /// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route interface ISelfPermit { /// @notice Permits this contract to spend a given token from `msg.sender` /// @dev The `owner` is always msg.sender and the `spender` is always address(this). /// @param token The address of the token spent /// @param value The amount that can be spent of token /// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function selfPermit(address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external payable; /// @notice Permits this contract to spend a given token from `msg.sender` /// @dev The `owner` is always msg.sender and the `spender` is always address(this). /// Can be used instead of #selfPermit to prevent calls from failing due to a frontrun of a call to #selfPermit /// @param token The address of the token spent /// @param value The amount that can be spent of token /// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function selfPermitIfNecessary(address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external payable; /// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter /// @dev The `owner` is always msg.sender and the `spender` is always address(this) /// @param token The address of the token spent /// @param nonce The current nonce of the owner /// @param expiry The timestamp at which the permit is no longer valid /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function selfPermitAllowed(address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external payable; /// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter /// @dev The `owner` is always msg.sender and the `spender` is always address(this) /// Can be used instead of #selfPermitAllowed to prevent calls from failing due to a frontrun of a call to #selfPermitAllowed. /// @param token The address of the token spent /// @param nonce The current nonce of the owner /// @param expiry The timestamp at which the permit is no longer valid /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function selfPermitAllowedIfNecessary(address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; import {IUniswapV3SwapCallback} from '../../v3-core/interfaces/callback/IUniswapV3SwapCallback.sol'; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouter is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; /// @title Tick Lens /// @notice Provides functions for fetching chunks of tick data for a pool /// @dev This avoids the waterfall of fetching the tick bitmap, parsing the bitmap to know which ticks to fetch, and /// then sending additional multicalls to fetch the tick data interface ITickLens { struct PopulatedTick { int24 tick; int128 liquidityNet; uint128 liquidityGross; } /// @notice Get all the tick data for the populated ticks from a word of the tick bitmap of a pool /// @param pool The address of the pool for which to fetch populated tick data /// @param tickBitmapIndex The index of the word in the tick bitmap for which to parse the bitmap and /// fetch all the populated ticks /// @return populatedTicks An array of tick data for the given word in the tick bitmap function getPopulatedTicksInWord(address pool, int16 tickBitmapIndex) external view returns (PopulatedTick[] memory populatedTicks); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; import {IMulticall} from './IMulticall.sol'; import {IPoolInitializer} from './IPoolInitializer.sol'; import {ISelfPermit} from './ISelfPermit.sol'; /// @title V3 Migrator /// @notice Enables migration of liqudity from Uniswap v2-compatible pairs into Uniswap v3 pools interface IV3Migrator is IMulticall, ISelfPermit, IPoolInitializer { struct MigrateParams { address pair; // the Uniswap v2-compatible pair uint256 liquidityToMigrate; // expected to be balanceOf(msg.sender) uint8 percentageToMigrate; // represented as a numerator over 100 address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Min; // must be discounted by percentageToMigrate uint256 amount1Min; // must be discounted by percentageToMigrate address recipient; uint256 deadline; bool refundAsETH; } /// @notice Migrates liquidity to v3 by burning v2 liquidity and minting a new position for v3 /// @dev Slippage protection is enforced via `amount{0,1}Min`, which should be a discount of the expected values of /// the maximum amount of v3 liquidity that the v2 liquidity can get. For the special case of migrating to an /// out-of-range position, `amount{0,1}Min` may be set to 0, enforcing that the position remains out of range /// @param params The params necessary to migrate v2 liquidity, encoded as `MigrateParams` in calldata function migrate(MigrateParams calldata params) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /// @notice Interface for functions to access any storage slot in a contract interface IExtsload { /// @notice Called by external contracts to access granular pool state /// @param slot Key of slot to sload /// @return value The value of the slot as bytes32 function extsload(bytes32 slot) external view returns (bytes32 value); /// @notice Called by external contracts to access granular pool state /// @param startSlot Key of slot to start sloading from /// @param nSlots Number of slots to load into return value /// @return values List of loaded values. function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory values); /// @notice Called by external contracts to access sparse pool state /// @param slots List of slots to SLOAD from. /// @return values List of loaded values. function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory values); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /// @notice Interface for functions to access any transient storage slot in a contract interface IExttload { /// @notice Called by external contracts to access transient storage of the contract /// @param slot Key of slot to tload /// @return value The value of the slot as bytes32 function exttload(bytes32 slot) external view returns (bytes32 value); /// @notice Called by external contracts to access sparse transient pool state /// @param slots List of slots to tload /// @return values List of loaded values function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory values); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {BalanceDelta} from '../types/BalanceDelta.sol'; import {BeforeSwapDelta} from '../types/BeforeSwapDelta.sol'; import {PoolKey} from '../types/PoolKey.sol'; import {IPoolManager} from './IPoolManager.sol'; /// @notice V4 decides whether to invoke specific hooks by inspecting the least significant bits /// of the address that the hooks contract is deployed to. /// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400 /// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used. /// See the Hooks library for the full spec. /// @dev Should only be callable by the v4 PoolManager. interface IHooks { /// @notice The hook called before the state of a pool is initialized /// @param sender The initial msg.sender for the initialize call /// @param key The key for the pool being initialized /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 /// @return bytes4 The function selector for the hook function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96) external returns (bytes4); /// @notice The hook called after the state of a pool is initialized /// @param sender The initial msg.sender for the initialize call /// @param key The key for the pool being initialized /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 /// @param tick The current tick after the state of a pool is initialized /// @return bytes4 The function selector for the hook function afterInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, int24 tick) external returns (bytes4); /// @notice The hook called before liquidity is added /// @param sender The initial msg.sender for the add liquidity call /// @param key The key for the pool /// @param params The parameters for adding liquidity /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook /// @return bytes4 The function selector for the hook function beforeAddLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, bytes calldata hookData ) external returns (bytes4); /// @notice The hook called after liquidity is added /// @param sender The initial msg.sender for the add liquidity call /// @param key The key for the pool /// @param params The parameters for adding liquidity /// @param delta The caller's balance delta after adding liquidity; the sum of principal delta, fees accrued, and hook delta /// @param feesAccrued The fees accrued since the last time fees were collected from this position /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook /// @return bytes4 The function selector for the hook /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency function afterAddLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external returns (bytes4, BalanceDelta); /// @notice The hook called before liquidity is removed /// @param sender The initial msg.sender for the remove liquidity call /// @param key The key for the pool /// @param params The parameters for removing liquidity /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook /// @return bytes4 The function selector for the hook function beforeRemoveLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, bytes calldata hookData ) external returns (bytes4); /// @notice The hook called after liquidity is removed /// @param sender The initial msg.sender for the remove liquidity call /// @param key The key for the pool /// @param params The parameters for removing liquidity /// @param delta The caller's balance delta after removing liquidity; the sum of principal delta, fees accrued, and hook delta /// @param feesAccrued The fees accrued since the last time fees were collected from this position /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook /// @return bytes4 The function selector for the hook /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency function afterRemoveLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external returns (bytes4, BalanceDelta); /// @notice The hook called before a swap /// @param sender The initial msg.sender for the swap call /// @param key The key for the pool /// @param params The parameters for the swap /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook /// @return bytes4 The function selector for the hook /// @return BeforeSwapDelta The hook's delta in specified and unspecified currencies. Positive: the hook is owed/took currency, negative: the hook owes/sent currency /// @return uint24 Optionally override the lp fee, only used if three conditions are met: 1. the Pool has a dynamic fee, 2. the value's 2nd highest bit is set (23rd bit, 0x400000), and 3. the value is less than or equal to the maximum fee (1 million) function beforeSwap( address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata hookData ) external returns (bytes4, BeforeSwapDelta, uint24); /// @notice The hook called after a swap /// @param sender The initial msg.sender for the swap call /// @param key The key for the pool /// @param params The parameters for the swap /// @param delta The amount owed to the caller (positive) or owed to the pool (negative) /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook /// @return bytes4 The function selector for the hook /// @return int128 The hook's delta in unspecified currency. Positive: the hook is owed/took currency, negative: the hook owes/sent currency function afterSwap( address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, BalanceDelta delta, bytes calldata hookData ) external returns (bytes4, int128); /// @notice The hook called before donate /// @param sender The initial msg.sender for the donate call /// @param key The key for the pool /// @param amount0 The amount of token0 being donated /// @param amount1 The amount of token1 being donated /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook /// @return bytes4 The function selector for the hook function beforeDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external returns (bytes4); /// @notice The hook called after donate /// @param sender The initial msg.sender for the donate call /// @param key The key for the pool /// @param amount0 The amount of token0 being donated /// @param amount1 The amount of token1 being donated /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook /// @return bytes4 The function selector for the hook function afterDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {BalanceDelta} from '../types/BalanceDelta.sol'; import {Currency} from '../types/Currency.sol'; import {PoolId} from '../types/PoolId.sol'; import {PoolKey} from '../types/PoolKey.sol'; import {IExtsload} from './IExtsload.sol'; import {IExttload} from './IExttload.sol'; import {IHooks} from './IHooks.sol'; import {IProtocolFees} from './IProtocolFees.sol'; import {IERC6909Claims} from './external/IERC6909Claims.sol'; /// @notice Interface for the PoolManager interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload, IExttload { /// @notice Thrown when a currency is not netted out after the contract is unlocked error CurrencyNotSettled(); /// @notice Thrown when trying to interact with a non-initialized pool error PoolNotInitialized(); /// @notice Thrown when unlock is called, but the contract is already unlocked error AlreadyUnlocked(); /// @notice Thrown when a function is called that requires the contract to be unlocked, but it is not error ManagerLocked(); /// @notice Pools are limited to type(int16).max tickSpacing in #initialize, to prevent overflow error TickSpacingTooLarge(int24 tickSpacing); /// @notice Pools must have a positive non-zero tickSpacing passed to #initialize error TickSpacingTooSmall(int24 tickSpacing); /// @notice PoolKey must have currencies where address(currency0) < address(currency1) error CurrenciesOutOfOrderOrEqual(address currency0, address currency1); /// @notice Thrown when a call to updateDynamicLPFee is made by an address that is not the hook, /// or on a pool that does not have a dynamic swap fee. error UnauthorizedDynamicLPFeeUpdate(); /// @notice Thrown when trying to swap amount of 0 error SwapAmountCannotBeZero(); ///@notice Thrown when native currency is passed to a non native settlement error NonzeroNativeValue(); /// @notice Thrown when `clear` is called with an amount that is not exactly equal to the open currency delta. error MustClearExactPositiveDelta(); /// @notice Emitted when a new pool is initialized /// @param id The abi encoded hash of the pool key struct for the new pool /// @param currency0 The first currency of the pool by address sort order /// @param currency1 The second currency of the pool by address sort order /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @param tickSpacing The minimum number of ticks between initialized ticks /// @param hooks The hooks contract address for the pool, or address(0) if none /// @param sqrtPriceX96 The price of the pool on initialization /// @param tick The initial tick of the pool corresponding to the initialized price event Initialize( PoolId indexed id, Currency indexed currency0, Currency indexed currency1, uint24 fee, int24 tickSpacing, IHooks hooks, uint160 sqrtPriceX96, int24 tick ); /// @notice Emitted when a liquidity position is modified /// @param id The abi encoded hash of the pool key struct for the pool that was modified /// @param sender The address that modified the pool /// @param tickLower The lower tick of the position /// @param tickUpper The upper tick of the position /// @param liquidityDelta The amount of liquidity that was added or removed /// @param salt The extra data to make positions unique event ModifyLiquidity( PoolId indexed id, address indexed sender, int24 tickLower, int24 tickUpper, int256 liquidityDelta, bytes32 salt ); /// @notice Emitted for swaps between currency0 and currency1 /// @param id The abi encoded hash of the pool key struct for the pool that was modified /// @param sender The address that initiated the swap call, and that received the callback /// @param amount0 The delta of the currency0 balance of the pool /// @param amount1 The delta of the currency1 balance of the pool /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96 /// @param liquidity The liquidity of the pool after the swap /// @param tick The log base 1.0001 of the price of the pool after the swap /// @param fee The swap fee in hundredths of a bip event Swap( PoolId indexed id, address indexed sender, int128 amount0, int128 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick, uint24 fee ); /// @notice Emitted for donations /// @param id The abi encoded hash of the pool key struct for the pool that was donated to /// @param sender The address that initiated the donate call /// @param amount0 The amount donated in currency0 /// @param amount1 The amount donated in currency1 event Donate(PoolId indexed id, address indexed sender, uint256 amount0, uint256 amount1); /// @notice All interactions on the contract that account deltas require unlocking. A caller that calls `unlock` must implement /// `IUnlockCallback(msg.sender).unlockCallback(data)`, where they interact with the remaining functions on this contract. /// @dev The only functions callable without an unlocking are `initialize` and `updateDynamicLPFee` /// @param data Any data to pass to the callback, via `IUnlockCallback(msg.sender).unlockCallback(data)` /// @return The data returned by the call to `IUnlockCallback(msg.sender).unlockCallback(data)` function unlock(bytes calldata data) external returns (bytes memory); /// @notice Initialize the state for a given pool ID /// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee /// @param key The pool key for the pool to initialize /// @param sqrtPriceX96 The initial square root price /// @return tick The initial tick of the pool function initialize(PoolKey memory key, uint160 sqrtPriceX96) external returns (int24 tick); struct ModifyLiquidityParams { // the lower and upper tick of the position int24 tickLower; int24 tickUpper; // how to modify the liquidity int256 liquidityDelta; // a value to set if you want unique liquidity positions at the same range bytes32 salt; } /// @notice Modify the liquidity for the given pool /// @dev Poke by calling with a zero liquidityDelta /// @param key The pool to modify liquidity in /// @param params The parameters for modifying the liquidity /// @param hookData The data to pass through to the add/removeLiquidity hooks /// @return callerDelta The balance delta of the caller of modifyLiquidity. This is the total of both principal, fee deltas, and hook deltas if applicable /// @return feesAccrued The balance delta of the fees generated in the liquidity range. Returned for informational purposes /// @dev Note that feesAccrued can be artificially inflated by a malicious actor and integrators should be careful using the value /// For pools with a single liquidity position, actors can donate to themselves to inflate feeGrowthGlobal (and consequently feesAccrued) /// atomically donating and collecting fees in the same unlockCallback may make the inflated value more extreme function modifyLiquidity(PoolKey memory key, ModifyLiquidityParams memory params, bytes calldata hookData) external returns (BalanceDelta callerDelta, BalanceDelta feesAccrued); struct SwapParams { /// Whether to swap token0 for token1 or vice versa bool zeroForOne; /// The desired input amount if negative (exactIn), or the desired output amount if positive (exactOut) int256 amountSpecified; /// The sqrt price at which, if reached, the swap will stop executing uint160 sqrtPriceLimitX96; } /// @notice Swap against the given pool /// @param key The pool to swap in /// @param params The parameters for swapping /// @param hookData The data to pass through to the swap hooks /// @return swapDelta The balance delta of the address swapping /// @dev Swapping on low liquidity pools may cause unexpected swap amounts when liquidity available is less than amountSpecified. /// Additionally note that if interacting with hooks that have the BEFORE_SWAP_RETURNS_DELTA_FLAG or AFTER_SWAP_RETURNS_DELTA_FLAG /// the hook may alter the swap input/output. Integrators should perform checks on the returned swapDelta. function swap(PoolKey memory key, SwapParams memory params, bytes calldata hookData) external returns (BalanceDelta swapDelta); /// @notice Donate the given currency amounts to the in-range liquidity providers of a pool /// @dev Calls to donate can be frontrun adding just-in-time liquidity, with the aim of receiving a portion donated funds. /// Donors should keep this in mind when designing donation mechanisms. /// @dev This function donates to in-range LPs at slot0.tick. In certain edge-cases of the swap algorithm, the `sqrtPrice` of /// a pool can be at the lower boundary of tick `n`, but the `slot0.tick` of the pool is already `n - 1`. In this case a call to /// `donate` would donate to tick `n - 1` (slot0.tick) not tick `n` (getTickAtSqrtPrice(slot0.sqrtPriceX96)). /// Read the comments in `Pool.swap()` for more information about this. /// @param key The key of the pool to donate to /// @param amount0 The amount of currency0 to donate /// @param amount1 The amount of currency1 to donate /// @param hookData The data to pass through to the donate hooks /// @return BalanceDelta The delta of the caller after the donate function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) external returns (BalanceDelta); /// @notice Writes the current ERC20 balance of the specified currency to transient storage /// This is used to checkpoint balances for the manager and derive deltas for the caller. /// @dev This MUST be called before any ERC20 tokens are sent into the contract, but can be skipped /// for native tokens because the amount to settle is determined by the sent value. /// However, if an ERC20 token has been synced and not settled, and the caller instead wants to settle /// native funds, this function can be called with the native currency to then be able to settle the native currency function sync(Currency currency) external; /// @notice Called by the user to net out some value owed to the user /// @dev Will revert if the requested amount is not available, consider using `mint` instead /// @dev Can also be used as a mechanism for free flash loans /// @param currency The currency to withdraw from the pool manager /// @param to The address to withdraw to /// @param amount The amount of currency to withdraw function take(Currency currency, address to, uint256 amount) external; /// @notice Called by the user to pay what is owed /// @return paid The amount of currency settled function settle() external payable returns (uint256 paid); /// @notice Called by the user to pay on behalf of another address /// @param recipient The address to credit for the payment /// @return paid The amount of currency settled function settleFor(address recipient) external payable returns (uint256 paid); /// @notice WARNING - Any currency that is cleared, will be non-retrievable, and locked in the contract permanently. /// A call to clear will zero out a positive balance WITHOUT a corresponding transfer. /// @dev This could be used to clear a balance that is considered dust. /// Additionally, the amount must be the exact positive balance. This is to enforce that the caller is aware of the amount being cleared. function clear(Currency currency, uint256 amount) external; /// @notice Called by the user to move value into ERC6909 balance /// @param to The address to mint the tokens to /// @param id The currency address to mint to ERC6909s, as a uint256 /// @param amount The amount of currency to mint /// @dev The id is converted to a uint160 to correspond to a currency address /// If the upper 12 bytes are not 0, they will be 0-ed out function mint(address to, uint256 id, uint256 amount) external; /// @notice Called by the user to move value from ERC6909 balance /// @param from The address to burn the tokens from /// @param id The currency address to burn from ERC6909s, as a uint256 /// @param amount The amount of currency to burn /// @dev The id is converted to a uint160 to correspond to a currency address /// If the upper 12 bytes are not 0, they will be 0-ed out function burn(address from, uint256 id, uint256 amount) external; /// @notice Updates the pools lp fees for the a pool that has enabled dynamic lp fees. /// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee /// @param key The key of the pool to update dynamic LP fees for /// @param newDynamicLPFee The new dynamic pool LP fee function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {Currency} from '../types/Currency.sol'; import {PoolId} from '../types/PoolId.sol'; import {PoolKey} from '../types/PoolKey.sol'; /// @notice Interface for all protocol-fee related functions in the pool manager interface IProtocolFees { /// @notice Thrown when protocol fee is set too high error ProtocolFeeTooLarge(uint24 fee); /// @notice Thrown when collectProtocolFees or setProtocolFee is not called by the controller. error InvalidCaller(); /// @notice Thrown when collectProtocolFees is attempted on a token that is synced. error ProtocolFeeCurrencySynced(); /// @notice Emitted when the protocol fee controller address is updated in setProtocolFeeController. event ProtocolFeeControllerUpdated(address indexed protocolFeeController); /// @notice Emitted when the protocol fee is updated for a pool. event ProtocolFeeUpdated(PoolId indexed id, uint24 protocolFee); /// @notice Given a currency address, returns the protocol fees accrued in that currency /// @param currency The currency to check /// @return amount The amount of protocol fees accrued in the currency function protocolFeesAccrued(Currency currency) external view returns (uint256 amount); /// @notice Sets the protocol fee for the given pool /// @param key The key of the pool to set a protocol fee for /// @param newProtocolFee The fee to set function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external; /// @notice Sets the protocol fee controller /// @param controller The new protocol fee controller function setProtocolFeeController(address controller) external; /// @notice Collects the protocol fees for a given recipient and currency, returning the amount collected /// @dev This will revert if the contract is unlocked /// @param recipient The address to receive the protocol fees /// @param currency The currency to withdraw /// @param amount The amount of currency to withdraw /// @return amountCollected The amount of currency successfully withdrawn function collectProtocolFees(address recipient, Currency currency, uint256 amount) external returns (uint256 amountCollected); /// @notice Returns the current protocol fee controller address /// @return address The current protocol fee controller address function protocolFeeController() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /// @title Minimal ERC20 interface for Uniswap /// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3 interface IERC20Minimal { /// @notice Returns an account's balance in the token /// @param account The account for which to look up the number of tokens it has, i.e. its balance /// @return The number of tokens held by the account function balanceOf(address account) external view returns (uint256); /// @notice Transfers the amount of token from the `msg.sender` to the recipient /// @param recipient The account that will receive the amount transferred /// @param amount The number of tokens to send from the sender to the recipient /// @return Returns true for a successful transfer, false for an unsuccessful transfer function transfer(address recipient, uint256 amount) external returns (bool); /// @notice Returns the current allowance given to a spender by an owner /// @param owner The account of the token owner /// @param spender The account of the token spender /// @return The current allowance granted by `owner` to `spender` function allowance(address owner, address spender) external view returns (uint256); /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` /// @param spender The account which will be allowed to spend a given amount of the owners tokens /// @param amount The amount of tokens allowed to be used by `spender` /// @return Returns true for a successful approval, false for unsuccessful function approve(address spender, uint256 amount) external returns (bool); /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` /// @param sender The account from which the transfer will be initiated /// @param recipient The recipient of the transfer /// @param amount The amount of the transfer /// @return Returns true for a successful transfer, false for unsuccessful function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. /// @param from The account from which the tokens were sent, i.e. the balance decreased /// @param to The account to which the tokens were sent, i.e. the balance increased /// @param value The amount of tokens that were transferred event Transfer(address indexed from, address indexed to, uint256 value); /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. /// @param owner The account that approved spending of its tokens /// @param spender The account for which the spending allowance was modified /// @param value The new allowance from the owner to the spender event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /// @notice Interface for claims over a contract balance, wrapped as a ERC6909 interface IERC6909Claims { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OperatorSet(address indexed owner, address indexed operator, bool approved); event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount); event Transfer(address caller, address indexed from, address indexed to, uint256 indexed id, uint256 amount); /*////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Owner balance of an id. /// @param owner The address of the owner. /// @param id The id of the token. /// @return amount The balance of the token. function balanceOf(address owner, uint256 id) external view returns (uint256 amount); /// @notice Spender allowance of an id. /// @param owner The address of the owner. /// @param spender The address of the spender. /// @param id The id of the token. /// @return amount The allowance of the token. function allowance(address owner, address spender, uint256 id) external view returns (uint256 amount); /// @notice Checks if a spender is approved by an owner as an operator /// @param owner The address of the owner. /// @param spender The address of the spender. /// @return approved The approval status. function isOperator(address owner, address spender) external view returns (bool approved); /// @notice Transfers an amount of an id from the caller to a receiver. /// @param receiver The address of the receiver. /// @param id The id of the token. /// @param amount The amount of the token. /// @return bool True, always, unless the function reverts function transfer(address receiver, uint256 id, uint256 amount) external returns (bool); /// @notice Transfers an amount of an id from a sender to a receiver. /// @param sender The address of the sender. /// @param receiver The address of the receiver. /// @param id The id of the token. /// @param amount The amount of the token. /// @return bool True, always, unless the function reverts function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool); /// @notice Approves an amount of an id to a spender. /// @param spender The address of the spender. /// @param id The id of the token. /// @param amount The amount of the token. /// @return bool True, always function approve(address spender, uint256 id, uint256 amount) external returns (bool); /// @notice Sets or removes an operator for the caller. /// @param operator The address of the operator. /// @param approved The approval status. /// @return bool True, always function setOperator(address operator, bool approved) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Library for reverting with custom errors efficiently /// @notice Contains functions for reverting with custom errors with different argument types efficiently /// @dev To use this library, declare `using CustomRevert for bytes4;` and replace `revert CustomError()` with /// `CustomError.selector.revertWith()` /// @dev The functions may tamper with the free memory pointer but it is fine since the call context is exited immediately library CustomRevert { /// @dev ERC-7751 error for wrapping bubbled up reverts error WrappedError(address target, bytes4 selector, bytes reason, bytes details); /// @dev Reverts with the selector of a custom error in the scratch space function revertWith(bytes4 selector) internal pure { assembly ("memory-safe") { mstore(0, selector) revert(0, 0x04) } } /// @dev Reverts with a custom error with an address argument in the scratch space function revertWith(bytes4 selector, address addr) internal pure { assembly ("memory-safe") { mstore(0, selector) mstore(0x04, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) revert(0, 0x24) } } /// @dev Reverts with a custom error with an int24 argument in the scratch space function revertWith(bytes4 selector, int24 value) internal pure { assembly ("memory-safe") { mstore(0, selector) mstore(0x04, signextend(2, value)) revert(0, 0x24) } } /// @dev Reverts with a custom error with a uint160 argument in the scratch space function revertWith(bytes4 selector, uint160 value) internal pure { assembly ("memory-safe") { mstore(0, selector) mstore(0x04, and(value, 0xffffffffffffffffffffffffffffffffffffffff)) revert(0, 0x24) } } /// @dev Reverts with a custom error with two int24 arguments function revertWith(bytes4 selector, int24 value1, int24 value2) internal pure { assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, selector) mstore(add(fmp, 0x04), signextend(2, value1)) mstore(add(fmp, 0x24), signextend(2, value2)) revert(fmp, 0x44) } } /// @dev Reverts with a custom error with two uint160 arguments function revertWith(bytes4 selector, uint160 value1, uint160 value2) internal pure { assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, selector) mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff)) revert(fmp, 0x44) } } /// @dev Reverts with a custom error with two address arguments function revertWith(bytes4 selector, address value1, address value2) internal pure { assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, selector) mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff)) revert(fmp, 0x44) } } /// @notice bubble up the revert message returned by a call and revert with a wrapped ERC-7751 error /// @dev this method can be vulnerable to revert data bombs function bubbleUpAndRevertWith( address revertingContract, bytes4 revertingFunctionSelector, bytes4 additionalContext ) internal pure { bytes4 wrappedErrorSelector = WrappedError.selector; assembly ("memory-safe") { // Ensure the size of the revert data is a multiple of 32 bytes let encodedDataSize := mul(div(add(returndatasize(), 31), 32), 32) let fmp := mload(0x40) // Encode wrapped error selector, address, function selector, offset, additional context, size, revert reason mstore(fmp, wrappedErrorSelector) mstore(add(fmp, 0x04), and(revertingContract, 0xffffffffffffffffffffffffffffffffffffffff)) mstore( add(fmp, 0x24), and(revertingFunctionSelector, 0xffffffff00000000000000000000000000000000000000000000000000000000) ) // offset revert reason mstore(add(fmp, 0x44), 0x80) // offset additional context mstore(add(fmp, 0x64), add(0xa0, encodedDataSize)) // size revert reason mstore(add(fmp, 0x84), returndatasize()) // revert reason returndatacopy(add(fmp, 0xa4), 0, returndatasize()) // size additional context mstore(add(fmp, add(0xa4, encodedDataSize)), 0x04) // additional context mstore( add(fmp, add(0xc4, encodedDataSize)), and(additionalContext, 0xffffffff00000000000000000000000000000000000000000000000000000000) ) revert(fmp, add(0xe4, encodedDataSize)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {CustomRevert} from './CustomRevert.sol'; /// @title Safe casting methods /// @notice Contains methods for safely casting between types library SafeCast { using CustomRevert for bytes4; error SafeCastOverflow(); /// @notice Cast a uint256 to a uint160, revert on overflow /// @param x The uint256 to be downcasted /// @return y The downcasted integer, now type uint160 function toUint160(uint256 x) internal pure returns (uint160 y) { y = uint160(x); if (y != x) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a uint256 to a uint128, revert on overflow /// @param x The uint256 to be downcasted /// @return y The downcasted integer, now type uint128 function toUint128(uint256 x) internal pure returns (uint128 y) { y = uint128(x); if (x != y) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a int128 to a uint128, revert on overflow or underflow /// @param x The int128 to be casted /// @return y The casted integer, now type uint128 function toUint128(int128 x) internal pure returns (uint128 y) { if (x < 0) SafeCastOverflow.selector.revertWith(); y = uint128(x); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param x The int256 to be downcasted /// @return y The downcasted integer, now type int128 function toInt128(int256 x) internal pure returns (int128 y) { y = int128(x); if (y != x) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a uint256 to a int256, revert on overflow /// @param x The uint256 to be casted /// @return y The casted integer, now type int256 function toInt256(uint256 x) internal pure returns (int256 y) { y = int256(x); if (y < 0) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a uint256 to a int128, revert on overflow /// @param x The uint256 to be downcasted /// @return The downcasted integer, now type int128 function toInt128(uint256 x) internal pure returns (int128) { if (x >= 1 << 127) SafeCastOverflow.selector.revertWith(); return int128(int256(x)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {SafeCast} from '../libraries/SafeCast.sol'; /// @dev Two `int128` values packed into a single `int256` where the upper 128 bits represent the amount0 /// and the lower 128 bits represent the amount1. type BalanceDelta is int256; using {add as +, sub as -, eq as ==, neq as !=} for BalanceDelta global; using BalanceDeltaLibrary for BalanceDelta global; using SafeCast for int256; function toBalanceDelta(int128 _amount0, int128 _amount1) pure returns (BalanceDelta balanceDelta) { assembly ("memory-safe") { balanceDelta := or(shl(128, _amount0), and(sub(shl(128, 1), 1), _amount1)) } } function add(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) { int256 res0; int256 res1; assembly ("memory-safe") { let a0 := sar(128, a) let a1 := signextend(15, a) let b0 := sar(128, b) let b1 := signextend(15, b) res0 := add(a0, b0) res1 := add(a1, b1) } return toBalanceDelta(res0.toInt128(), res1.toInt128()); } function sub(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) { int256 res0; int256 res1; assembly ("memory-safe") { let a0 := sar(128, a) let a1 := signextend(15, a) let b0 := sar(128, b) let b1 := signextend(15, b) res0 := sub(a0, b0) res1 := sub(a1, b1) } return toBalanceDelta(res0.toInt128(), res1.toInt128()); } function eq(BalanceDelta a, BalanceDelta b) pure returns (bool) { return BalanceDelta.unwrap(a) == BalanceDelta.unwrap(b); } function neq(BalanceDelta a, BalanceDelta b) pure returns (bool) { return BalanceDelta.unwrap(a) != BalanceDelta.unwrap(b); } /// @notice Library for getting the amount0 and amount1 deltas from the BalanceDelta type library BalanceDeltaLibrary { /// @notice A BalanceDelta of 0 BalanceDelta public constant ZERO_DELTA = BalanceDelta.wrap(0); function amount0(BalanceDelta balanceDelta) internal pure returns (int128 _amount0) { assembly ("memory-safe") { _amount0 := sar(128, balanceDelta) } } function amount1(BalanceDelta balanceDelta) internal pure returns (int128 _amount1) { assembly ("memory-safe") { _amount1 := signextend(15, balanceDelta) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; // Return type of the beforeSwap hook. // Upper 128 bits is the delta in specified tokens. Lower 128 bits is delta in unspecified tokens (to match the afterSwap hook) type BeforeSwapDelta is int256; // Creates a BeforeSwapDelta from specified and unspecified function toBeforeSwapDelta(int128 deltaSpecified, int128 deltaUnspecified) pure returns (BeforeSwapDelta beforeSwapDelta) { assembly ("memory-safe") { beforeSwapDelta := or(shl(128, deltaSpecified), and(sub(shl(128, 1), 1), deltaUnspecified)) } } /// @notice Library for getting the specified and unspecified deltas from the BeforeSwapDelta type library BeforeSwapDeltaLibrary { /// @notice A BeforeSwapDelta of 0 BeforeSwapDelta public constant ZERO_DELTA = BeforeSwapDelta.wrap(0); /// extracts int128 from the upper 128 bits of the BeforeSwapDelta /// returned by beforeSwap function getSpecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaSpecified) { assembly ("memory-safe") { deltaSpecified := sar(128, delta) } } /// extracts int128 from the lower 128 bits of the BeforeSwapDelta /// returned by beforeSwap and afterSwap function getUnspecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaUnspecified) { assembly ("memory-safe") { deltaUnspecified := signextend(15, delta) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IERC20Minimal} from '../interfaces/external/IERC20Minimal.sol'; import {CustomRevert} from '../libraries/CustomRevert.sol'; type Currency is address; using {greaterThan as >, lessThan as <, greaterThanOrEqualTo as >=, equals as ==} for Currency global; using CurrencyLibrary for Currency global; function equals(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) == Currency.unwrap(other); } function greaterThan(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) > Currency.unwrap(other); } function lessThan(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) < Currency.unwrap(other); } function greaterThanOrEqualTo(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) >= Currency.unwrap(other); } /// @title CurrencyLibrary /// @dev This library allows for transferring and holding native tokens and ERC20 tokens library CurrencyLibrary { /// @notice Additional context for ERC-7751 wrapped error when a native transfer fails error NativeTransferFailed(); /// @notice Additional context for ERC-7751 wrapped error when an ERC20 transfer fails error ERC20TransferFailed(); /// @notice A constant to represent the native currency Currency public constant ADDRESS_ZERO = Currency.wrap(address(0)); function transfer(Currency currency, address to, uint256 amount) internal { // altered from https://github.com/transmissions11/solmate/blob/44a9963d4c78111f77caa0e65d677b8b46d6f2e6/src/utils/SafeTransferLib.sol // modified custom error selectors bool success; if (currency.isAddressZero()) { assembly ("memory-safe") { // Transfer the ETH and revert if it fails. success := call(gas(), to, amount, 0, 0, 0, 0) } // revert with NativeTransferFailed, containing the bubbled up error as an argument if (!success) { CustomRevert.bubbleUpAndRevertWith(to, bytes4(0), NativeTransferFailed.selector); } } else { assembly ("memory-safe") { // Get a pointer to some free memory. let fmp := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(fmp, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(fmp, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(fmp, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), currency, 0, fmp, 68, 0, 32) ) // Now clean the memory we used mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were stored here mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored here } // revert with ERC20TransferFailed, containing the bubbled up error as an argument if (!success) { CustomRevert.bubbleUpAndRevertWith( Currency.unwrap(currency), IERC20Minimal.transfer.selector, ERC20TransferFailed.selector ); } } } function balanceOfSelf(Currency currency) internal view returns (uint256) { if (currency.isAddressZero()) { return address(this).balance; } else { return IERC20Minimal(Currency.unwrap(currency)).balanceOf(address(this)); } } function balanceOf(Currency currency, address owner) internal view returns (uint256) { if (currency.isAddressZero()) { return owner.balance; } else { return IERC20Minimal(Currency.unwrap(currency)).balanceOf(owner); } } function isAddressZero(Currency currency) internal pure returns (bool) { return Currency.unwrap(currency) == Currency.unwrap(ADDRESS_ZERO); } function toId(Currency currency) internal pure returns (uint256) { return uint160(Currency.unwrap(currency)); } // If the upper 12 bytes are non-zero, they will be zero-ed out // Therefore, fromId() and toId() are not inverses of each other function fromId(uint256 id) internal pure returns (Currency) { return Currency.wrap(address(uint160(id))); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {PoolKey} from './PoolKey.sol'; type PoolId is bytes32; /// @notice Library for computing the ID of a pool library PoolIdLibrary { /// @notice Returns value equal to keccak256(abi.encode(poolKey)) function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) { assembly ("memory-safe") { // 0xa0 represents the total size of the poolKey struct (5 slots of 32 bytes) poolId := keccak256(poolKey, 0xa0) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IHooks} from '../interfaces/IHooks.sol'; import {Currency} from './Currency.sol'; import {PoolIdLibrary} from './PoolId.sol'; using PoolIdLibrary for PoolKey global; /// @notice Returns the key for identifying a pool struct PoolKey { /// @notice The lower currency of the pool, sorted numerically Currency currency0; /// @notice The higher currency of the pool, sorted numerically Currency currency1; /// @notice The pool LP fee, capped at 1_000_000. If the highest bit is 1, the pool has a dynamic fee and must be exactly equal to 0x800000 uint24 fee; /// @notice Ticks that involve positions must be a multiple of tick spacing int24 tickSpacing; /// @notice The hooks of the pool IHooks hooks; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /// @title IEIP712_v4 /// @notice Interface for the EIP712 contract interface IEIP712_v4 { /// @notice Returns the domain separator for the current chain. /// @return bytes32 The domain separator function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /// @title IERC721Permit_v4 /// @notice Interface for the ERC721Permit_v4 contract interface IERC721Permit_v4 { error SignatureDeadlineExpired(); error NoSelfPermit(); error Unauthorized(); /// @notice Approve of a specific token ID for spending by spender via signature /// @param spender The account that is being approved /// @param tokenId The ID of the token that is being approved for spending /// @param deadline The deadline timestamp by which the call must be mined for the approve to work /// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word /// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v) /// @dev payable so it can be multicalled with NATIVE related actions function permit(address spender, uint256 tokenId, uint256 deadline, uint256 nonce, bytes calldata signature) external payable; /// @notice Set an operator with full permission to an owner's tokens via signature /// @param owner The address that is setting the operator /// @param operator The address that will be set as an operator for the owner /// @param approved The permission to set on the operator /// @param deadline The deadline timestamp by which the call must be mined for the approve to work /// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word /// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v) /// @dev payable so it can be multicalled with NATIVE related actions function permitForAll( address owner, address operator, bool approved, uint256 deadline, uint256 nonce, bytes calldata signature ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IPoolManager} from '../../v4-core/interfaces/IPoolManager.sol'; /// @title IImmutableState /// @notice Interface for the ImmutableState contract interface IImmutableState { /// @notice The Uniswap v4 PoolManager contract function poolManager() external view returns (IPoolManager); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /// @title IMulticall_v4 /// @notice Interface for the Multicall_v4 contract interface IMulticall_v4 { /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` is passed onto all subcalls, even if a previous subcall has consumed the ether. /// Subcalls can instead use `address(this).value` to see the available ETH, and consume it using {value: x}. /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {ISubscriber} from './ISubscriber.sol'; /// @title INotifier /// @notice Interface for the Notifier contract interface INotifier { /// @notice Thrown when unsubscribing without a subscriber error NotSubscribed(); /// @notice Thrown when a subscriber does not have code error NoCodeSubscriber(); /// @notice Thrown when a user specifies a gas limit too low to avoid valid unsubscribe notifications error GasLimitTooLow(); /// @notice Wraps the revert message of the subscriber contract on a reverting subscription error SubscriptionReverted(address subscriber, bytes reason); /// @notice Wraps the revert message of the subscriber contract on a reverting modify liquidity notification error ModifyLiquidityNotificationReverted(address subscriber, bytes reason); /// @notice Wraps the revert message of the subscriber contract on a reverting burn notification error BurnNotificationReverted(address subscriber, bytes reason); /// @notice Thrown when a tokenId already has a subscriber error AlreadySubscribed(uint256 tokenId, address subscriber); /// @notice Emitted on a successful call to subscribe event Subscription(uint256 indexed tokenId, address indexed subscriber); /// @notice Emitted on a successful call to unsubscribe event Unsubscription(uint256 indexed tokenId, address indexed subscriber); /// @notice Returns the subscriber for a respective position /// @param tokenId the ERC721 tokenId /// @return subscriber the subscriber contract function subscriber(uint256 tokenId) external view returns (ISubscriber subscriber); /// @notice Enables the subscriber to receive notifications for a respective position /// @param tokenId the ERC721 tokenId /// @param newSubscriber the address of the subscriber contract /// @param data caller-provided data that's forwarded to the subscriber contract /// @dev Calling subscribe when a position is already subscribed will revert /// @dev payable so it can be multicalled with NATIVE related actions /// @dev will revert if pool manager is locked function subscribe(uint256 tokenId, address newSubscriber, bytes calldata data) external payable; /// @notice Removes the subscriber from receiving notifications for a respective position /// @param tokenId the ERC721 tokenId /// @dev Callers must specify a high gas limit (remaining gas should be higher than unsubscriberGasLimit) such that the subscriber can be notified /// @dev payable so it can be multicalled with NATIVE related actions /// @dev Must always allow a user to unsubscribe. In the case of a malicious subscriber, a user can always unsubscribe safely, ensuring liquidity is always modifiable. /// @dev will revert if pool manager is locked function unsubscribe(uint256 tokenId) external payable; /// @notice Returns and determines the maximum allowable gas-used for notifying unsubscribe /// @return uint256 the maximum gas limit when notifying a subscriber's `notifyUnsubscribe` function function unsubscribeGasLimit() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IAllowanceTransfer} from '../../permit2/interfaces/IAllowanceTransfer.sol'; /// @title IPermit2Forwarder /// @notice Interface for the Permit2Forwarder contract interface IPermit2Forwarder { /// @notice allows forwarding a single permit to permit2 /// @dev this function is payable to allow multicall with NATIVE based actions /// @param owner the owner of the tokens /// @param permitSingle the permit data /// @param signature the signature of the permit; abi.encodePacked(r, s, v) /// @return err the error returned by a reverting permit call, empty if successful function permit(address owner, IAllowanceTransfer.PermitSingle calldata permitSingle, bytes calldata signature) external payable returns (bytes memory err); /// @notice allows forwarding batch permits to permit2 /// @dev this function is payable to allow multicall with NATIVE based actions /// @param owner the owner of the tokens /// @param _permitBatch a batch of approvals /// @param signature the signature of the permit; abi.encodePacked(r, s, v) /// @return err the error returned by a reverting permit call, empty if successful function permitBatch(address owner, IAllowanceTransfer.PermitBatch calldata _permitBatch, bytes calldata signature) external payable returns (bytes memory err); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {PoolKey} from '../../v4-core/types/PoolKey.sol'; /// @title IPoolInitializer_v4 /// @notice Interface for the PoolInitializer_v4 contract interface IPoolInitializer_v4 { /// @notice Initialize a Uniswap v4 Pool /// @dev If the pool is already initialized, this function will not revert and just return type(int24).max /// @param key The PoolKey of the pool to initialize /// @param sqrtPriceX96 The initial starting price of the pool, expressed as a sqrtPriceX96 /// @return The current tick of the pool, or type(int24).max if the pool creation failed, or the pool already existed function initializePool(PoolKey calldata key, uint160 sqrtPriceX96) external payable returns (int24); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {IPoolManager} from '../../v4-core/interfaces/IPoolManager.sol'; import {IPositionManager} from './IPositionManager.sol'; /// @title IPositionDescriptor /// @notice Interface for the PositionDescriptor contract interface IPositionDescriptor { error InvalidTokenId(uint256 tokenId); /// @notice Produces the URI describing a particular token ID /// @dev Note this URI may be a data: URI with the JSON contents directly inlined /// @param positionManager The position manager for which to describe the token /// @param tokenId The ID of the token for which to produce a description, which may not be valid /// @return The URI of the ERC721-compliant metadata function tokenURI(IPositionManager positionManager, uint256 tokenId) external view returns (string memory); /// @notice Returns true if currency0 has higher priority than currency1 /// @param currency0 The first currency address /// @param currency1 The second currency address /// @return True if currency0 has higher priority than currency1 function flipRatio(address currency0, address currency1) external view returns (bool); /// @notice Returns the priority of a currency. /// For certain currencies on mainnet, the smaller the currency, the higher the priority /// And those with the higher priority values (more positive values) will be in the numerator of the price ratio /// @param currency The currency address /// @return The priority of the currency function currencyRatioPriority(address currency) external view returns (int256); /// @return The wrapped native token for this descriptor function wrappedNative() external view returns (address); /// @return The native currency label for this descriptor function nativeCurrencyLabel() external view returns (string memory); /// @return The pool manager for this descriptor function poolManager() external view returns (IPoolManager); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {PoolKey} from '../../v4-core/types/PoolKey.sol'; import {PositionInfo} from '../libraries/PositionInfoLibrary.sol'; import {IEIP712_v4} from './IEIP712_v4.sol'; import {IERC721Permit_v4} from './IERC721Permit_v4.sol'; import {IImmutableState} from './IImmutableState.sol'; import {IMulticall_v4} from './IMulticall_v4.sol'; import {INotifier} from './INotifier.sol'; import {IPermit2Forwarder} from './IPermit2Forwarder.sol'; import {IPoolInitializer_v4} from './IPoolInitializer_v4.sol'; import {IUnorderedNonce} from './IUnorderedNonce.sol'; /// @title IPositionManager /// @notice Interface for the PositionManager contract interface IPositionManager is INotifier, IImmutableState, IERC721Permit_v4, IEIP712_v4, IMulticall_v4, IPoolInitializer_v4, IUnorderedNonce, IPermit2Forwarder { /// @notice Thrown when the caller is not approved to modify a position error NotApproved(address caller); /// @notice Thrown when the block.timestamp exceeds the user-provided deadline error DeadlinePassed(uint256 deadline); /// @notice Thrown when calling transfer, subscribe, or unsubscribe when the PoolManager is unlocked. /// @dev This is to prevent hooks from being able to trigger notifications at the same time the position is being modified. error PoolManagerMustBeLocked(); /// @notice Unlocks Uniswap v4 PoolManager and batches actions for modifying liquidity /// @dev This is the standard entrypoint for the PositionManager /// @param unlockData is an encoding of actions, and parameters for those actions /// @param deadline is the deadline for the batched actions to be executed function modifyLiquidities(bytes calldata unlockData, uint256 deadline) external payable; /// @notice Batches actions for modifying liquidity without unlocking v4 PoolManager /// @dev This must be called by a contract that has already unlocked the v4 PoolManager /// @param actions the actions to perform /// @param params the parameters to provide for the actions function modifyLiquiditiesWithoutUnlock(bytes calldata actions, bytes[] calldata params) external payable; /// @notice Used to get the ID that will be used for the next minted liquidity position /// @return uint256 The next token ID function nextTokenId() external view returns (uint256); /// @notice Returns the liquidity of a position /// @param tokenId the ERC721 tokenId /// @return liquidity the position's liquidity, as a liquidityAmount /// @dev this value can be processed as an amount0 and amount1 by using the LiquidityAmounts library function getPositionLiquidity(uint256 tokenId) external view returns (uint128 liquidity); /// @notice Returns the pool key and position info of a position /// @param tokenId the ERC721 tokenId /// @return poolKey the pool key of the position /// @return PositionInfo a uint256 packed value holding information about the position including the range (tickLower, tickUpper) function getPoolAndPositionInfo(uint256 tokenId) external view returns (PoolKey memory, PositionInfo); /// @notice Returns the position info of a position /// @param tokenId the ERC721 tokenId /// @return a uint256 packed value holding information about the position including the range (tickLower, tickUpper) function positionInfo(uint256 tokenId) external view returns (PositionInfo); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {BalanceDelta} from '../../v4-core/types/BalanceDelta.sol'; import {PositionInfo} from '../libraries/PositionInfoLibrary.sol'; /// @title ISubscriber /// @notice Interface that a Subscriber contract should implement to receive updates from the v4 position manager interface ISubscriber { /// @notice Called when a position subscribes to this subscriber contract /// @param tokenId the token ID of the position /// @param data additional data passed in by the caller function notifySubscribe(uint256 tokenId, bytes memory data) external; /// @notice Called when a position unsubscribes from the subscriber /// @dev This call's gas is capped at `unsubscribeGasLimit` (set at deployment) /// @dev Because of EIP-150, solidity may only allocate 63/64 of gasleft() /// @param tokenId the token ID of the position function notifyUnsubscribe(uint256 tokenId) external; /// @notice Called when a position is burned /// @param tokenId the token ID of the position /// @param owner the current owner of the tokenId /// @param info information about the position /// @param liquidity the amount of liquidity decreased in the position, may be 0 /// @param feesAccrued the fees accrued by the position if liquidity was decreased function notifyBurn(uint256 tokenId, address owner, PositionInfo info, uint256 liquidity, BalanceDelta feesAccrued) external; /// @notice Called when a position modifies its liquidity or collects fees /// @param tokenId the token ID of the position /// @param liquidityChange the change in liquidity on the underlying position /// @param feesAccrued the fees to be collected from the position as a result of the modifyLiquidity call /// @dev Note that feesAccrued can be artificially inflated by a malicious user /// Pools with a single liquidity position can inflate feeGrowthGlobal (and consequently feesAccrued) by donating to themselves; /// atomically donating and collecting fees within the same unlockCallback may further inflate feeGrowthGlobal/feesAccrued function notifyModifyLiquidity(uint256 tokenId, int256 liquidityChange, BalanceDelta feesAccrued) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; /// @title IUnorderedNonce /// @notice Interface for the UnorderedNonce contract interface IUnorderedNonce { error NonceAlreadyUsed(); /// @notice mapping of nonces consumed by each address, where a nonce is a single bit on the 256-bit bitmap /// @dev word is at most type(uint248).max function nonces(address owner, uint256 word) external view returns (uint256); /// @notice Revoke a nonce by spending it, preventing it from being used again /// @dev Used in cases where a valid nonce has not been broadcasted onchain, and the owner wants to revoke the validity of the nonce /// @dev payable so it can be multicalled with native-token related actions function revokeNonce(uint256 nonce) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2; import {Currency} from '../../v4-core/types/Currency.sol'; import {PoolKey} from '../../v4-core/types/PoolKey.sol'; import {PathKey} from '../libraries/PathKey.sol'; import {IImmutableState} from './IImmutableState.sol'; /// @title IV4Quoter /// @notice Interface for the V4Quoter contract interface IV4Quoter is IImmutableState { struct QuoteExactSingleParams { PoolKey poolKey; bool zeroForOne; uint128 exactAmount; bytes hookData; } struct QuoteExactParams { Currency exactCurrency; PathKey[] path; uint128 exactAmount; } /// @notice Returns the delta amounts for a given exact input swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactSingleParams` /// poolKey The key for identifying a V4 pool /// zeroForOne If the swap is from currency0 to currency1 /// exactAmount The desired input amount /// hookData arbitrary hookData to pass into the associated hooks /// @return amountOut The output quote for the exactIn swap /// @return gasEstimate Estimated gas units used for the swap function quoteExactInputSingle(QuoteExactSingleParams memory params) external returns (uint256 amountOut, uint256 gasEstimate); /// @notice Returns the delta amounts along the swap path for a given exact input swap /// @param params the params for the quote, encoded as 'QuoteExactParams' /// currencyIn The input currency of the swap /// path The path of the swap encoded as PathKeys that contains currency, fee, tickSpacing, and hook info /// exactAmount The desired input amount /// @return amountOut The output quote for the exactIn swap /// @return gasEstimate Estimated gas units used for the swap function quoteExactInput(QuoteExactParams memory params) external returns (uint256 amountOut, uint256 gasEstimate); /// @notice Returns the delta amounts for a given exact output swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactSingleParams` /// poolKey The key for identifying a V4 pool /// zeroForOne If the swap is from currency0 to currency1 /// exactAmount The desired output amount /// hookData arbitrary hookData to pass into the associated hooks /// @return amountIn The input quote for the exactOut swap /// @return gasEstimate Estimated gas units used for the swap function quoteExactOutputSingle(QuoteExactSingleParams memory params) external returns (uint256 amountIn, uint256 gasEstimate); /// @notice Returns the delta amounts along the swap path for a given exact output swap /// @param params the params for the quote, encoded as 'QuoteExactParams' /// currencyOut The output currency of the swap /// path The path of the swap encoded as PathKeys that contains currency, fee, tickSpacing, and hook info /// exactAmount The desired output amount /// @return amountIn The input quote for the exactOut swap /// @return gasEstimate Estimated gas units used for the swap function quoteExactOutput(QuoteExactParams memory params) external returns (uint256 amountIn, uint256 gasEstimate); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IHooks} from '../../v4-core/interfaces/IHooks.sol'; import {Currency} from '../../v4-core/types/Currency.sol'; import {PoolKey} from '../../v4-core/types/PoolKey.sol'; struct PathKey { Currency intermediateCurrency; uint24 fee; int24 tickSpacing; IHooks hooks; bytes hookData; } using PathKeyLibrary for PathKey global; /// @title PathKey Library /// @notice Functions for working with PathKeys library PathKeyLibrary { /// @notice Get the pool and swap direction for a given PathKey /// @param params the given PathKey /// @param currencyIn the input currency /// @return poolKey the pool key of the swap /// @return zeroForOne the direction of the swap, true if currency0 is being swapped for currency1 function getPoolAndSwapDirection(PathKey calldata params, Currency currencyIn) internal pure returns (PoolKey memory poolKey, bool zeroForOne) { Currency currencyOut = params.intermediateCurrency; (Currency currency0, Currency currency1) = currencyIn < currencyOut ? (currencyIn, currencyOut) : (currencyOut, currencyIn); zeroForOne = currencyIn == currency0; poolKey = PoolKey(currency0, currency1, params.fee, params.tickSpacing, params.hooks); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {PoolId} from '../../v4-core/types/PoolId.sol'; import {PoolKey} from '../../v4-core/types/PoolKey.sol'; /** * @dev PositionInfo is a packed version of solidity structure. * Using the packaged version saves gas and memory by not storing the structure fields in memory slots. * * Layout: * 200 bits poolId | 24 bits tickUpper | 24 bits tickLower | 8 bits hasSubscriber * * Fields in the direction from the least significant bit: * * A flag to know if the tokenId is subscribed to an address * uint8 hasSubscriber; * * The tickUpper of the position * int24 tickUpper; * * The tickLower of the position * int24 tickLower; * * The truncated poolId. Truncates a bytes32 value so the most signifcant (highest) 200 bits are used. * bytes25 poolId; * * Note: If more bits are needed, hasSubscriber can be a single bit. * */ type PositionInfo is uint256; using PositionInfoLibrary for PositionInfo global; library PositionInfoLibrary { PositionInfo internal constant EMPTY_POSITION_INFO = PositionInfo.wrap(0); uint256 internal constant MASK_UPPER_200_BITS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000; uint256 internal constant MASK_8_BITS = 0xFF; uint24 internal constant MASK_24_BITS = 0xFFFFFF; uint256 internal constant SET_UNSUBSCRIBE = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00; uint256 internal constant SET_SUBSCRIBE = 0x01; uint8 internal constant TICK_LOWER_OFFSET = 8; uint8 internal constant TICK_UPPER_OFFSET = 32; /// @dev This poolId is NOT compatible with the poolId used in UniswapV4 core. It is truncated to 25 bytes, and just used to lookup PoolKey in the poolKeys mapping. function poolId(PositionInfo info) internal pure returns (bytes25 _poolId) { assembly ("memory-safe") { _poolId := and(MASK_UPPER_200_BITS, info) } } function tickLower(PositionInfo info) internal pure returns (int24 _tickLower) { assembly ("memory-safe") { _tickLower := signextend(2, shr(TICK_LOWER_OFFSET, info)) } } function tickUpper(PositionInfo info) internal pure returns (int24 _tickUpper) { assembly ("memory-safe") { _tickUpper := signextend(2, shr(TICK_UPPER_OFFSET, info)) } } function hasSubscriber(PositionInfo info) internal pure returns (bool _hasSubscriber) { assembly ("memory-safe") { _hasSubscriber := and(MASK_8_BITS, info) } } /// @dev this does not actually set any storage function setSubscribe(PositionInfo info) internal pure returns (PositionInfo _info) { assembly ("memory-safe") { _info := or(info, SET_SUBSCRIBE) } } /// @dev this does not actually set any storage function setUnsubscribe(PositionInfo info) internal pure returns (PositionInfo _info) { assembly ("memory-safe") { _info := and(info, SET_UNSUBSCRIBE) } } /// @notice Creates the default PositionInfo struct /// @dev Called when minting a new position /// @param _poolKey the pool key of the position /// @param _tickLower the lower tick of the position /// @param _tickUpper the upper tick of the position /// @return info packed position info, with the truncated poolId and the hasSubscriber flag set to false function initialize(PoolKey memory _poolKey, int24 _tickLower, int24 _tickUpper) internal pure returns (PositionInfo info) { bytes25 _poolId = bytes25(PoolId.unwrap(_poolKey.toId())); assembly { info := or( or(and(MASK_UPPER_200_BITS, _poolId), shl(TICK_UPPER_OFFSET, and(MASK_24_BITS, _tickUpper))), shl(TICK_LOWER_OFFSET, and(MASK_24_BITS, _tickLower)) ) } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.2; pragma abicoder v2; /// @title QuoterV2 Interface /// @notice Supports quoting the calculated amounts from exact input or exact output swaps. /// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap. /// @dev These functions are not marked view because they rely on calling non-view functions and reverting /// to compute the result. They are also not gas efficient and should not be called on-chain. interface IQuoter { /// @notice Returns the amount out received for a given exact input swap without executing the swap /// @param path The path of the swap, i.e. each token pair and the pool fee /// @param amountIn The amount of the first token to swap /// @return amountOut The amount of the last token that would be received /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path /// @return initializedTicksCrossedList List of number of initialized ticks loaded function quoteExactInput(bytes memory path, uint256 amountIn) external view returns ( uint256 amountOut, uint160[] memory sqrtPriceX96AfterList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate ); struct QuoteExactInputSingleWithPoolParams { address tokenIn; address tokenOut; uint256 amountIn; address pool; uint24 fee; uint160 sqrtPriceLimitX96; } /// @notice Returns the amount out received for a given exact input but for a swap of a single pool /// @param params The params for the quote, encoded as `quoteExactInputSingleWithPool` /// tokenIn The token being swapped in /// amountIn The desired input amount /// tokenOut The token being swapped out /// fee The fee of the pool to consider for the pair /// pool The address of the pool to consider for the pair /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap /// @return amountOut The amount of `tokenOut` that would be received /// @return sqrtPriceX96After The sqrt price of the pool after the swap /// @return initializedTicksCrossed The number of initialized ticks loaded function quoteExactInputSingleWithPool(QuoteExactInputSingleWithPoolParams memory params) external view returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate); struct QuoteExactInputSingleParams { address tokenIn; address tokenOut; uint256 amountIn; uint24 fee; uint160 sqrtPriceLimitX96; } /// @notice Returns the amount out received for a given exact input but for a swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactInputSingleParams` /// tokenIn The token being swapped in /// amountIn The desired input amount /// tokenOut The token being swapped out /// fee The fee of the token pool to consider for the pair /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap /// @return amountOut The amount of `tokenOut` that would be received /// @return sqrtPriceX96After The sqrt price of the pool after the swap /// @return initializedTicksCrossed The number of initialized ticks loaded function quoteExactInputSingle(QuoteExactInputSingleParams memory params) external view returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate); struct QuoteExactOutputSingleWithPoolParams { address tokenIn; address tokenOut; uint256 amount; uint24 fee; address pool; uint160 sqrtPriceLimitX96; } /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactOutputSingleWithPoolParams` /// tokenIn The token being swapped in /// tokenOut The token being swapped out /// amount The desired output amount /// fee The fee of the token pool to consider for the pair /// pool The address of the pool to consider for the pair /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap /// @return amountIn The amount required as the input for the swap in order to receive `amountOut` /// @return sqrtPriceX96After The sqrt price of the pool after the swap /// @return initializedTicksCrossed The number of initialized ticks loaded function quoteExactOutputSingleWithPool(QuoteExactOutputSingleWithPoolParams memory params) external view returns (uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate); struct QuoteExactOutputSingleParams { address tokenIn; address tokenOut; uint256 amount; uint24 fee; uint160 sqrtPriceLimitX96; } /// @notice Returns the amount in required to receive the given exact output amount but for a swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactOutputSingleParams` /// tokenIn The token being swapped in /// tokenOut The token being swapped out /// amountOut The desired output amount /// fee The fee of the token pool to consider for the pair /// sqrtPriceLimitX96 The price limit of the pool that cannot be exceeded by the swap /// @return amountIn The amount required as the input for the swap in order to receive `amountOut` /// @return sqrtPriceX96After The sqrt price of the pool after the swap /// @return initializedTicksCrossed The number of initialized ticks loaded function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params) external view returns (uint256 amountIn, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate); /// @notice Returns the amount in required for a given exact output swap without executing the swap /// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order /// @param amountOut The amount of the last token to receive /// @return amountIn The amount of first token required to be paid /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path function quoteExactOutput(bytes memory path, uint256 amountOut) external view returns ( uint256 amountIn, uint160[] memory sqrtPriceX96AfterList, uint32[] memory initializedTicksCrossedList, uint256 gasEstimate ); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IArbSys} from "../interfaces/IArbSys.sol"; /// @title BlockNumberish /// A helper contract to get the current block number on different chains /// inspired by https://github.com/ProjectOpenSea/tstorish/blob/main/src/Tstorish.sol contract BlockNumberish { // Declare an immutable function type variable for the _getBlockNumberish function function() view returns (uint256) internal immutable _getBlockNumberish; uint256 private constant ARB_CHAIN_ID = 42161; address private constant ARB_SYS_ADDRESS = 0x0000000000000000000000000000000000000064; constructor() { // Set the function to use based on chainid if (block.chainid == ARB_CHAIN_ID) { _getBlockNumberish = _getBlockNumberSyscall; } else { _getBlockNumberish = _getBlockNumber; } } /// @dev Private function to get the block number on arbitrum function _getBlockNumberSyscall() private view returns (uint256) { return IArbSys(ARB_SYS_ADDRESS).arbBlockNumber(); } /// @dev Private function to get the block number using the opcode function _getBlockNumber() private view returns (uint256) { return block.number; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; /// @notice standardized events that should be emitted by all reactors /// @dev collated into one library to help with forge expectEmit integration /// @dev and for reactors which dont use base interface ReactorEvents { /// @notice emitted when an order is filled /// @param orderHash The hash of the order that was filled /// @param filler The address which executed the fill /// @param swapper The swapper of the filled order /// @param nonce The nonce of the filled order event Fill(bytes32 indexed orderHash, address indexed filler, address indexed swapper, uint256 nonce); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {IReactor} from "../interfaces/IReactor.sol"; import {IValidationCallback} from "../interfaces/IValidationCallback.sol"; import {ERC20} from "solmate/src/tokens/ERC20.sol"; /// @dev generic order information /// should be included as the first field in any concrete order types struct OrderInfo { // The address of the reactor that this order is targeting // Note that this must be included in every order so the swapper // signature commits to the specific reactor that they trust to fill their order properly IReactor reactor; // The address of the user which created the order // Note that this must be included so that order hashes are unique by swapper address swapper; // The nonce of the order, allowing for signature replay protection and cancellation uint256 nonce; // The timestamp after which this order is no longer valid uint256 deadline; // Custom validation contract IValidationCallback additionalValidationContract; // Encoded validation params for additionalValidationContract bytes additionalValidationData; } /// @dev tokens that need to be sent from the swapper in order to satisfy an order struct InputToken { ERC20 token; uint256 amount; // Needed for dutch decaying inputs uint256 maxAmount; } /// @dev tokens that need to be received by the recipient in order to satisfy an order struct OutputToken { address token; uint256 amount; address recipient; } /// @dev generic concrete order that specifies exact tokens which need to be sent and received struct ResolvedOrder { OrderInfo info; InputToken input; OutputToken[] outputs; bytes sig; bytes32 hash; } /// @dev external struct including a generic encoded order and swapper signature /// The order bytes will be parsed and mapped to a ResolvedOrder in the concrete reactor contract struct SignedOrder { bytes order; bytes sig; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } struct ExactInputParams { bytes path; address recipient; uint256 amountIn; uint256 amountOutMinimum; } interface ISwapRouter02 { function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); function multicall(uint256 deadline, bytes[] calldata data) external payable returns (bytes[] memory results); function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to) external payable returns (uint256 amountOut); function unwrapWETH9(uint256 amountMinimum) external payable; function WETH9() external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; /** * @notice Minimal interface for interacting with Arbitrum system contracts */ interface IArbSys { /** * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0) * @return block number as int */ function arbBlockNumber() external view returns (uint256); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {ResolvedOrder, OutputToken} from "../base/ReactorStructs.sol"; /// @notice Interface for getting fee outputs interface IProtocolFeeController { /// @notice Get fee outputs for the given orders /// @param order The orders to get fee outputs for /// @return List of fee outputs to append for each provided order function getFeeOutputs(ResolvedOrder memory order) external view returns (OutputToken[] memory); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {SignedOrder} from "../base/ReactorStructs.sol"; /// @notice Interface for order execution reactors interface IReactor { /// @notice Execute a single order /// @param order The order definition and valid signature to execute function execute(SignedOrder calldata order) external payable; /// @notice Execute a single order using the given callback data /// @param order The order definition and valid signature to execute /// @param callbackData The callbackData to pass to the callback function executeWithCallback(SignedOrder calldata order, bytes calldata callbackData) external payable; /// @notice Execute the given orders at once /// @param orders The order definitions and valid signatures to execute function executeBatch(SignedOrder[] calldata orders) external payable; /// @notice Execute the given orders at once using a callback with the given callback data /// @param orders The order definitions and valid signatures to execute /// @param callbackData The callbackData to pass to the callback function executeBatchWithCallback(SignedOrder[] calldata orders, bytes calldata callbackData) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {ResolvedOrder} from "../base/ReactorStructs.sol"; /// @notice Callback for executing orders through a reactor. interface IReactorCallback { /// @notice Called by the reactor during the execution of an order /// @param resolvedOrders Has inputs and outputs /// @param callbackData The callbackData specified for an order execution /// @dev Must have approved each token and amount in outputs to the msg.sender function reactorCallback(ResolvedOrder[] memory resolvedOrders, bytes memory callbackData) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {ResolvedOrder} from "../base/ReactorStructs.sol"; /// @notice Callback to validate an order interface IValidationCallback { /// @notice Called by the reactor for custom validation of an order. Will revert if validation fails /// @param filler The filler of the order /// @param resolvedOrder The resolved order to fill function validate(address filler, ResolvedOrder calldata resolvedOrder) external view; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {IReactorCallback} from "../interfaces/IReactorCallback.sol"; import {IReactor} from "../interfaces/IReactor.sol"; import {ResolvedOrder, SignedOrder} from "../base/ReactorStructs.sol"; /// @notice Quoter contract for orders /// @dev note this is meant to be used as an off-chain lens contract to pre-validate generic orders contract OrderQuoter is IReactorCallback { /// @notice thrown if reactorCallback receives more than one order error OrdersLengthIncorrect(); /// @notice offset bytes into the order object to the head of the order info struct uint256 private constant ORDER_INFO_OFFSET = 64; /// @notice minimum length of a resolved order object in bytes uint256 private constant RESOLVED_ORDER_MIN_LENGTH = 192; /// @notice Quote the given order, returning the ResolvedOrder object which defines /// the current input and output token amounts required to satisfy it /// Also bubbles up any reverts that would occur during the processing of the order /// @param order abi-encoded order, including `reactor` as the first encoded struct member /// @param sig The order signature /// @return result The ResolvedOrder function quote(bytes memory order, bytes memory sig) external returns (ResolvedOrder memory result) { try IReactor(getReactor(order)).executeWithCallback(SignedOrder(order, sig), bytes("")) {} catch (bytes memory reason) { result = parseRevertReason(reason); } } /// @notice Return the reactor of a given order (abi.encoded bytes). /// @param order abi-encoded order, including `reactor` as the first encoded struct member /// @return reactor function getReactor(bytes memory order) public pure returns (IReactor reactor) { assembly { let orderInfoOffsetPointer := add(order, ORDER_INFO_OFFSET) reactor := mload(add(orderInfoOffsetPointer, mload(orderInfoOffsetPointer))) } } /// @notice Return the order info of a given order (abi-encoded bytes). /// @param reason The revert reason /// @return abi-encoded order, including `reactor` as the first encoded struct member function parseRevertReason(bytes memory reason) private pure returns (ResolvedOrder memory) { if (reason.length < RESOLVED_ORDER_MIN_LENGTH) { assembly { revert(add(32, reason), mload(reason)) } } else { return abi.decode(reason, (ResolvedOrder)); } } /// @notice Reactor callback function /// @dev reverts with the resolved order as reason /// @param resolvedOrders The resolved orders function reactorCallback(ResolvedOrder[] memory resolvedOrders, bytes memory) external pure { if (resolvedOrders.length != 1) { revert OrdersLengthIncorrect(); } bytes memory order = abi.encode(resolvedOrders[0]); assembly { revert(add(32, order), mload(order)) } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {IValidationCallback} from "../interfaces/IValidationCallback.sol"; import {ResolvedOrder} from "../base/ReactorStructs.sol"; /// @notice validation for orders that are exclusive to a single filler contract ExclusiveFillerValidation is IValidationCallback { /// @notice thrown if the filler does not have fill rights error NotExclusiveFiller(address filler); /// @notice verify that the filler exclusivity is satisfied /// @dev reverts if invalid filler given the exclusivity parameters /// @param filler The filler of the order /// @param resolvedOrder The order data to validate function validate(address filler, ResolvedOrder calldata resolvedOrder) external view { (address exclusiveFiller, uint256 lastExclusiveTimestamp) = abi.decode(resolvedOrder.info.additionalValidationData, (address, uint256)); if (lastExclusiveTimestamp >= block.timestamp && filler != exclusiveFiller) { revert NotExclusiveFiller(filler); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @dev An uint16 array of max 16 values packed into a single uint256 type Uint16Array is uint256; error IndexOutOfBounds(); error InvalidArrLength(); function toUint256(uint16[] memory inputArray) pure returns (uint256 uint16Array) { return Uint16Array.unwrap(toUint16Array(inputArray)); } function fromUnderlying(uint256 value) pure returns (Uint16Array) { return Uint16Array.wrap(value); } // Helper for creating a packed uint256 from a uint16 array function toUint16Array(uint16[] memory inputArray) pure returns (Uint16Array uint16Array) { if (inputArray.length > 16) { revert InvalidArrLength(); } uint256 packedData = 0; for (uint256 i = 0; i < inputArray.length; i++) { packedData |= uint256(inputArray[i]) << (i * 16); } uint16Array = Uint16Array.wrap(packedData); } library Uint16ArrayLibrary { // Retrieve the nth uint16 value from a packed uint256 function getElement(Uint16Array packedData, uint256 n) internal pure returns (uint16) { if (n >= 16) { revert IndexOutOfBounds(); } unchecked { uint256 shiftAmount = n * 16; uint16 result = uint16(Uint16Array.unwrap(packedData) >> shiftAmount); return result; } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; import {Owned} from "solmate/auth/Owned.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {IFeeCollector} from "./interfaces/IFeeCollector.sol"; import {IPermit2} from "./external/IPermit2.sol"; /// @notice The collector of protocol fees that will be used to swap and send to a fee recipient address. contract FeeCollector is Owned, IFeeCollector { using SafeTransferLib for ERC20; address public universalRouter; ERC20 public immutable feeToken; IPermit2 public immutable permit2; uint256 public constant MAX_APPROVAL_AMOUNT = type(uint256).max; uint160 public constant MAX_PERMIT2_APPROVAL_AMOUNT = type(uint160).max; uint48 public constant MAX_PERMIT2_DEADLINE = type(uint48).max; constructor(address _owner, address _universalRouter, address _permit2, address _feeToken) Owned(_owner) { universalRouter = _universalRouter; feeToken = ERC20(_feeToken); permit2 = IPermit2(_permit2); } /// @inheritdoc IFeeCollector function swapBalance(bytes calldata swapData, uint256 nativeValue) external onlyOwner { _execute(swapData, nativeValue); } /// @inheritdoc IFeeCollector function swapBalance(bytes calldata swapData, uint256 nativeValue, ERC20[] calldata tokensToApprove) external onlyOwner { unchecked { for (uint256 i = 0; i < tokensToApprove.length; i++) { tokensToApprove[i].safeApprove(address(permit2), MAX_APPROVAL_AMOUNT); permit2.approve( address(tokensToApprove[i]), universalRouter, MAX_PERMIT2_APPROVAL_AMOUNT, MAX_PERMIT2_DEADLINE ); } } _execute(swapData, nativeValue); } /// @notice Helper function to call UniversalRouter. /// @param swapData The bytes call data to be forwarded to UniversalRouter. /// @param nativeValue The amount of native currency to send to UniversalRouter. function _execute(bytes calldata swapData, uint256 nativeValue) internal { (bool success,) = universalRouter.call{value: nativeValue}(swapData); if (!success) revert UniversalRouterCallFailed(); } /// @inheritdoc IFeeCollector function revokeTokenApprovals(ERC20[] calldata tokensToRevoke) external onlyOwner { unchecked { for (uint256 i = 0; i < tokensToRevoke.length; i++) { tokensToRevoke[i].safeApprove(address(permit2), 0); } } } /// @inheritdoc IFeeCollector function revokePermit2Approvals(IPermit2.TokenSpenderPair[] calldata approvals) external onlyOwner { permit2.lockdown(approvals); } /// @inheritdoc IFeeCollector function withdrawFeeToken(address feeRecipient, uint256 amount) external onlyOwner { feeToken.safeTransfer(feeRecipient, amount); } /// @inheritdoc IFeeCollector function setUniversalRouter(address _universalRouter) external onlyOwner { emit UniversalRouterChanged(universalRouter, _universalRouter); universalRouter = _universalRouter; } receive() external payable {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IEIP712} from "./IEIP712.sol"; /// @title AllowanceTransfer /// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts /// @dev Requires user's token approval on the Permit2 contract interface IAllowanceTransfer is IEIP712 { /// @notice A token spender pair. struct TokenSpenderPair { // the token the spender is approved address token; // the spender address address spender; } /// @notice A mapping from owner address to token address to spender address to PackedAllowance struct, which contains details and conditions of the approval. /// @notice The mapping is indexed in the above order see: allowance[ownerAddress][tokenAddress][spenderAddress] /// @dev The packed slot holds the allowed amount, expiration at which the allowed amount is no longer valid, and current nonce thats updated on any signature based approvals. function allowance(address user, address token, address spender) external view returns (uint160 amount, uint48 expiration, uint48 nonce); /// @notice Approves the spender to use up to amount of the specified token up until the expiration /// @param token The token to approve /// @param spender The spender address to approve /// @param amount The approved amount of the token /// @param expiration The timestamp at which the approval is no longer valid /// @dev The packed allowance also holds a nonce, which will stay unchanged in approve /// @dev Setting amount to type(uint160).max sets an unlimited approval function approve(address token, address spender, uint160 amount, uint48 expiration) external; /// @notice Enables performing a "lockdown" of the sender's Permit2 identity /// by batch revoking approvals /// @param approvals Array of approvals to revoke. function lockdown(TokenSpenderPair[] calldata approvals) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IEIP712 { function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IAllowanceTransfer} from "./IAllowanceTransfer.sol"; /// @notice Permit2 handles signature-based transfers in SignatureTransfer and allowance-based transfers in AllowanceTransfer. /// @dev Users must approve Permit2 before calling any of the transfer functions. interface IPermit2 is IAllowanceTransfer { // IPermit2 unifies the two interfaces so users have maximal flexibility with their approval. }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.13; import {ERC20} from "solmate/tokens/ERC20.sol"; import {IPermit2} from "../external/IPermit2.sol"; /// @notice The collector of protocol fees that will be used to swap and send to a fee recipient address. interface IFeeCollector { /// @notice Error thrown when the call to UniversalRouter fails. error UniversalRouterCallFailed(); /// @notice Emitted when the UniversalRouter address is changed. /// @param oldUniversalRouter The old router address. /// @param newUniversalRouter The new router address. event UniversalRouterChanged(address oldUniversalRouter, address newUniversalRouter); /// @notice Swaps the contract balance. /// @param swapData The bytes call data to be forwarded to UniversalRouter. /// @param nativeValue The amount of native currency to send to UniversalRouter. function swapBalance(bytes calldata swapData, uint256 nativeValue) external; /// @notice Approves tokens for swapping and then swaps the contract balance. /// @param swapData The bytes call data to be forwarded to UniversalRouter. /// @param nativeValue The amount of native currency to send to UniversalRouter. /// @param tokensToApprove An array of ERC20 tokens to approve for spending. function swapBalance(bytes calldata swapData, uint256 nativeValue, ERC20[] calldata tokensToApprove) external; /// @notice Revokes approvals on tokens by setting their allowance to 0. /// @param tokensToRevoke The token to revoke the approval for. function revokeTokenApprovals(ERC20[] calldata tokensToRevoke) external; /// @notice Revokes the permit2 allowance of a spender by setting token allowances to 0. /// @param approvals The approvals to revoke. function revokePermit2Approvals(IPermit2.TokenSpenderPair[] calldata approvals) external; /// @notice Transfers the fee token balance from this contract to the fee recipient. /// @param feeRecipient The address to send the fee token balance to. /// @param amount The amount to withdraw. function withdrawFeeToken(address feeRecipient, uint256 amount) external; /// @notice Sets the address of the UniversalRouter contract. /// @param _universalRouter The address of the UniversalRouter contract. function setUniversalRouter(address _universalRouter) external; }
pragma solidity >=0.5.0; interface IERC20 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); }
pragma solidity >=0.5.0; interface IUniswapV2Callee { function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external; }
pragma solidity >=0.5.0; interface IUniswapV2ERC20 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; }
pragma solidity >=0.5.0; interface IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; }
pragma solidity >=0.5.0; interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; }
pragma solidity >=0.5.0; interface IERC20 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); }
pragma solidity >=0.5.0; interface IUniswapV2Migrator { function migrate(address token, uint amountTokenMin, uint amountETHMin, address to, uint deadline) external; }
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
pragma solidity >=0.5.0; interface IWETH { function deposit() external payable; function transfer(address to, uint value) external returns (bool); function withdraw(uint) external; }
pragma solidity >=0.5.0; interface IUniswapV1Exchange { function balanceOf(address owner) external view returns (uint); function transferFrom(address from, address to, uint value) external returns (bool); function removeLiquidity(uint, uint, uint, uint) external returns (uint, uint); function tokenToEthSwapInput(uint, uint, uint) external returns (uint); function ethToTokenSwapInput(uint, uint) external payable returns (uint); }
pragma solidity >=0.5.0; interface IUniswapV1Factory { function getExchange(address) external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Minimal ERC20 interface for Uniswap /// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3 interface IERC20Minimal { /// @notice Returns the balance of a token /// @param account The account for which to look up the number of tokens it has, i.e. its balance /// @return The number of tokens held by the account function balanceOf(address account) external view returns (uint256); /// @notice Transfers the amount of token from the `msg.sender` to the recipient /// @param recipient The account that will receive the amount transferred /// @param amount The number of tokens to send from the sender to the recipient /// @return Returns true for a successful transfer, false for an unsuccessful transfer function transfer(address recipient, uint256 amount) external returns (bool); /// @notice Returns the current allowance given to a spender by an owner /// @param owner The account of the token owner /// @param spender The account of the token spender /// @return The current allowance granted by `owner` to `spender` function allowance(address owner, address spender) external view returns (uint256); /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` /// @param spender The account which will be allowed to spend a given amount of the owners tokens /// @param amount The amount of tokens allowed to be used by `spender` /// @return Returns true for a successful approval, false for unsuccessful function approve(address spender, uint256 amount) external returns (bool); /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` /// @param sender The account from which the transfer will be initiated /// @param recipient The recipient of the transfer /// @param amount The amount of the transfer /// @return Returns true for a successful transfer, false for unsuccessful function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. /// @param from The account from which the tokens were sent, i.e. the balance decreased /// @param to The account to which the tokens were sent, i.e. the balance increased /// @param value The amount of tokens that were transferred event Transfer(address indexed from, address indexed to, uint256 value); /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. /// @param owner The account that approved spending of its tokens /// @param spender The account for which the spending allowance was modified /// @param value The new allowance from the owner to the spender event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title The interface for the Uniswap V3 Factory /// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees interface IUniswapV3Factory { /// @notice Emitted when the owner of the factory is changed /// @param oldOwner The owner before the owner was changed /// @param newOwner The owner after the owner was changed event OwnerChanged(address indexed oldOwner, address indexed newOwner); /// @notice Emitted when a pool is created /// @param token0 The first token of the pool by address sort order /// @param token1 The second token of the pool by address sort order /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @param tickSpacing The minimum number of ticks between initialized ticks /// @param pool The address of the created pool event PoolCreated( address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool ); /// @notice Emitted when a new fee amount is enabled for pool creation via the factory /// @param fee The enabled fee, denominated in hundredths of a bip /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing); /// @notice Returns the current owner of the factory /// @dev Can be changed by the current owner via setOwner /// @return The address of the factory owner function owner() external view returns (address); /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee /// @return The tick spacing function feeAmountTickSpacing(uint24 fee) external view returns (int24); /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order /// @param tokenA The contract address of either token0 or token1 /// @param tokenB The contract address of the other token /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @return pool The pool address function getPool( address tokenA, address tokenB, uint24 fee ) external view returns (address pool); /// @notice Creates a pool for the given two tokens and fee /// @param tokenA One of the two tokens in the desired pool /// @param tokenB The other of the two tokens in the desired pool /// @param fee The desired fee for the pool /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments /// are invalid. /// @return pool The address of the newly created pool function createPool( address tokenA, address tokenB, uint24 fee ) external returns (address pool); /// @notice Updates the owner of the factory /// @dev Must be called by the current owner /// @param _owner The new owner of the factory function setOwner(address _owner) external; /// @notice Enables a fee amount with the given tickSpacing /// @dev Fee amounts may never be removed once enabled /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6) /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount function enableFeeAmount(uint24 fee, int24 tickSpacing) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import './pool/IUniswapV3PoolImmutables.sol'; import './pool/IUniswapV3PoolState.sol'; import './pool/IUniswapV3PoolDerivedState.sol'; import './pool/IUniswapV3PoolActions.sol'; import './pool/IUniswapV3PoolOwnerActions.sol'; import './pool/IUniswapV3PoolEvents.sol'; /// @title The interface for a Uniswap V3 Pool /// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform /// to the ERC20 specification /// @dev The pool interface is broken up into many smaller pieces interface IUniswapV3Pool is IUniswapV3PoolImmutables, IUniswapV3PoolState, IUniswapV3PoolDerivedState, IUniswapV3PoolActions, IUniswapV3PoolOwnerActions, IUniswapV3PoolEvents { }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title An interface for a contract that is capable of deploying Uniswap V3 Pools /// @notice A contract that constructs a pool must implement this to pass arguments to the pool /// @dev This is used to avoid having constructor arguments in the pool contract, which results in the init code hash /// of the pool being constant allowing the CREATE2 address of the pool to be cheaply computed on-chain interface IUniswapV3PoolDeployer { /// @notice Get the parameters to be used in constructing the pool, set transiently during pool creation. /// @dev Called by the pool constructor to fetch the parameters of the pool /// Returns factory The factory address /// Returns token0 The first token of the pool by address sort order /// Returns token1 The second token of the pool by address sort order /// Returns fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// Returns tickSpacing The minimum number of ticks between initialized ticks function parameters() external view returns ( address factory, address token0, address token1, uint24 fee, int24 tickSpacing ); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#flash /// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface interface IUniswapV3FlashCallback { /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash. /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// @param fee0 The fee amount in token0 due to the pool by the end of the flash /// @param fee1 The fee amount in token1 due to the pool by the end of the flash /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call function uniswapV3FlashCallback( uint256 fee0, uint256 fee1, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#mint /// @notice Any contract that calls IUniswapV3PoolActions#mint must implement this interface interface IUniswapV3MintCallback { /// @notice Called to `msg.sender` after minting liquidity to a position from IUniswapV3Pool#mint. /// @dev In the implementation you must pay the pool tokens owed for the minted liquidity. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// @param amount0Owed The amount of token0 due to the pool for the minted liquidity /// @param amount1Owed The amount of token1 due to the pool for the minted liquidity /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#mint call function uniswapV3MintCallback( uint256 amount0Owed, uint256 amount1Owed, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Permissionless pool actions /// @notice Contains pool methods that can be called by anyone interface IUniswapV3PoolActions { /// @notice Sets the initial price for the pool /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96 function initialize(uint160 sqrtPriceX96) external; /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends /// on tickLower, tickUpper, the amount of liquidity, and the current price. /// @param recipient The address for which the liquidity will be created /// @param tickLower The lower tick of the position in which to add liquidity /// @param tickUpper The upper tick of the position in which to add liquidity /// @param amount The amount of liquidity to mint /// @param data Any data that should be passed through to the callback /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback function mint( address recipient, int24 tickLower, int24 tickUpper, uint128 amount, bytes calldata data ) external returns (uint256 amount0, uint256 amount1); /// @notice Collects tokens owed to a position /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity. /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity. /// @param recipient The address which should receive the fees collected /// @param tickLower The lower tick of the position for which to collect fees /// @param tickUpper The upper tick of the position for which to collect fees /// @param amount0Requested How much token0 should be withdrawn from the fees owed /// @param amount1Requested How much token1 should be withdrawn from the fees owed /// @return amount0 The amount of fees collected in token0 /// @return amount1 The amount of fees collected in token1 function collect( address recipient, int24 tickLower, int24 tickUpper, uint128 amount0Requested, uint128 amount1Requested ) external returns (uint128 amount0, uint128 amount1); /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0 /// @dev Fees must be collected separately via a call to #collect /// @param tickLower The lower tick of the position for which to burn liquidity /// @param tickUpper The upper tick of the position for which to burn liquidity /// @param amount How much liquidity to burn /// @return amount0 The amount of token0 sent to the recipient /// @return amount1 The amount of token1 sent to the recipient function burn( int24 tickLower, int24 tickUpper, uint128 amount ) external returns (uint256 amount0, uint256 amount1); /// @notice Swap token0 for token1, or token1 for token0 /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback /// @param recipient The address to receive the output of the swap /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0 /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this /// value after the swap. If one for zero, the price cannot be greater than this value after the swap /// @param data Any data to be passed through to the callback /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive function swap( address recipient, bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data ) external returns (int256 amount0, int256 amount1); /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling /// with 0 amount{0,1} and sending the donation amount(s) from the callback /// @param recipient The address which will receive the token0 and token1 amounts /// @param amount0 The amount of token0 to send /// @param amount1 The amount of token1 to send /// @param data Any data to be passed through to the callback function flash( address recipient, uint256 amount0, uint256 amount1, bytes calldata data ) external; /// @notice Increase the maximum number of price and liquidity observations that this pool will store /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to /// the input observationCardinalityNext. /// @param observationCardinalityNext The desired minimum number of observations for the pool to store function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Pool state that is not stored /// @notice Contains view functions to provide information about the pool that is computed rather than stored on the /// blockchain. The functions here may have variable gas costs. interface IUniswapV3PoolDerivedState { /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick, /// you must call it with secondsAgos = [3600, 0]. /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio. /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block /// timestamp function observe(uint32[] calldata secondsAgos) external view returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s); /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed. /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first /// snapshot is taken and the second snapshot is taken. /// @param tickLower The lower tick of the range /// @param tickUpper The upper tick of the range /// @return tickCumulativeInside The snapshot of the tick accumulator for the range /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range /// @return secondsInside The snapshot of seconds per liquidity for the range function snapshotCumulativesInside(int24 tickLower, int24 tickUpper) external view returns ( int56 tickCumulativeInside, uint160 secondsPerLiquidityInsideX128, uint32 secondsInside ); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Events emitted by a pool /// @notice Contains all events emitted by the pool interface IUniswapV3PoolEvents { /// @notice Emitted exactly once by a pool when #initialize is first called on the pool /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96 /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool event Initialize(uint160 sqrtPriceX96, int24 tick); /// @notice Emitted when liquidity is minted for a given position /// @param sender The address that minted the liquidity /// @param owner The owner of the position and recipient of any minted liquidity /// @param tickLower The lower tick of the position /// @param tickUpper The upper tick of the position /// @param amount The amount of liquidity minted to the position range /// @param amount0 How much token0 was required for the minted liquidity /// @param amount1 How much token1 was required for the minted liquidity event Mint( address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1 ); /// @notice Emitted when fees are collected by the owner of a position /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees /// @param owner The owner of the position for which fees are collected /// @param tickLower The lower tick of the position /// @param tickUpper The upper tick of the position /// @param amount0 The amount of token0 fees collected /// @param amount1 The amount of token1 fees collected event Collect( address indexed owner, address recipient, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount0, uint128 amount1 ); /// @notice Emitted when a position's liquidity is removed /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect /// @param owner The owner of the position for which liquidity is removed /// @param tickLower The lower tick of the position /// @param tickUpper The upper tick of the position /// @param amount The amount of liquidity to remove /// @param amount0 The amount of token0 withdrawn /// @param amount1 The amount of token1 withdrawn event Burn( address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1 ); /// @notice Emitted by the pool for any swaps between token0 and token1 /// @param sender The address that initiated the swap call, and that received the callback /// @param recipient The address that received the output of the swap /// @param amount0 The delta of the token0 balance of the pool /// @param amount1 The delta of the token1 balance of the pool /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96 /// @param liquidity The liquidity of the pool after the swap /// @param tick The log base 1.0001 of price of the pool after the swap event Swap( address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick ); /// @notice Emitted by the pool for any flashes of token0/token1 /// @param sender The address that initiated the swap call, and that received the callback /// @param recipient The address that received the tokens from flash /// @param amount0 The amount of token0 that was flashed /// @param amount1 The amount of token1 that was flashed /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee event Flash( address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1, uint256 paid0, uint256 paid1 ); /// @notice Emitted by the pool for increases to the number of observations that can be stored /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index /// just before a mint/swap/burn. /// @param observationCardinalityNextOld The previous value of the next observation cardinality /// @param observationCardinalityNextNew The updated value of the next observation cardinality event IncreaseObservationCardinalityNext( uint16 observationCardinalityNextOld, uint16 observationCardinalityNextNew ); /// @notice Emitted when the protocol fee is changed by the pool /// @param feeProtocol0Old The previous value of the token0 protocol fee /// @param feeProtocol1Old The previous value of the token1 protocol fee /// @param feeProtocol0New The updated value of the token0 protocol fee /// @param feeProtocol1New The updated value of the token1 protocol fee event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New); /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner /// @param sender The address that collects the protocol fees /// @param recipient The address that receives the collected protocol fees /// @param amount0 The amount of token0 protocol fees that is withdrawn /// @param amount0 The amount of token1 protocol fees that is withdrawn event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Pool state that never changes /// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values interface IUniswapV3PoolImmutables { /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface /// @return The contract address function factory() external view returns (address); /// @notice The first of the two tokens of the pool, sorted by address /// @return The token contract address function token0() external view returns (address); /// @notice The second of the two tokens of the pool, sorted by address /// @return The token contract address function token1() external view returns (address); /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6 /// @return The fee function fee() external view returns (uint24); /// @notice The pool tick spacing /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ... /// This value is an int24 to avoid casting even though it is always positive. /// @return The tick spacing function tickSpacing() external view returns (int24); /// @notice The maximum amount of position liquidity that can use any tick in the range /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool /// @return The max amount of liquidity per tick function maxLiquidityPerTick() external view returns (uint128); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Permissioned pool actions /// @notice Contains pool methods that may only be called by the factory owner interface IUniswapV3PoolOwnerActions { /// @notice Set the denominator of the protocol's % share of the fees /// @param feeProtocol0 new protocol fee for token0 of the pool /// @param feeProtocol1 new protocol fee for token1 of the pool function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external; /// @notice Collect the protocol fee accrued to the pool /// @param recipient The address to which collected protocol fees should be sent /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1 /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0 /// @return amount0 The protocol fee collected in token0 /// @return amount1 The protocol fee collected in token1 function collectProtocol( address recipient, uint128 amount0Requested, uint128 amount1Requested ) external returns (uint128 amount0, uint128 amount1); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Pool state that can change /// @notice These methods compose the pool's state, and can change with any frequency including multiple times /// per transaction interface IUniswapV3PoolState { /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas /// when accessed externally. /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value /// tick The current tick of the pool, i.e. according to the last tick transition that was run. /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick /// boundary. /// observationIndex The index of the last oracle observation that was written, /// observationCardinality The current maximum number of observations stored in the pool, /// observationCardinalityNext The next maximum number of observations, to be updated when the observation. /// feeProtocol The protocol fee for both tokens of the pool. /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0 /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee. /// unlocked Whether the pool is currently locked to reentrancy function slot0() external view returns ( uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked ); /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool /// @dev This value can overflow the uint256 function feeGrowthGlobal0X128() external view returns (uint256); /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool /// @dev This value can overflow the uint256 function feeGrowthGlobal1X128() external view returns (uint256); /// @notice The amounts of token0 and token1 that are owed to the protocol /// @dev Protocol fees will never exceed uint128 max in either token function protocolFees() external view returns (uint128 token0, uint128 token1); /// @notice The currently in range liquidity available to the pool /// @dev This value has no relationship to the total liquidity across all ticks function liquidity() external view returns (uint128); /// @notice Look up information about a specific tick in the pool /// @param tick The tick to look up /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or /// tick upper, /// liquidityNet how much liquidity changes when the pool price crosses the tick, /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0, /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1, /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick, /// secondsOutside the seconds spent on the other side of the tick from the current tick, /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false. /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0. /// In addition, these values are only relative and must be used only in comparison to previous snapshots for /// a specific position. function ticks(int24 tick) external view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128, int56 tickCumulativeOutside, uint160 secondsPerLiquidityOutsideX128, uint32 secondsOutside, bool initialized ); /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information function tickBitmap(int16 wordPosition) external view returns (uint256); /// @notice Returns the information about a position by the position's key /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper /// @return _liquidity The amount of liquidity in the position, /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke, /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke, /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke, /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke function positions(bytes32 key) external view returns ( uint128 _liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1 ); /// @notice Returns data about a specific observation index /// @param index The element of the observations array to fetch /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time /// ago, rather than at a specific index in the array. /// @return blockTimestamp The timestamp of the observation, /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp, /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp, /// Returns initialized whether the observation has been initialized and the values are safe to use function observations(uint256 index) external view returns ( uint32 blockTimestamp, int56 tickCumulative, uint160 secondsPerLiquidityCumulativeX128, bool initialized ); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title BitMath /// @dev This library provides functionality for computing bit properties of an unsigned integer library BitMath { /// @notice Returns the index of the most significant bit of the number, /// where the least significant bit is at index 0 and the most significant bit is at index 255 /// @dev The function satisfies the property: /// x >= 2**mostSignificantBit(x) and x < 2**(mostSignificantBit(x)+1) /// @param x the value for which to compute the most significant bit, must be greater than 0 /// @return r the index of the most significant bit function mostSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0); if (x >= 0x100000000000000000000000000000000) { x >>= 128; r += 128; } if (x >= 0x10000000000000000) { x >>= 64; r += 64; } if (x >= 0x100000000) { x >>= 32; r += 32; } if (x >= 0x10000) { x >>= 16; r += 16; } if (x >= 0x100) { x >>= 8; r += 8; } if (x >= 0x10) { x >>= 4; r += 4; } if (x >= 0x4) { x >>= 2; r += 2; } if (x >= 0x2) r += 1; } /// @notice Returns the index of the least significant bit of the number, /// where the least significant bit is at index 0 and the most significant bit is at index 255 /// @dev The function satisfies the property: /// (x & 2**leastSignificantBit(x)) != 0 and (x & (2**(leastSignificantBit(x)) - 1)) == 0) /// @param x the value for which to compute the least significant bit, must be greater than 0 /// @return r the index of the least significant bit function leastSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0); r = 255; if (x & type(uint128).max > 0) { r -= 128; } else { x >>= 128; } if (x & type(uint64).max > 0) { r -= 64; } else { x >>= 64; } if (x & type(uint32).max > 0) { r -= 32; } else { x >>= 32; } if (x & type(uint16).max > 0) { r -= 16; } else { x >>= 16; } if (x & type(uint8).max > 0) { r -= 8; } else { x >>= 8; } if (x & 0xf > 0) { r -= 4; } else { x >>= 4; } if (x & 0x3 > 0) { r -= 2; } else { x >>= 2; } if (x & 0x1 > 0) r -= 1; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.4.0; /// @title FixedPoint128 /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) library FixedPoint128 { uint256 internal constant Q128 = 0x100000000000000000000000000000000; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.4.0; /// @title FixedPoint96 /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) /// @dev Used in SqrtPriceMath.sol library FixedPoint96 { uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 0x1000000000000000000000000; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Math library for liquidity library LiquidityMath { /// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows /// @param x The liquidity before change /// @param y The delta by which liquidity should be changed /// @return z The liquidity delta function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) { if (y < 0) { require((z = x - uint128(-y)) < x, 'LS'); } else { require((z = x + uint128(y)) >= x, 'LA'); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.0; /// @title Optimized overflow and underflow safe math operations /// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost library LowGasSafeMath { /// @notice Returns x + y, reverts if sum overflows uint256 /// @param x The augend /// @param y The addend /// @return z The sum of x and y function add(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x + y) >= x); } /// @notice Returns x - y, reverts if underflows /// @param x The minuend /// @param y The subtrahend /// @return z The difference of x and y function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x - y) <= x); } /// @notice Returns x * y, reverts if overflows /// @param x The multiplicand /// @param y The multiplier /// @return z The product of x and y function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { require(x == 0 || (z = x * y) / x == y); } /// @notice Returns x + y, reverts if overflows or underflows /// @param x The augend /// @param y The addend /// @return z The sum of x and y function add(int256 x, int256 y) internal pure returns (int256 z) { require((z = x + y) >= x == (y >= 0)); } /// @notice Returns x - y, reverts if overflows or underflows /// @param x The minuend /// @param y The subtrahend /// @return z The difference of x and y function sub(int256 x, int256 y) internal pure returns (int256 z) { require((z = x - y) <= x == (y >= 0)); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Safe casting methods /// @notice Contains methods for safely casting between types library SafeCast { /// @notice Cast a uint256 to a uint160, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint160 function toUint160(uint256 y) internal pure returns (uint160 z) { require((z = uint160(y)) == y); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param y The int256 to be downcasted /// @return z The downcasted integer, now type int128 function toInt128(int256 y) internal pure returns (int128 z) { require((z = int128(y)) == y); } /// @notice Cast a uint256 to a int256, revert on overflow /// @param y The uint256 to be casted /// @return z The casted integer, now type int256 function toInt256(uint256 y) internal pure returns (int256 z) { require(y < 2**255); z = int256(y); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.0; import '../interfaces/IERC20Minimal.sol'; /// @title TransferHelper /// @notice Contains helper methods for interacting with ERC20 tokens that do not consistently return true/false library TransferHelper { /// @notice Transfers tokens from msg.sender to a recipient /// @dev Calls transfer on token contract, errors with TF if transfer fails /// @param token The contract address of the token which will be transferred /// @param to The recipient of the transfer /// @param value The value of the transfer function safeTransfer( address token, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20Minimal.transfer.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TF'); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Math functions that do not check inputs or outputs /// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks library UnsafeMath { /// @notice Returns ceil(x / y) /// @dev division by 0 has unspecified behavior, and must be checked externally /// @param x The dividend /// @param y The divisor /// @return z The quotient, ceil(x / y) function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := add(div(x, y), gt(mod(x, y), 0)) } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC6909Claims} from "./interfaces/external/IERC6909Claims.sol"; /// @notice Minimalist and gas efficient standard ERC6909 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC6909.sol) /// @dev Copied from the commit at 4b47a19038b798b4a33d9749d25e570443520647 /// @dev This contract has been modified from the implementation at the above link. abstract contract ERC6909 is IERC6909Claims { /*////////////////////////////////////////////////////////////// ERC6909 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address owner => mapping(address operator => bool isOperator)) public isOperator; mapping(address owner => mapping(uint256 id => uint256 balance)) public balanceOf; mapping(address owner => mapping(address spender => mapping(uint256 id => uint256 amount))) public allowance; /*////////////////////////////////////////////////////////////// ERC6909 LOGIC //////////////////////////////////////////////////////////////*/ function transfer(address receiver, uint256 id, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender][id] -= amount; balanceOf[receiver][id] += amount; emit Transfer(msg.sender, msg.sender, receiver, id, amount); return true; } function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public virtual returns (bool) { if (msg.sender != sender && !isOperator[sender][msg.sender]) { uint256 allowed = allowance[sender][msg.sender][id]; if (allowed != type(uint256).max) allowance[sender][msg.sender][id] = allowed - amount; } balanceOf[sender][id] -= amount; balanceOf[receiver][id] += amount; emit Transfer(msg.sender, sender, receiver, id, amount); return true; } function approve(address spender, uint256 id, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender][id] = amount; emit Approval(msg.sender, spender, id, amount); return true; } function setOperator(address operator, bool approved) public virtual returns (bool) { isOperator[msg.sender][operator] = approved; emit OperatorSet(msg.sender, operator, approved); return true; } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 || interfaceId == 0x0f632fb3; // ERC165 Interface ID for ERC6909 } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address receiver, uint256 id, uint256 amount) internal virtual { balanceOf[receiver][id] += amount; emit Transfer(msg.sender, address(0), receiver, id, amount); } function _burn(address sender, uint256 id, uint256 amount) internal virtual { balanceOf[sender][id] -= amount; emit Transfer(msg.sender, sender, address(0), id, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ERC6909} from "./ERC6909.sol"; /// @notice ERC6909Claims inherits ERC6909 and implements an internal burnFrom function abstract contract ERC6909Claims is ERC6909 { /// @notice Burn `amount` tokens of token type `id` from `from`. /// @dev if sender is not `from` they must be an operator or have sufficient allowance. /// @param from The address to burn tokens from. /// @param id The currency to burn. /// @param amount The amount to burn. function _burnFrom(address from, uint256 id, uint256 amount) internal { address sender = msg.sender; if (from != sender && !isOperator[from][sender]) { uint256 senderAllowance = allowance[from][sender][id]; if (senderAllowance != type(uint256).max) { allowance[from][sender][id] = senderAllowance - amount; } } _burn(from, id, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IExtsload} from "./interfaces/IExtsload.sol"; /// @notice Enables public storage access for efficient state retrieval by external contracts. /// https://eips.ethereum.org/EIPS/eip-2330#rationale abstract contract Extsload is IExtsload { /// @inheritdoc IExtsload function extsload(bytes32 slot) external view returns (bytes32) { assembly ("memory-safe") { mstore(0, sload(slot)) return(0, 0x20) } } /// @inheritdoc IExtsload function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory) { assembly ("memory-safe") { let memptr := mload(0x40) let start := memptr // A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas. let length := shl(5, nSlots) // The abi offset of dynamic array in the returndata is 32. mstore(memptr, 0x20) // Store the length of the array returned mstore(add(memptr, 0x20), nSlots) // update memptr to the first location to hold a result memptr := add(memptr, 0x40) let end := add(memptr, length) for {} 1 {} { mstore(memptr, sload(startSlot)) memptr := add(memptr, 0x20) startSlot := add(startSlot, 1) if iszero(lt(memptr, end)) { break } } return(start, sub(end, start)) } } /// @inheritdoc IExtsload function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory) { assembly ("memory-safe") { let memptr := mload(0x40) let start := memptr // for abi encoding the response - the array will be found at 0x20 mstore(memptr, 0x20) // next we store the length of the return array mstore(add(memptr, 0x20), slots.length) // update memptr to the first location to hold an array entry memptr := add(memptr, 0x40) // A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas. let end := add(memptr, shl(5, slots.length)) let calldataptr := slots.offset for {} 1 {} { mstore(memptr, sload(calldataload(calldataptr))) memptr := add(memptr, 0x20) calldataptr := add(calldataptr, 0x20) if iszero(lt(memptr, end)) { break } } return(start, sub(end, start)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {IExttload} from "./interfaces/IExttload.sol"; /// @notice Enables public transient storage access for efficient state retrieval by external contracts. /// https://eips.ethereum.org/EIPS/eip-2330#rationale abstract contract Exttload is IExttload { /// @inheritdoc IExttload function exttload(bytes32 slot) external view returns (bytes32) { assembly ("memory-safe") { mstore(0, tload(slot)) return(0, 0x20) } } /// @inheritdoc IExttload function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory) { assembly ("memory-safe") { let memptr := mload(0x40) let start := memptr // for abi encoding the response - the array will be found at 0x20 mstore(memptr, 0x20) // next we store the length of the return array mstore(add(memptr, 0x20), slots.length) // update memptr to the first location to hold an array entry memptr := add(memptr, 0x40) // A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas. let end := add(memptr, shl(5, slots.length)) let calldataptr := slots.offset for {} 1 {} { mstore(memptr, tload(calldataload(calldataptr))) memptr := add(memptr, 0x20) calldataptr := add(calldataptr, 0x20) if iszero(lt(memptr, end)) { break } } return(start, sub(end, start)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {CustomRevert} from "./libraries/CustomRevert.sol"; /// @title Prevents delegatecall to a contract /// @notice Base contract that provides a modifier for preventing delegatecall to methods in a child contract abstract contract NoDelegateCall { using CustomRevert for bytes4; error DelegateCallNotAllowed(); /// @dev The original address of this contract address private immutable original; constructor() { // Immutables are computed in the init code of the contract, and then inlined into the deployed bytecode. // In other words, this variable won't change when it's checked at runtime. original = address(this); } /// @dev Private method is used instead of inlining into modifier because modifiers are copied into each method, /// and the use of immutable means the address bytes are copied in every place the modifier is used. function checkNotDelegateCall() private view { if (address(this) != original) DelegateCallNotAllowed.selector.revertWith(); } /// @notice Prevents delegatecall into the modified method modifier noDelegateCall() { checkNotDelegateCall(); _; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; import {Hooks} from "./libraries/Hooks.sol"; import {Pool} from "./libraries/Pool.sol"; import {SafeCast} from "./libraries/SafeCast.sol"; import {Position} from "./libraries/Position.sol"; import {LPFeeLibrary} from "./libraries/LPFeeLibrary.sol"; import {Currency, CurrencyLibrary} from "./types/Currency.sol"; import {PoolKey} from "./types/PoolKey.sol"; import {TickMath} from "./libraries/TickMath.sol"; import {NoDelegateCall} from "./NoDelegateCall.sol"; import {IHooks} from "./interfaces/IHooks.sol"; import {IPoolManager} from "./interfaces/IPoolManager.sol"; import {IUnlockCallback} from "./interfaces/callback/IUnlockCallback.sol"; import {ProtocolFees} from "./ProtocolFees.sol"; import {ERC6909Claims} from "./ERC6909Claims.sol"; import {PoolId} from "./types/PoolId.sol"; import {BalanceDelta, BalanceDeltaLibrary} from "./types/BalanceDelta.sol"; import {BeforeSwapDelta} from "./types/BeforeSwapDelta.sol"; import {Lock} from "./libraries/Lock.sol"; import {CurrencyDelta} from "./libraries/CurrencyDelta.sol"; import {NonzeroDeltaCount} from "./libraries/NonzeroDeltaCount.sol"; import {CurrencyReserves} from "./libraries/CurrencyReserves.sol"; import {Extsload} from "./Extsload.sol"; import {Exttload} from "./Exttload.sol"; import {CustomRevert} from "./libraries/CustomRevert.sol"; // 4 // 44 // 444 // 444 4444 // 4444 4444 4444 // 4444 4444444 4444 4 // 4444 44444444 4444 4 // 44444 4444444 4444444444444444 444444 // 4 44444 44444444 444444444444444444444 4444 // 4 44444 4444444 4444444444444444444444 44444 // 4 444444 4444444 44444444444444444444444 44 4 // 44 44444 444444 444444444444444444444 4 4 // 44 44444 44444 4444444444444444444 4 44 // 44 4444 44 444444444444444 444 // 444 4444 4444444 // 4444444444444 44 4 // 44444444444 444444 444444444 44 // 444444 4444 4444 4444444444 44 // 4444 44 44 4 44444444444 // 44444 444444444 444444444444 4444 // 44444 44444444 4444 44444444 444444 // 44444 4444 444444444 44444444 // 44444 4444 44444444 4444444444 // 44444 4444 444444444 444444444444 // 44444 4444 44444444 444444444444 // 4444444 4444 44444444 4444444 // 4444444 44444 44444444 4444444 // 44444444 44444444444444444444444444444 4444 // 4444444444 44444444444444444444444444444 444 // 444444444444 444444444444444444444444444444 444 444 // 44444444444444 444444444 44444 // 44444 44444444444 444 44444444 444444 // 44444 4444444444 4444444444 444444 44444444 444444444444 // 444444444444444 4444 444444 4444444 44444444 444444444444 // 444444444444444 444 444444 444444 44444444 44444444444 // 4444444444444 4444 444444 4444 4444444444 // 444444444444 4 44444 4444 444444444 // 44444444444 444444 444 44444444 // 44444444 444444 4444 4444444 // 44444 444 44444 // 44444 444 4 4444 // 44444 444 44 444 // 44444 444 4444 // 444444 44444 444 // 444444444 444 // 44444 444 // 444 /// @title PoolManager /// @notice Holds the state for all pools contract PoolManager is IPoolManager, ProtocolFees, NoDelegateCall, ERC6909Claims, Extsload, Exttload { using SafeCast for *; using Pool for *; using Hooks for IHooks; using CurrencyDelta for Currency; using LPFeeLibrary for uint24; using CurrencyReserves for Currency; using CustomRevert for bytes4; int24 private constant MAX_TICK_SPACING = TickMath.MAX_TICK_SPACING; int24 private constant MIN_TICK_SPACING = TickMath.MIN_TICK_SPACING; mapping(PoolId id => Pool.State) internal _pools; /// @notice This will revert if the contract is locked modifier onlyWhenUnlocked() { if (!Lock.isUnlocked()) ManagerLocked.selector.revertWith(); _; } constructor(address initialOwner) ProtocolFees(initialOwner) {} /// @inheritdoc IPoolManager function unlock(bytes calldata data) external override returns (bytes memory result) { if (Lock.isUnlocked()) AlreadyUnlocked.selector.revertWith(); Lock.unlock(); // the caller does everything in this callback, including paying what they owe via calls to settle result = IUnlockCallback(msg.sender).unlockCallback(data); if (NonzeroDeltaCount.read() != 0) CurrencyNotSettled.selector.revertWith(); Lock.lock(); } /// @inheritdoc IPoolManager function initialize(PoolKey memory key, uint160 sqrtPriceX96) external noDelegateCall returns (int24 tick) { // see TickBitmap.sol for overflow conditions that can arise from tick spacing being too large if (key.tickSpacing > MAX_TICK_SPACING) TickSpacingTooLarge.selector.revertWith(key.tickSpacing); if (key.tickSpacing < MIN_TICK_SPACING) TickSpacingTooSmall.selector.revertWith(key.tickSpacing); if (key.currency0 >= key.currency1) { CurrenciesOutOfOrderOrEqual.selector.revertWith( Currency.unwrap(key.currency0), Currency.unwrap(key.currency1) ); } if (!key.hooks.isValidHookAddress(key.fee)) Hooks.HookAddressNotValid.selector.revertWith(address(key.hooks)); uint24 lpFee = key.fee.getInitialLPFee(); key.hooks.beforeInitialize(key, sqrtPriceX96); PoolId id = key.toId(); tick = _pools[id].initialize(sqrtPriceX96, lpFee); // event is emitted before the afterInitialize call to ensure events are always emitted in order // emit all details of a pool key. poolkeys are not saved in storage and must always be provided by the caller // the key's fee may be a static fee or a sentinel to denote a dynamic fee. emit Initialize(id, key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks, sqrtPriceX96, tick); key.hooks.afterInitialize(key, sqrtPriceX96, tick); } /// @inheritdoc IPoolManager function modifyLiquidity( PoolKey memory key, IPoolManager.ModifyLiquidityParams memory params, bytes calldata hookData ) external onlyWhenUnlocked noDelegateCall returns (BalanceDelta callerDelta, BalanceDelta feesAccrued) { PoolId id = key.toId(); { Pool.State storage pool = _getPool(id); pool.checkPoolInitialized(); key.hooks.beforeModifyLiquidity(key, params, hookData); BalanceDelta principalDelta; (principalDelta, feesAccrued) = pool.modifyLiquidity( Pool.ModifyLiquidityParams({ owner: msg.sender, tickLower: params.tickLower, tickUpper: params.tickUpper, liquidityDelta: params.liquidityDelta.toInt128(), tickSpacing: key.tickSpacing, salt: params.salt }) ); // fee delta and principal delta are both accrued to the caller callerDelta = principalDelta + feesAccrued; } // event is emitted before the afterModifyLiquidity call to ensure events are always emitted in order emit ModifyLiquidity(id, msg.sender, params.tickLower, params.tickUpper, params.liquidityDelta, params.salt); BalanceDelta hookDelta; (callerDelta, hookDelta) = key.hooks.afterModifyLiquidity(key, params, callerDelta, feesAccrued, hookData); // if the hook doesn't have the flag to be able to return deltas, hookDelta will always be 0 if (hookDelta != BalanceDeltaLibrary.ZERO_DELTA) _accountPoolBalanceDelta(key, hookDelta, address(key.hooks)); _accountPoolBalanceDelta(key, callerDelta, msg.sender); } /// @inheritdoc IPoolManager function swap(PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData) external onlyWhenUnlocked noDelegateCall returns (BalanceDelta swapDelta) { if (params.amountSpecified == 0) SwapAmountCannotBeZero.selector.revertWith(); PoolId id = key.toId(); Pool.State storage pool = _getPool(id); pool.checkPoolInitialized(); BeforeSwapDelta beforeSwapDelta; { int256 amountToSwap; uint24 lpFeeOverride; (amountToSwap, beforeSwapDelta, lpFeeOverride) = key.hooks.beforeSwap(key, params, hookData); // execute swap, account protocol fees, and emit swap event // _swap is needed to avoid stack too deep error swapDelta = _swap( pool, id, Pool.SwapParams({ tickSpacing: key.tickSpacing, zeroForOne: params.zeroForOne, amountSpecified: amountToSwap, sqrtPriceLimitX96: params.sqrtPriceLimitX96, lpFeeOverride: lpFeeOverride }), params.zeroForOne ? key.currency0 : key.currency1 // input token ); } BalanceDelta hookDelta; (swapDelta, hookDelta) = key.hooks.afterSwap(key, params, swapDelta, hookData, beforeSwapDelta); // if the hook doesn't have the flag to be able to return deltas, hookDelta will always be 0 if (hookDelta != BalanceDeltaLibrary.ZERO_DELTA) _accountPoolBalanceDelta(key, hookDelta, address(key.hooks)); _accountPoolBalanceDelta(key, swapDelta, msg.sender); } /// @notice Internal swap function to execute a swap, take protocol fees on input token, and emit the swap event function _swap(Pool.State storage pool, PoolId id, Pool.SwapParams memory params, Currency inputCurrency) internal returns (BalanceDelta) { (BalanceDelta delta, uint256 amountToProtocol, uint24 swapFee, Pool.SwapResult memory result) = pool.swap(params); // the fee is on the input currency if (amountToProtocol > 0) _updateProtocolFees(inputCurrency, amountToProtocol); // event is emitted before the afterSwap call to ensure events are always emitted in order emit Swap( id, msg.sender, delta.amount0(), delta.amount1(), result.sqrtPriceX96, result.liquidity, result.tick, swapFee ); return delta; } /// @inheritdoc IPoolManager function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) external onlyWhenUnlocked noDelegateCall returns (BalanceDelta delta) { PoolId poolId = key.toId(); Pool.State storage pool = _getPool(poolId); pool.checkPoolInitialized(); key.hooks.beforeDonate(key, amount0, amount1, hookData); delta = pool.donate(amount0, amount1); _accountPoolBalanceDelta(key, delta, msg.sender); // event is emitted before the afterDonate call to ensure events are always emitted in order emit Donate(poolId, msg.sender, amount0, amount1); key.hooks.afterDonate(key, amount0, amount1, hookData); } /// @inheritdoc IPoolManager function sync(Currency currency) external { // address(0) is used for the native currency if (currency.isAddressZero()) { // The reserves balance is not used for native settling, so we only need to reset the currency. CurrencyReserves.resetCurrency(); } else { uint256 balance = currency.balanceOfSelf(); CurrencyReserves.syncCurrencyAndReserves(currency, balance); } } /// @inheritdoc IPoolManager function take(Currency currency, address to, uint256 amount) external onlyWhenUnlocked { unchecked { // negation must be safe as amount is not negative _accountDelta(currency, -(amount.toInt128()), msg.sender); currency.transfer(to, amount); } } /// @inheritdoc IPoolManager function settle() external payable onlyWhenUnlocked returns (uint256) { return _settle(msg.sender); } /// @inheritdoc IPoolManager function settleFor(address recipient) external payable onlyWhenUnlocked returns (uint256) { return _settle(recipient); } /// @inheritdoc IPoolManager function clear(Currency currency, uint256 amount) external onlyWhenUnlocked { int256 current = currency.getDelta(msg.sender); // Because input is `uint256`, only positive amounts can be cleared. int128 amountDelta = amount.toInt128(); if (amountDelta != current) MustClearExactPositiveDelta.selector.revertWith(); // negation must be safe as amountDelta is positive unchecked { _accountDelta(currency, -(amountDelta), msg.sender); } } /// @inheritdoc IPoolManager function mint(address to, uint256 id, uint256 amount) external onlyWhenUnlocked { unchecked { Currency currency = CurrencyLibrary.fromId(id); // negation must be safe as amount is not negative _accountDelta(currency, -(amount.toInt128()), msg.sender); _mint(to, currency.toId(), amount); } } /// @inheritdoc IPoolManager function burn(address from, uint256 id, uint256 amount) external onlyWhenUnlocked { Currency currency = CurrencyLibrary.fromId(id); _accountDelta(currency, amount.toInt128(), msg.sender); _burnFrom(from, currency.toId(), amount); } /// @inheritdoc IPoolManager function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external { if (!key.fee.isDynamicFee() || msg.sender != address(key.hooks)) { UnauthorizedDynamicLPFeeUpdate.selector.revertWith(); } newDynamicLPFee.validate(); PoolId id = key.toId(); _pools[id].setLPFee(newDynamicLPFee); } // if settling native, integrators should still call `sync` first to avoid DoS attack vectors function _settle(address recipient) internal returns (uint256 paid) { Currency currency = CurrencyReserves.getSyncedCurrency(); // if not previously synced, or the syncedCurrency slot has been reset, expects native currency to be settled if (currency.isAddressZero()) { paid = msg.value; } else { if (msg.value > 0) NonzeroNativeValue.selector.revertWith(); // Reserves are guaranteed to be set because currency and reserves are always set together uint256 reservesBefore = CurrencyReserves.getSyncedReserves(); uint256 reservesNow = currency.balanceOfSelf(); paid = reservesNow - reservesBefore; CurrencyReserves.resetCurrency(); } _accountDelta(currency, paid.toInt128(), recipient); } /// @notice Adds a balance delta in a currency for a target address function _accountDelta(Currency currency, int128 delta, address target) internal { if (delta == 0) return; (int256 previous, int256 next) = currency.applyDelta(target, delta); if (next == 0) { NonzeroDeltaCount.decrement(); } else if (previous == 0) { NonzeroDeltaCount.increment(); } } /// @notice Accounts the deltas of 2 currencies to a target address function _accountPoolBalanceDelta(PoolKey memory key, BalanceDelta delta, address target) internal { _accountDelta(key.currency0, delta.amount0(), target); _accountDelta(key.currency1, delta.amount1(), target); } /// @notice Implementation of the _getPool function defined in ProtocolFees function _getPool(PoolId id) internal view override returns (Pool.State storage) { return _pools[id]; } /// @notice Implementation of the _isUnlocked function defined in ProtocolFees function _isUnlocked() internal view override returns (bool) { return Lock.isUnlocked(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Currency} from "./types/Currency.sol"; import {CurrencyReserves} from "./libraries/CurrencyReserves.sol"; import {IProtocolFees} from "./interfaces/IProtocolFees.sol"; import {PoolKey} from "./types/PoolKey.sol"; import {ProtocolFeeLibrary} from "./libraries/ProtocolFeeLibrary.sol"; import {Owned} from "solmate/src/auth/Owned.sol"; import {PoolId} from "./types/PoolId.sol"; import {Pool} from "./libraries/Pool.sol"; import {CustomRevert} from "./libraries/CustomRevert.sol"; /// @notice Contract handling the setting and accrual of protocol fees abstract contract ProtocolFees is IProtocolFees, Owned { using ProtocolFeeLibrary for uint24; using Pool for Pool.State; using CustomRevert for bytes4; /// @inheritdoc IProtocolFees mapping(Currency currency => uint256 amount) public protocolFeesAccrued; /// @inheritdoc IProtocolFees address public protocolFeeController; constructor(address initialOwner) Owned(initialOwner) {} /// @inheritdoc IProtocolFees function setProtocolFeeController(address controller) external onlyOwner { protocolFeeController = controller; emit ProtocolFeeControllerUpdated(controller); } /// @inheritdoc IProtocolFees function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external { if (msg.sender != protocolFeeController) InvalidCaller.selector.revertWith(); if (!newProtocolFee.isValidProtocolFee()) ProtocolFeeTooLarge.selector.revertWith(newProtocolFee); PoolId id = key.toId(); _getPool(id).setProtocolFee(newProtocolFee); emit ProtocolFeeUpdated(id, newProtocolFee); } /// @inheritdoc IProtocolFees function collectProtocolFees(address recipient, Currency currency, uint256 amount) external returns (uint256 amountCollected) { if (msg.sender != protocolFeeController) InvalidCaller.selector.revertWith(); if (!currency.isAddressZero() && CurrencyReserves.getSyncedCurrency() == currency) { // prevent transfer between the sync and settle balanceOfs (native settle uses msg.value) ProtocolFeeCurrencySynced.selector.revertWith(); } amountCollected = (amount == 0) ? protocolFeesAccrued[currency] : amount; protocolFeesAccrued[currency] -= amountCollected; currency.transfer(recipient, amountCollected); } /// @dev abstract internal function to allow the ProtocolFees contract to access the lock function _isUnlocked() internal virtual returns (bool); /// @dev abstract internal function to allow the ProtocolFees contract to access pool state /// @dev this is overridden in PoolManager.sol to give access to the _pools mapping function _getPool(PoolId id) internal virtual returns (Pool.State storage); function _updateProtocolFees(Currency currency, uint256 amount) internal { unchecked { protocolFeesAccrued[currency] += amount; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Interface for functions to access any storage slot in a contract interface IExtsload { /// @notice Called by external contracts to access granular pool state /// @param slot Key of slot to sload /// @return value The value of the slot as bytes32 function extsload(bytes32 slot) external view returns (bytes32 value); /// @notice Called by external contracts to access granular pool state /// @param startSlot Key of slot to start sloading from /// @param nSlots Number of slots to load into return value /// @return values List of loaded values. function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory values); /// @notice Called by external contracts to access sparse pool state /// @param slots List of slots to SLOAD from. /// @return values List of loaded values. function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory values); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /// @notice Interface for functions to access any transient storage slot in a contract interface IExttload { /// @notice Called by external contracts to access transient storage of the contract /// @param slot Key of slot to tload /// @return value The value of the slot as bytes32 function exttload(bytes32 slot) external view returns (bytes32 value); /// @notice Called by external contracts to access sparse transient pool state /// @param slots List of slots to tload /// @return values List of loaded values function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory values); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "../types/PoolKey.sol"; import {BalanceDelta} from "../types/BalanceDelta.sol"; import {IPoolManager} from "./IPoolManager.sol"; import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol"; /// @notice V4 decides whether to invoke specific hooks by inspecting the least significant bits /// of the address that the hooks contract is deployed to. /// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400 /// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used. /// See the Hooks library for the full spec. /// @dev Should only be callable by the v4 PoolManager. interface IHooks { /// @notice The hook called before the state of a pool is initialized /// @param sender The initial msg.sender for the initialize call /// @param key The key for the pool being initialized /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 /// @return bytes4 The function selector for the hook function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96) external returns (bytes4); /// @notice The hook called after the state of a pool is initialized /// @param sender The initial msg.sender for the initialize call /// @param key The key for the pool being initialized /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 /// @param tick The current tick after the state of a pool is initialized /// @return bytes4 The function selector for the hook function afterInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, int24 tick) external returns (bytes4); /// @notice The hook called before liquidity is added /// @param sender The initial msg.sender for the add liquidity call /// @param key The key for the pool /// @param params The parameters for adding liquidity /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook /// @return bytes4 The function selector for the hook function beforeAddLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, bytes calldata hookData ) external returns (bytes4); /// @notice The hook called after liquidity is added /// @param sender The initial msg.sender for the add liquidity call /// @param key The key for the pool /// @param params The parameters for adding liquidity /// @param delta The caller's balance delta after adding liquidity; the sum of principal delta, fees accrued, and hook delta /// @param feesAccrued The fees accrued since the last time fees were collected from this position /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook /// @return bytes4 The function selector for the hook /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency function afterAddLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external returns (bytes4, BalanceDelta); /// @notice The hook called before liquidity is removed /// @param sender The initial msg.sender for the remove liquidity call /// @param key The key for the pool /// @param params The parameters for removing liquidity /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook /// @return bytes4 The function selector for the hook function beforeRemoveLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, bytes calldata hookData ) external returns (bytes4); /// @notice The hook called after liquidity is removed /// @param sender The initial msg.sender for the remove liquidity call /// @param key The key for the pool /// @param params The parameters for removing liquidity /// @param delta The caller's balance delta after removing liquidity; the sum of principal delta, fees accrued, and hook delta /// @param feesAccrued The fees accrued since the last time fees were collected from this position /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook /// @return bytes4 The function selector for the hook /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency function afterRemoveLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external returns (bytes4, BalanceDelta); /// @notice The hook called before a swap /// @param sender The initial msg.sender for the swap call /// @param key The key for the pool /// @param params The parameters for the swap /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook /// @return bytes4 The function selector for the hook /// @return BeforeSwapDelta The hook's delta in specified and unspecified currencies. Positive: the hook is owed/took currency, negative: the hook owes/sent currency /// @return uint24 Optionally override the lp fee, only used if three conditions are met: 1. the Pool has a dynamic fee, 2. the value's 2nd highest bit is set (23rd bit, 0x400000), and 3. the value is less than or equal to the maximum fee (1 million) function beforeSwap( address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata hookData ) external returns (bytes4, BeforeSwapDelta, uint24); /// @notice The hook called after a swap /// @param sender The initial msg.sender for the swap call /// @param key The key for the pool /// @param params The parameters for the swap /// @param delta The amount owed to the caller (positive) or owed to the pool (negative) /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook /// @return bytes4 The function selector for the hook /// @return int128 The hook's delta in unspecified currency. Positive: the hook is owed/took currency, negative: the hook owes/sent currency function afterSwap( address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, BalanceDelta delta, bytes calldata hookData ) external returns (bytes4, int128); /// @notice The hook called before donate /// @param sender The initial msg.sender for the donate call /// @param key The key for the pool /// @param amount0 The amount of token0 being donated /// @param amount1 The amount of token1 being donated /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook /// @return bytes4 The function selector for the hook function beforeDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external returns (bytes4); /// @notice The hook called after donate /// @param sender The initial msg.sender for the donate call /// @param key The key for the pool /// @param amount0 The amount of token0 being donated /// @param amount1 The amount of token1 being donated /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook /// @return bytes4 The function selector for the hook function afterDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {Currency} from "../types/Currency.sol"; import {PoolKey} from "../types/PoolKey.sol"; import {IHooks} from "./IHooks.sol"; import {IERC6909Claims} from "./external/IERC6909Claims.sol"; import {IProtocolFees} from "./IProtocolFees.sol"; import {BalanceDelta} from "../types/BalanceDelta.sol"; import {PoolId} from "../types/PoolId.sol"; import {IExtsload} from "./IExtsload.sol"; import {IExttload} from "./IExttload.sol"; /// @notice Interface for the PoolManager interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload, IExttload { /// @notice Thrown when a currency is not netted out after the contract is unlocked error CurrencyNotSettled(); /// @notice Thrown when trying to interact with a non-initialized pool error PoolNotInitialized(); /// @notice Thrown when unlock is called, but the contract is already unlocked error AlreadyUnlocked(); /// @notice Thrown when a function is called that requires the contract to be unlocked, but it is not error ManagerLocked(); /// @notice Pools are limited to type(int16).max tickSpacing in #initialize, to prevent overflow error TickSpacingTooLarge(int24 tickSpacing); /// @notice Pools must have a positive non-zero tickSpacing passed to #initialize error TickSpacingTooSmall(int24 tickSpacing); /// @notice PoolKey must have currencies where address(currency0) < address(currency1) error CurrenciesOutOfOrderOrEqual(address currency0, address currency1); /// @notice Thrown when a call to updateDynamicLPFee is made by an address that is not the hook, /// or on a pool that does not have a dynamic swap fee. error UnauthorizedDynamicLPFeeUpdate(); /// @notice Thrown when trying to swap amount of 0 error SwapAmountCannotBeZero(); ///@notice Thrown when native currency is passed to a non native settlement error NonzeroNativeValue(); /// @notice Thrown when `clear` is called with an amount that is not exactly equal to the open currency delta. error MustClearExactPositiveDelta(); /// @notice Emitted when a new pool is initialized /// @param id The abi encoded hash of the pool key struct for the new pool /// @param currency0 The first currency of the pool by address sort order /// @param currency1 The second currency of the pool by address sort order /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @param tickSpacing The minimum number of ticks between initialized ticks /// @param hooks The hooks contract address for the pool, or address(0) if none /// @param sqrtPriceX96 The price of the pool on initialization /// @param tick The initial tick of the pool corresponding to the initialized price event Initialize( PoolId indexed id, Currency indexed currency0, Currency indexed currency1, uint24 fee, int24 tickSpacing, IHooks hooks, uint160 sqrtPriceX96, int24 tick ); /// @notice Emitted when a liquidity position is modified /// @param id The abi encoded hash of the pool key struct for the pool that was modified /// @param sender The address that modified the pool /// @param tickLower The lower tick of the position /// @param tickUpper The upper tick of the position /// @param liquidityDelta The amount of liquidity that was added or removed /// @param salt The extra data to make positions unique event ModifyLiquidity( PoolId indexed id, address indexed sender, int24 tickLower, int24 tickUpper, int256 liquidityDelta, bytes32 salt ); /// @notice Emitted for swaps between currency0 and currency1 /// @param id The abi encoded hash of the pool key struct for the pool that was modified /// @param sender The address that initiated the swap call, and that received the callback /// @param amount0 The delta of the currency0 balance of the pool /// @param amount1 The delta of the currency1 balance of the pool /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96 /// @param liquidity The liquidity of the pool after the swap /// @param tick The log base 1.0001 of the price of the pool after the swap /// @param fee The swap fee in hundredths of a bip event Swap( PoolId indexed id, address indexed sender, int128 amount0, int128 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick, uint24 fee ); /// @notice Emitted for donations /// @param id The abi encoded hash of the pool key struct for the pool that was donated to /// @param sender The address that initiated the donate call /// @param amount0 The amount donated in currency0 /// @param amount1 The amount donated in currency1 event Donate(PoolId indexed id, address indexed sender, uint256 amount0, uint256 amount1); /// @notice All interactions on the contract that account deltas require unlocking. A caller that calls `unlock` must implement /// `IUnlockCallback(msg.sender).unlockCallback(data)`, where they interact with the remaining functions on this contract. /// @dev The only functions callable without an unlocking are `initialize` and `updateDynamicLPFee` /// @param data Any data to pass to the callback, via `IUnlockCallback(msg.sender).unlockCallback(data)` /// @return The data returned by the call to `IUnlockCallback(msg.sender).unlockCallback(data)` function unlock(bytes calldata data) external returns (bytes memory); /// @notice Initialize the state for a given pool ID /// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee /// @param key The pool key for the pool to initialize /// @param sqrtPriceX96 The initial square root price /// @return tick The initial tick of the pool function initialize(PoolKey memory key, uint160 sqrtPriceX96) external returns (int24 tick); struct ModifyLiquidityParams { // the lower and upper tick of the position int24 tickLower; int24 tickUpper; // how to modify the liquidity int256 liquidityDelta; // a value to set if you want unique liquidity positions at the same range bytes32 salt; } /// @notice Modify the liquidity for the given pool /// @dev Poke by calling with a zero liquidityDelta /// @param key The pool to modify liquidity in /// @param params The parameters for modifying the liquidity /// @param hookData The data to pass through to the add/removeLiquidity hooks /// @return callerDelta The balance delta of the caller of modifyLiquidity. This is the total of both principal, fee deltas, and hook deltas if applicable /// @return feesAccrued The balance delta of the fees generated in the liquidity range. Returned for informational purposes /// @dev Note that feesAccrued can be artificially inflated by a malicious actor and integrators should be careful using the value /// For pools with a single liquidity position, actors can donate to themselves to inflate feeGrowthGlobal (and consequently feesAccrued) /// atomically donating and collecting fees in the same unlockCallback may make the inflated value more extreme function modifyLiquidity(PoolKey memory key, ModifyLiquidityParams memory params, bytes calldata hookData) external returns (BalanceDelta callerDelta, BalanceDelta feesAccrued); struct SwapParams { /// Whether to swap token0 for token1 or vice versa bool zeroForOne; /// The desired input amount if negative (exactIn), or the desired output amount if positive (exactOut) int256 amountSpecified; /// The sqrt price at which, if reached, the swap will stop executing uint160 sqrtPriceLimitX96; } /// @notice Swap against the given pool /// @param key The pool to swap in /// @param params The parameters for swapping /// @param hookData The data to pass through to the swap hooks /// @return swapDelta The balance delta of the address swapping /// @dev Swapping on low liquidity pools may cause unexpected swap amounts when liquidity available is less than amountSpecified. /// Additionally note that if interacting with hooks that have the BEFORE_SWAP_RETURNS_DELTA_FLAG or AFTER_SWAP_RETURNS_DELTA_FLAG /// the hook may alter the swap input/output. Integrators should perform checks on the returned swapDelta. function swap(PoolKey memory key, SwapParams memory params, bytes calldata hookData) external returns (BalanceDelta swapDelta); /// @notice Donate the given currency amounts to the in-range liquidity providers of a pool /// @dev Calls to donate can be frontrun adding just-in-time liquidity, with the aim of receiving a portion donated funds. /// Donors should keep this in mind when designing donation mechanisms. /// @dev This function donates to in-range LPs at slot0.tick. In certain edge-cases of the swap algorithm, the `sqrtPrice` of /// a pool can be at the lower boundary of tick `n`, but the `slot0.tick` of the pool is already `n - 1`. In this case a call to /// `donate` would donate to tick `n - 1` (slot0.tick) not tick `n` (getTickAtSqrtPrice(slot0.sqrtPriceX96)). /// Read the comments in `Pool.swap()` for more information about this. /// @param key The key of the pool to donate to /// @param amount0 The amount of currency0 to donate /// @param amount1 The amount of currency1 to donate /// @param hookData The data to pass through to the donate hooks /// @return BalanceDelta The delta of the caller after the donate function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) external returns (BalanceDelta); /// @notice Writes the current ERC20 balance of the specified currency to transient storage /// This is used to checkpoint balances for the manager and derive deltas for the caller. /// @dev This MUST be called before any ERC20 tokens are sent into the contract, but can be skipped /// for native tokens because the amount to settle is determined by the sent value. /// However, if an ERC20 token has been synced and not settled, and the caller instead wants to settle /// native funds, this function can be called with the native currency to then be able to settle the native currency function sync(Currency currency) external; /// @notice Called by the user to net out some value owed to the user /// @dev Will revert if the requested amount is not available, consider using `mint` instead /// @dev Can also be used as a mechanism for free flash loans /// @param currency The currency to withdraw from the pool manager /// @param to The address to withdraw to /// @param amount The amount of currency to withdraw function take(Currency currency, address to, uint256 amount) external; /// @notice Called by the user to pay what is owed /// @return paid The amount of currency settled function settle() external payable returns (uint256 paid); /// @notice Called by the user to pay on behalf of another address /// @param recipient The address to credit for the payment /// @return paid The amount of currency settled function settleFor(address recipient) external payable returns (uint256 paid); /// @notice WARNING - Any currency that is cleared, will be non-retrievable, and locked in the contract permanently. /// A call to clear will zero out a positive balance WITHOUT a corresponding transfer. /// @dev This could be used to clear a balance that is considered dust. /// Additionally, the amount must be the exact positive balance. This is to enforce that the caller is aware of the amount being cleared. function clear(Currency currency, uint256 amount) external; /// @notice Called by the user to move value into ERC6909 balance /// @param to The address to mint the tokens to /// @param id The currency address to mint to ERC6909s, as a uint256 /// @param amount The amount of currency to mint /// @dev The id is converted to a uint160 to correspond to a currency address /// If the upper 12 bytes are not 0, they will be 0-ed out function mint(address to, uint256 id, uint256 amount) external; /// @notice Called by the user to move value from ERC6909 balance /// @param from The address to burn the tokens from /// @param id The currency address to burn from ERC6909s, as a uint256 /// @param amount The amount of currency to burn /// @dev The id is converted to a uint160 to correspond to a currency address /// If the upper 12 bytes are not 0, they will be 0-ed out function burn(address from, uint256 id, uint256 amount) external; /// @notice Updates the pools lp fees for the a pool that has enabled dynamic lp fees. /// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee /// @param key The key of the pool to update dynamic LP fees for /// @param newDynamicLPFee The new dynamic pool LP fee function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Currency} from "../types/Currency.sol"; import {PoolId} from "../types/PoolId.sol"; import {PoolKey} from "../types/PoolKey.sol"; /// @notice Interface for all protocol-fee related functions in the pool manager interface IProtocolFees { /// @notice Thrown when protocol fee is set too high error ProtocolFeeTooLarge(uint24 fee); /// @notice Thrown when collectProtocolFees or setProtocolFee is not called by the controller. error InvalidCaller(); /// @notice Thrown when collectProtocolFees is attempted on a token that is synced. error ProtocolFeeCurrencySynced(); /// @notice Emitted when the protocol fee controller address is updated in setProtocolFeeController. event ProtocolFeeControllerUpdated(address indexed protocolFeeController); /// @notice Emitted when the protocol fee is updated for a pool. event ProtocolFeeUpdated(PoolId indexed id, uint24 protocolFee); /// @notice Given a currency address, returns the protocol fees accrued in that currency /// @param currency The currency to check /// @return amount The amount of protocol fees accrued in the currency function protocolFeesAccrued(Currency currency) external view returns (uint256 amount); /// @notice Sets the protocol fee for the given pool /// @param key The key of the pool to set a protocol fee for /// @param newProtocolFee The fee to set function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external; /// @notice Sets the protocol fee controller /// @param controller The new protocol fee controller function setProtocolFeeController(address controller) external; /// @notice Collects the protocol fees for a given recipient and currency, returning the amount collected /// @dev This will revert if the contract is unlocked /// @param recipient The address to receive the protocol fees /// @param currency The currency to withdraw /// @param amount The amount of currency to withdraw /// @return amountCollected The amount of currency successfully withdrawn function collectProtocolFees(address recipient, Currency currency, uint256 amount) external returns (uint256 amountCollected); /// @notice Returns the current protocol fee controller address /// @return address The current protocol fee controller address function protocolFeeController() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Interface for the callback executed when an address unlocks the pool manager interface IUnlockCallback { /// @notice Called by the pool manager on `msg.sender` when the manager is unlocked /// @param data The data that was passed to the call to unlock /// @return Any data that you want to be returned from the unlock call function unlockCallback(bytes calldata data) external returns (bytes memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Minimal ERC20 interface for Uniswap /// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3 interface IERC20Minimal { /// @notice Returns an account's balance in the token /// @param account The account for which to look up the number of tokens it has, i.e. its balance /// @return The number of tokens held by the account function balanceOf(address account) external view returns (uint256); /// @notice Transfers the amount of token from the `msg.sender` to the recipient /// @param recipient The account that will receive the amount transferred /// @param amount The number of tokens to send from the sender to the recipient /// @return Returns true for a successful transfer, false for an unsuccessful transfer function transfer(address recipient, uint256 amount) external returns (bool); /// @notice Returns the current allowance given to a spender by an owner /// @param owner The account of the token owner /// @param spender The account of the token spender /// @return The current allowance granted by `owner` to `spender` function allowance(address owner, address spender) external view returns (uint256); /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` /// @param spender The account which will be allowed to spend a given amount of the owners tokens /// @param amount The amount of tokens allowed to be used by `spender` /// @return Returns true for a successful approval, false for unsuccessful function approve(address spender, uint256 amount) external returns (bool); /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` /// @param sender The account from which the transfer will be initiated /// @param recipient The recipient of the transfer /// @param amount The amount of the transfer /// @return Returns true for a successful transfer, false for unsuccessful function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. /// @param from The account from which the tokens were sent, i.e. the balance decreased /// @param to The account to which the tokens were sent, i.e. the balance increased /// @param value The amount of tokens that were transferred event Transfer(address indexed from, address indexed to, uint256 value); /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. /// @param owner The account that approved spending of its tokens /// @param spender The account for which the spending allowance was modified /// @param value The new allowance from the owner to the spender event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Interface for claims over a contract balance, wrapped as a ERC6909 interface IERC6909Claims { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OperatorSet(address indexed owner, address indexed operator, bool approved); event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount); event Transfer(address caller, address indexed from, address indexed to, uint256 indexed id, uint256 amount); /*////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Owner balance of an id. /// @param owner The address of the owner. /// @param id The id of the token. /// @return amount The balance of the token. function balanceOf(address owner, uint256 id) external view returns (uint256 amount); /// @notice Spender allowance of an id. /// @param owner The address of the owner. /// @param spender The address of the spender. /// @param id The id of the token. /// @return amount The allowance of the token. function allowance(address owner, address spender, uint256 id) external view returns (uint256 amount); /// @notice Checks if a spender is approved by an owner as an operator /// @param owner The address of the owner. /// @param spender The address of the spender. /// @return approved The approval status. function isOperator(address owner, address spender) external view returns (bool approved); /// @notice Transfers an amount of an id from the caller to a receiver. /// @param receiver The address of the receiver. /// @param id The id of the token. /// @param amount The amount of the token. /// @return bool True, always, unless the function reverts function transfer(address receiver, uint256 id, uint256 amount) external returns (bool); /// @notice Transfers an amount of an id from a sender to a receiver. /// @param sender The address of the sender. /// @param receiver The address of the receiver. /// @param id The id of the token. /// @param amount The amount of the token. /// @return bool True, always, unless the function reverts function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool); /// @notice Approves an amount of an id to a spender. /// @param spender The address of the spender. /// @param id The id of the token. /// @param amount The amount of the token. /// @return bool True, always function approve(address spender, uint256 id, uint256 amount) external returns (bool); /// @notice Sets or removes an operator for the caller. /// @param operator The address of the operator. /// @param approved The approval status. /// @return bool True, always function setOperator(address operator, bool approved) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title BitMath /// @dev This library provides functionality for computing bit properties of an unsigned integer /// @author Solady (https://github.com/Vectorized/solady/blob/8200a70e8dc2a77ecb074fc2e99a2a0d36547522/src/utils/LibBit.sol) library BitMath { /// @notice Returns the index of the most significant bit of the number, /// where the least significant bit is at index 0 and the most significant bit is at index 255 /// @param x the value for which to compute the most significant bit, must be greater than 0 /// @return r the index of the most significant bit function mostSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0); assembly ("memory-safe") { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0x0706060506020500060203020504000106050205030304010505030400000000)) } } /// @notice Returns the index of the least significant bit of the number, /// where the least significant bit is at index 0 and the most significant bit is at index 255 /// @param x the value for which to compute the least significant bit, must be greater than 0 /// @return r the index of the least significant bit function leastSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0); assembly ("memory-safe") { // Isolate the least significant bit. x := and(x, sub(0, x)) // For the upper 3 bits of the result, use a De Bruijn-like lookup. // Credit to adhusson: https://blog.adhusson.com/cheap-find-first-set-evm/ // forgefmt: disable-next-item r := shl(5, shr(252, shl(shl(2, shr(250, mul(x, 0xb6db6db6ddddddddd34d34d349249249210842108c6318c639ce739cffffffff))), 0x8040405543005266443200005020610674053026020000107506200176117077))) // For the lower 5 bits of the result, use a De Bruijn lookup. // forgefmt: disable-next-item r := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f), 0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405)) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import {Currency} from "../types/Currency.sol"; /// @title a library to store callers' currency deltas in transient storage /// @dev this library implements the equivalent of a mapping, as transient storage can only be accessed in assembly library CurrencyDelta { /// @notice calculates which storage slot a delta should be stored in for a given account and currency function _computeSlot(address target, Currency currency) internal pure returns (bytes32 hashSlot) { assembly ("memory-safe") { mstore(0, and(target, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(32, and(currency, 0xffffffffffffffffffffffffffffffffffffffff)) hashSlot := keccak256(0, 64) } } function getDelta(Currency currency, address target) internal view returns (int256 delta) { bytes32 hashSlot = _computeSlot(target, currency); assembly ("memory-safe") { delta := tload(hashSlot) } } /// @notice applies a new currency delta for a given account and currency /// @return previous The prior value /// @return next The modified result function applyDelta(Currency currency, address target, int128 delta) internal returns (int256 previous, int256 next) { bytes32 hashSlot = _computeSlot(target, currency); assembly ("memory-safe") { previous := tload(hashSlot) } next = previous + delta; assembly ("memory-safe") { tstore(hashSlot, next) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import {Currency} from "../types/Currency.sol"; import {CustomRevert} from "./CustomRevert.sol"; library CurrencyReserves { using CustomRevert for bytes4; /// bytes32(uint256(keccak256("ReservesOf")) - 1) bytes32 constant RESERVES_OF_SLOT = 0x1e0745a7db1623981f0b2a5d4232364c00787266eb75ad546f190e6cebe9bd95; /// bytes32(uint256(keccak256("Currency")) - 1) bytes32 constant CURRENCY_SLOT = 0x27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b9; function getSyncedCurrency() internal view returns (Currency currency) { assembly ("memory-safe") { currency := tload(CURRENCY_SLOT) } } function resetCurrency() internal { assembly ("memory-safe") { tstore(CURRENCY_SLOT, 0) } } function syncCurrencyAndReserves(Currency currency, uint256 value) internal { assembly ("memory-safe") { tstore(CURRENCY_SLOT, and(currency, 0xffffffffffffffffffffffffffffffffffffffff)) tstore(RESERVES_OF_SLOT, value) } } function getSyncedReserves() internal view returns (uint256 value) { assembly ("memory-safe") { value := tload(RESERVES_OF_SLOT) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Library for reverting with custom errors efficiently /// @notice Contains functions for reverting with custom errors with different argument types efficiently /// @dev To use this library, declare `using CustomRevert for bytes4;` and replace `revert CustomError()` with /// `CustomError.selector.revertWith()` /// @dev The functions may tamper with the free memory pointer but it is fine since the call context is exited immediately library CustomRevert { /// @dev ERC-7751 error for wrapping bubbled up reverts error WrappedError(address target, bytes4 selector, bytes reason, bytes details); /// @dev Reverts with the selector of a custom error in the scratch space function revertWith(bytes4 selector) internal pure { assembly ("memory-safe") { mstore(0, selector) revert(0, 0x04) } } /// @dev Reverts with a custom error with an address argument in the scratch space function revertWith(bytes4 selector, address addr) internal pure { assembly ("memory-safe") { mstore(0, selector) mstore(0x04, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) revert(0, 0x24) } } /// @dev Reverts with a custom error with an int24 argument in the scratch space function revertWith(bytes4 selector, int24 value) internal pure { assembly ("memory-safe") { mstore(0, selector) mstore(0x04, signextend(2, value)) revert(0, 0x24) } } /// @dev Reverts with a custom error with a uint160 argument in the scratch space function revertWith(bytes4 selector, uint160 value) internal pure { assembly ("memory-safe") { mstore(0, selector) mstore(0x04, and(value, 0xffffffffffffffffffffffffffffffffffffffff)) revert(0, 0x24) } } /// @dev Reverts with a custom error with two int24 arguments function revertWith(bytes4 selector, int24 value1, int24 value2) internal pure { assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, selector) mstore(add(fmp, 0x04), signextend(2, value1)) mstore(add(fmp, 0x24), signextend(2, value2)) revert(fmp, 0x44) } } /// @dev Reverts with a custom error with two uint160 arguments function revertWith(bytes4 selector, uint160 value1, uint160 value2) internal pure { assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, selector) mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff)) revert(fmp, 0x44) } } /// @dev Reverts with a custom error with two address arguments function revertWith(bytes4 selector, address value1, address value2) internal pure { assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, selector) mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff)) revert(fmp, 0x44) } } /// @notice bubble up the revert message returned by a call and revert with a wrapped ERC-7751 error /// @dev this method can be vulnerable to revert data bombs function bubbleUpAndRevertWith( address revertingContract, bytes4 revertingFunctionSelector, bytes4 additionalContext ) internal pure { bytes4 wrappedErrorSelector = WrappedError.selector; assembly ("memory-safe") { // Ensure the size of the revert data is a multiple of 32 bytes let encodedDataSize := mul(div(add(returndatasize(), 31), 32), 32) let fmp := mload(0x40) // Encode wrapped error selector, address, function selector, offset, additional context, size, revert reason mstore(fmp, wrappedErrorSelector) mstore(add(fmp, 0x04), and(revertingContract, 0xffffffffffffffffffffffffffffffffffffffff)) mstore( add(fmp, 0x24), and(revertingFunctionSelector, 0xffffffff00000000000000000000000000000000000000000000000000000000) ) // offset revert reason mstore(add(fmp, 0x44), 0x80) // offset additional context mstore(add(fmp, 0x64), add(0xa0, encodedDataSize)) // size revert reason mstore(add(fmp, 0x84), returndatasize()) // revert reason returndatacopy(add(fmp, 0xa4), 0, returndatasize()) // size additional context mstore(add(fmp, add(0xa4, encodedDataSize)), 0x04) // additional context mstore( add(fmp, add(0xc4, encodedDataSize)), and(additionalContext, 0xffffffff00000000000000000000000000000000000000000000000000000000) ) revert(fmp, add(0xe4, encodedDataSize)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title FixedPoint128 /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) library FixedPoint128 { uint256 internal constant Q128 = 0x100000000000000000000000000000000; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title FixedPoint96 /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) /// @dev Used in SqrtPriceMath.sol library FixedPoint96 { uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 0x1000000000000000000000000; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0 = a * b; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly ("memory-safe") { let mm := mulmod(a, b, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { assembly ("memory-safe") { result := div(prod0, denominator) } return result; } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly ("memory-safe") { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly ("memory-safe") { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = (0 - denominator) & denominator; // Divide denominator by power of two assembly ("memory-safe") { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly ("memory-safe") { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly ("memory-safe") { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the preconditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { unchecked { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) != 0) { require(++result > 0); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "../types/PoolKey.sol"; import {IHooks} from "../interfaces/IHooks.sol"; import {SafeCast} from "./SafeCast.sol"; import {LPFeeLibrary} from "./LPFeeLibrary.sol"; import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol"; import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol"; import {IPoolManager} from "../interfaces/IPoolManager.sol"; import {ParseBytes} from "./ParseBytes.sol"; import {CustomRevert} from "./CustomRevert.sol"; /// @notice V4 decides whether to invoke specific hooks by inspecting the least significant bits /// of the address that the hooks contract is deployed to. /// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400 /// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used. library Hooks { using LPFeeLibrary for uint24; using Hooks for IHooks; using SafeCast for int256; using BeforeSwapDeltaLibrary for BeforeSwapDelta; using ParseBytes for bytes; using CustomRevert for bytes4; uint160 internal constant ALL_HOOK_MASK = uint160((1 << 14) - 1); uint160 internal constant BEFORE_INITIALIZE_FLAG = 1 << 13; uint160 internal constant AFTER_INITIALIZE_FLAG = 1 << 12; uint160 internal constant BEFORE_ADD_LIQUIDITY_FLAG = 1 << 11; uint160 internal constant AFTER_ADD_LIQUIDITY_FLAG = 1 << 10; uint160 internal constant BEFORE_REMOVE_LIQUIDITY_FLAG = 1 << 9; uint160 internal constant AFTER_REMOVE_LIQUIDITY_FLAG = 1 << 8; uint160 internal constant BEFORE_SWAP_FLAG = 1 << 7; uint160 internal constant AFTER_SWAP_FLAG = 1 << 6; uint160 internal constant BEFORE_DONATE_FLAG = 1 << 5; uint160 internal constant AFTER_DONATE_FLAG = 1 << 4; uint160 internal constant BEFORE_SWAP_RETURNS_DELTA_FLAG = 1 << 3; uint160 internal constant AFTER_SWAP_RETURNS_DELTA_FLAG = 1 << 2; uint160 internal constant AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 1; uint160 internal constant AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 0; struct Permissions { bool beforeInitialize; bool afterInitialize; bool beforeAddLiquidity; bool afterAddLiquidity; bool beforeRemoveLiquidity; bool afterRemoveLiquidity; bool beforeSwap; bool afterSwap; bool beforeDonate; bool afterDonate; bool beforeSwapReturnDelta; bool afterSwapReturnDelta; bool afterAddLiquidityReturnDelta; bool afterRemoveLiquidityReturnDelta; } /// @notice Thrown if the address will not lead to the specified hook calls being called /// @param hooks The address of the hooks contract error HookAddressNotValid(address hooks); /// @notice Hook did not return its selector error InvalidHookResponse(); /// @notice Additional context for ERC-7751 wrapped error when a hook call fails error HookCallFailed(); /// @notice The hook's delta changed the swap from exactIn to exactOut or vice versa error HookDeltaExceedsSwapAmount(); /// @notice Utility function intended to be used in hook constructors to ensure /// the deployed hooks address causes the intended hooks to be called /// @param permissions The hooks that are intended to be called /// @dev permissions param is memory as the function will be called from constructors function validateHookPermissions(IHooks self, Permissions memory permissions) internal pure { if ( permissions.beforeInitialize != self.hasPermission(BEFORE_INITIALIZE_FLAG) || permissions.afterInitialize != self.hasPermission(AFTER_INITIALIZE_FLAG) || permissions.beforeAddLiquidity != self.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG) || permissions.afterAddLiquidity != self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG) || permissions.beforeRemoveLiquidity != self.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG) || permissions.afterRemoveLiquidity != self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG) || permissions.beforeSwap != self.hasPermission(BEFORE_SWAP_FLAG) || permissions.afterSwap != self.hasPermission(AFTER_SWAP_FLAG) || permissions.beforeDonate != self.hasPermission(BEFORE_DONATE_FLAG) || permissions.afterDonate != self.hasPermission(AFTER_DONATE_FLAG) || permissions.beforeSwapReturnDelta != self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG) || permissions.afterSwapReturnDelta != self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG) || permissions.afterAddLiquidityReturnDelta != self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG) || permissions.afterRemoveLiquidityReturnDelta != self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG) ) { HookAddressNotValid.selector.revertWith(address(self)); } } /// @notice Ensures that the hook address includes at least one hook flag or dynamic fees, or is the 0 address /// @param self The hook to verify /// @param fee The fee of the pool the hook is used with /// @return bool True if the hook address is valid function isValidHookAddress(IHooks self, uint24 fee) internal pure returns (bool) { // The hook can only have a flag to return a hook delta on an action if it also has the corresponding action flag if (!self.hasPermission(BEFORE_SWAP_FLAG) && self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)) return false; if (!self.hasPermission(AFTER_SWAP_FLAG) && self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG)) return false; if (!self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG) && self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)) { return false; } if ( !self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG) && self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG) ) return false; // If there is no hook contract set, then fee cannot be dynamic // If a hook contract is set, it must have at least 1 flag set, or have a dynamic fee return address(self) == address(0) ? !fee.isDynamicFee() : (uint160(address(self)) & ALL_HOOK_MASK > 0 || fee.isDynamicFee()); } /// @notice performs a hook call using the given calldata on the given hook that doesn't return a delta /// @return result The complete data returned by the hook function callHook(IHooks self, bytes memory data) internal returns (bytes memory result) { bool success; assembly ("memory-safe") { success := call(gas(), self, 0, add(data, 0x20), mload(data), 0, 0) } // Revert with FailedHookCall, containing any error message to bubble up if (!success) CustomRevert.bubbleUpAndRevertWith(address(self), bytes4(data), HookCallFailed.selector); // The call was successful, fetch the returned data assembly ("memory-safe") { // allocate result byte array from the free memory pointer result := mload(0x40) // store new free memory pointer at the end of the array padded to 32 bytes mstore(0x40, add(result, and(add(returndatasize(), 0x3f), not(0x1f)))) // store length in memory mstore(result, returndatasize()) // copy return data to result returndatacopy(add(result, 0x20), 0, returndatasize()) } // Length must be at least 32 to contain the selector. Check expected selector and returned selector match. if (result.length < 32 || result.parseSelector() != data.parseSelector()) { InvalidHookResponse.selector.revertWith(); } } /// @notice performs a hook call using the given calldata on the given hook /// @return int256 The delta returned by the hook function callHookWithReturnDelta(IHooks self, bytes memory data, bool parseReturn) internal returns (int256) { bytes memory result = callHook(self, data); // If this hook wasn't meant to return something, default to 0 delta if (!parseReturn) return 0; // A length of 64 bytes is required to return a bytes4, and a 32 byte delta if (result.length != 64) InvalidHookResponse.selector.revertWith(); return result.parseReturnDelta(); } /// @notice modifier to prevent calling a hook if they initiated the action modifier noSelfCall(IHooks self) { if (msg.sender != address(self)) { _; } } /// @notice calls beforeInitialize hook if permissioned and validates return value function beforeInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96) internal noSelfCall(self) { if (self.hasPermission(BEFORE_INITIALIZE_FLAG)) { self.callHook(abi.encodeCall(IHooks.beforeInitialize, (msg.sender, key, sqrtPriceX96))); } } /// @notice calls afterInitialize hook if permissioned and validates return value function afterInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96, int24 tick) internal noSelfCall(self) { if (self.hasPermission(AFTER_INITIALIZE_FLAG)) { self.callHook(abi.encodeCall(IHooks.afterInitialize, (msg.sender, key, sqrtPriceX96, tick))); } } /// @notice calls beforeModifyLiquidity hook if permissioned and validates return value function beforeModifyLiquidity( IHooks self, PoolKey memory key, IPoolManager.ModifyLiquidityParams memory params, bytes calldata hookData ) internal noSelfCall(self) { if (params.liquidityDelta > 0 && self.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG)) { self.callHook(abi.encodeCall(IHooks.beforeAddLiquidity, (msg.sender, key, params, hookData))); } else if (params.liquidityDelta <= 0 && self.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG)) { self.callHook(abi.encodeCall(IHooks.beforeRemoveLiquidity, (msg.sender, key, params, hookData))); } } /// @notice calls afterModifyLiquidity hook if permissioned and validates return value function afterModifyLiquidity( IHooks self, PoolKey memory key, IPoolManager.ModifyLiquidityParams memory params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) internal returns (BalanceDelta callerDelta, BalanceDelta hookDelta) { if (msg.sender == address(self)) return (delta, BalanceDeltaLibrary.ZERO_DELTA); callerDelta = delta; if (params.liquidityDelta > 0) { if (self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG)) { hookDelta = BalanceDelta.wrap( self.callHookWithReturnDelta( abi.encodeCall( IHooks.afterAddLiquidity, (msg.sender, key, params, delta, feesAccrued, hookData) ), self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG) ) ); callerDelta = callerDelta - hookDelta; } } else { if (self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG)) { hookDelta = BalanceDelta.wrap( self.callHookWithReturnDelta( abi.encodeCall( IHooks.afterRemoveLiquidity, (msg.sender, key, params, delta, feesAccrued, hookData) ), self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG) ) ); callerDelta = callerDelta - hookDelta; } } } /// @notice calls beforeSwap hook if permissioned and validates return value function beforeSwap(IHooks self, PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData) internal returns (int256 amountToSwap, BeforeSwapDelta hookReturn, uint24 lpFeeOverride) { amountToSwap = params.amountSpecified; if (msg.sender == address(self)) return (amountToSwap, BeforeSwapDeltaLibrary.ZERO_DELTA, lpFeeOverride); if (self.hasPermission(BEFORE_SWAP_FLAG)) { bytes memory result = callHook(self, abi.encodeCall(IHooks.beforeSwap, (msg.sender, key, params, hookData))); // A length of 96 bytes is required to return a bytes4, a 32 byte delta, and an LP fee if (result.length != 96) InvalidHookResponse.selector.revertWith(); // dynamic fee pools that want to override the cache fee, return a valid fee with the override flag. If override flag // is set but an invalid fee is returned, the transaction will revert. Otherwise the current LP fee will be used if (key.fee.isDynamicFee()) lpFeeOverride = result.parseFee(); // skip this logic for the case where the hook return is 0 if (self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)) { hookReturn = BeforeSwapDelta.wrap(result.parseReturnDelta()); // any return in unspecified is passed to the afterSwap hook for handling int128 hookDeltaSpecified = hookReturn.getSpecifiedDelta(); // Update the swap amount according to the hook's return, and check that the swap type doesn't change (exact input/output) if (hookDeltaSpecified != 0) { bool exactInput = amountToSwap < 0; amountToSwap += hookDeltaSpecified; if (exactInput ? amountToSwap > 0 : amountToSwap < 0) { HookDeltaExceedsSwapAmount.selector.revertWith(); } } } } } /// @notice calls afterSwap hook if permissioned and validates return value function afterSwap( IHooks self, PoolKey memory key, IPoolManager.SwapParams memory params, BalanceDelta swapDelta, bytes calldata hookData, BeforeSwapDelta beforeSwapHookReturn ) internal returns (BalanceDelta, BalanceDelta) { if (msg.sender == address(self)) return (swapDelta, BalanceDeltaLibrary.ZERO_DELTA); int128 hookDeltaSpecified = beforeSwapHookReturn.getSpecifiedDelta(); int128 hookDeltaUnspecified = beforeSwapHookReturn.getUnspecifiedDelta(); if (self.hasPermission(AFTER_SWAP_FLAG)) { hookDeltaUnspecified += self.callHookWithReturnDelta( abi.encodeCall(IHooks.afterSwap, (msg.sender, key, params, swapDelta, hookData)), self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG) ).toInt128(); } BalanceDelta hookDelta; if (hookDeltaUnspecified != 0 || hookDeltaSpecified != 0) { hookDelta = (params.amountSpecified < 0 == params.zeroForOne) ? toBalanceDelta(hookDeltaSpecified, hookDeltaUnspecified) : toBalanceDelta(hookDeltaUnspecified, hookDeltaSpecified); // the caller has to pay for (or receive) the hook's delta swapDelta = swapDelta - hookDelta; } return (swapDelta, hookDelta); } /// @notice calls beforeDonate hook if permissioned and validates return value function beforeDonate(IHooks self, PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) internal noSelfCall(self) { if (self.hasPermission(BEFORE_DONATE_FLAG)) { self.callHook(abi.encodeCall(IHooks.beforeDonate, (msg.sender, key, amount0, amount1, hookData))); } } /// @notice calls afterDonate hook if permissioned and validates return value function afterDonate(IHooks self, PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) internal noSelfCall(self) { if (self.hasPermission(AFTER_DONATE_FLAG)) { self.callHook(abi.encodeCall(IHooks.afterDonate, (msg.sender, key, amount0, amount1, hookData))); } } function hasPermission(IHooks self, uint160 flag) internal pure returns (bool) { return uint160(address(self)) & flag != 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {CustomRevert} from "./CustomRevert.sol"; /// @notice Library of helper functions for a pools LP fee library LPFeeLibrary { using LPFeeLibrary for uint24; using CustomRevert for bytes4; /// @notice Thrown when the static or dynamic fee on a pool exceeds 100%. error LPFeeTooLarge(uint24 fee); /// @notice An lp fee of exactly 0b1000000... signals a dynamic fee pool. This isn't a valid static fee as it is > MAX_LP_FEE uint24 public constant DYNAMIC_FEE_FLAG = 0x800000; /// @notice the second bit of the fee returned by beforeSwap is used to signal if the stored LP fee should be overridden in this swap // only dynamic-fee pools can return a fee via the beforeSwap hook uint24 public constant OVERRIDE_FEE_FLAG = 0x400000; /// @notice mask to remove the override fee flag from a fee returned by the beforeSwaphook uint24 public constant REMOVE_OVERRIDE_MASK = 0xBFFFFF; /// @notice the lp fee is represented in hundredths of a bip, so the max is 100% uint24 public constant MAX_LP_FEE = 1000000; /// @notice returns true if a pool's LP fee signals that the pool has a dynamic fee /// @param self The fee to check /// @return bool True of the fee is dynamic function isDynamicFee(uint24 self) internal pure returns (bool) { return self == DYNAMIC_FEE_FLAG; } /// @notice returns true if an LP fee is valid, aka not above the maximum permitted fee /// @param self The fee to check /// @return bool True of the fee is valid function isValid(uint24 self) internal pure returns (bool) { return self <= MAX_LP_FEE; } /// @notice validates whether an LP fee is larger than the maximum, and reverts if invalid /// @param self The fee to validate function validate(uint24 self) internal pure { if (!self.isValid()) LPFeeTooLarge.selector.revertWith(self); } /// @notice gets and validates the initial LP fee for a pool. Dynamic fee pools have an initial fee of 0. /// @dev if a dynamic fee pool wants a non-0 initial fee, it should call `updateDynamicLPFee` in the afterInitialize hook /// @param self The fee to get the initial LP from /// @return initialFee 0 if the fee is dynamic, otherwise the fee (if valid) function getInitialLPFee(uint24 self) internal pure returns (uint24) { // the initial fee for a dynamic fee pool is 0 if (self.isDynamicFee()) return 0; self.validate(); return self; } /// @notice returns true if the fee has the override flag set (2nd highest bit of the uint24) /// @param self The fee to check /// @return bool True of the fee has the override flag set function isOverride(uint24 self) internal pure returns (bool) { return self & OVERRIDE_FEE_FLAG != 0; } /// @notice returns a fee with the override flag removed /// @param self The fee to remove the override flag from /// @return fee The fee without the override flag set function removeOverrideFlag(uint24 self) internal pure returns (uint24) { return self & REMOVE_OVERRIDE_MASK; } /// @notice Removes the override flag and validates the fee (reverts if the fee is too large) /// @param self The fee to remove the override flag from, and then validate /// @return fee The fee without the override flag set (if valid) function removeOverrideFlagAndValidate(uint24 self) internal pure returns (uint24 fee) { fee = self.removeOverrideFlag(); fee.validate(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Math library for liquidity library LiquidityMath { /// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows /// @param x The liquidity before change /// @param y The delta by which liquidity should be changed /// @return z The liquidity delta function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) { assembly ("memory-safe") { z := add(and(x, 0xffffffffffffffffffffffffffffffff), signextend(15, y)) if shr(128, z) { // revert SafeCastOverflow() mstore(0, 0x93dafdf1) revert(0x1c, 0x04) } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; /// @notice This is a temporary library that allows us to use transient storage (tstore/tload) /// TODO: This library can be deleted when we have the transient keyword support in solidity. library Lock { // The slot holding the unlocked state, transiently. bytes32(uint256(keccak256("Unlocked")) - 1) bytes32 internal constant IS_UNLOCKED_SLOT = 0xc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab23; function unlock() internal { assembly ("memory-safe") { // unlock tstore(IS_UNLOCKED_SLOT, true) } } function lock() internal { assembly ("memory-safe") { tstore(IS_UNLOCKED_SLOT, false) } } function isUnlocked() internal view returns (bool unlocked) { assembly ("memory-safe") { unlocked := tload(IS_UNLOCKED_SLOT) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; /// @notice This is a temporary library that allows us to use transient storage (tstore/tload) /// for the nonzero delta count. /// TODO: This library can be deleted when we have the transient keyword support in solidity. library NonzeroDeltaCount { // The slot holding the number of nonzero deltas. bytes32(uint256(keccak256("NonzeroDeltaCount")) - 1) bytes32 internal constant NONZERO_DELTA_COUNT_SLOT = 0x7d4b3164c6e45b97e7d87b7125a44c5828d005af88f9d751cfd78729c5d99a0b; function read() internal view returns (uint256 count) { assembly ("memory-safe") { count := tload(NONZERO_DELTA_COUNT_SLOT) } } function increment() internal { assembly ("memory-safe") { let count := tload(NONZERO_DELTA_COUNT_SLOT) count := add(count, 1) tstore(NONZERO_DELTA_COUNT_SLOT, count) } } /// @notice Potential to underflow. Ensure checks are performed by integrating contracts to ensure this does not happen. /// Current usage ensures this will not happen because we call decrement with known boundaries (only up to the number of times we call increment). function decrement() internal { assembly ("memory-safe") { let count := tload(NONZERO_DELTA_COUNT_SLOT) count := sub(count, 1) tstore(NONZERO_DELTA_COUNT_SLOT, count) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Parses bytes returned from hooks and the byte selector used to check return selectors from hooks. /// @dev parseSelector also is used to parse the expected selector /// For parsing hook returns, note that all hooks return either bytes4 or (bytes4, 32-byte-delta) or (bytes4, 32-byte-delta, uint24). library ParseBytes { function parseSelector(bytes memory result) internal pure returns (bytes4 selector) { // equivalent: (selector,) = abi.decode(result, (bytes4, int256)); assembly ("memory-safe") { selector := mload(add(result, 0x20)) } } function parseFee(bytes memory result) internal pure returns (uint24 lpFee) { // equivalent: (,, lpFee) = abi.decode(result, (bytes4, int256, uint24)); assembly ("memory-safe") { lpFee := mload(add(result, 0x60)) } } function parseReturnDelta(bytes memory result) internal pure returns (int256 hookReturn) { // equivalent: (, hookReturnDelta) = abi.decode(result, (bytes4, int256)); assembly ("memory-safe") { hookReturn := mload(add(result, 0x40)) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import {SafeCast} from "./SafeCast.sol"; import {TickBitmap} from "./TickBitmap.sol"; import {Position} from "./Position.sol"; import {UnsafeMath} from "./UnsafeMath.sol"; import {FixedPoint128} from "./FixedPoint128.sol"; import {TickMath} from "./TickMath.sol"; import {SqrtPriceMath} from "./SqrtPriceMath.sol"; import {SwapMath} from "./SwapMath.sol"; import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol"; import {Slot0} from "../types/Slot0.sol"; import {ProtocolFeeLibrary} from "./ProtocolFeeLibrary.sol"; import {LiquidityMath} from "./LiquidityMath.sol"; import {LPFeeLibrary} from "./LPFeeLibrary.sol"; import {CustomRevert} from "./CustomRevert.sol"; /// @notice a library with all actions that can be performed on a pool library Pool { using SafeCast for *; using TickBitmap for mapping(int16 => uint256); using Position for mapping(bytes32 => Position.State); using Position for Position.State; using Pool for State; using ProtocolFeeLibrary for *; using LPFeeLibrary for uint24; using CustomRevert for bytes4; /// @notice Thrown when tickLower is not below tickUpper /// @param tickLower The invalid tickLower /// @param tickUpper The invalid tickUpper error TicksMisordered(int24 tickLower, int24 tickUpper); /// @notice Thrown when tickLower is less than min tick /// @param tickLower The invalid tickLower error TickLowerOutOfBounds(int24 tickLower); /// @notice Thrown when tickUpper exceeds max tick /// @param tickUpper The invalid tickUpper error TickUpperOutOfBounds(int24 tickUpper); /// @notice For the tick spacing, the tick has too much liquidity error TickLiquidityOverflow(int24 tick); /// @notice Thrown when trying to initialize an already initialized pool error PoolAlreadyInitialized(); /// @notice Thrown when trying to interact with a non-initialized pool error PoolNotInitialized(); /// @notice Thrown when sqrtPriceLimitX96 on a swap has already exceeded its limit /// @param sqrtPriceCurrentX96 The invalid, already surpassed sqrtPriceLimitX96 /// @param sqrtPriceLimitX96 The surpassed price limit error PriceLimitAlreadyExceeded(uint160 sqrtPriceCurrentX96, uint160 sqrtPriceLimitX96); /// @notice Thrown when sqrtPriceLimitX96 lies outside of valid tick/price range /// @param sqrtPriceLimitX96 The invalid, out-of-bounds sqrtPriceLimitX96 error PriceLimitOutOfBounds(uint160 sqrtPriceLimitX96); /// @notice Thrown by donate if there is currently 0 liquidity, since the fees will not go to any liquidity providers error NoLiquidityToReceiveFees(); /// @notice Thrown when trying to swap with max lp fee and specifying an output amount error InvalidFeeForExactOut(); // info stored for each initialized individual tick struct TickInfo { // the total position liquidity that references this tick uint128 liquidityGross; // amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left), int128 liquidityNet; // fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) // only has relative meaning, not absolute — the value depends on when the tick is initialized uint256 feeGrowthOutside0X128; uint256 feeGrowthOutside1X128; } /// @notice The state of a pool /// @dev Note that feeGrowthGlobal can be artificially inflated /// For pools with a single liquidity position, actors can donate to themselves to freely inflate feeGrowthGlobal /// atomically donating and collecting fees in the same unlockCallback may make the inflated value more extreme struct State { Slot0 slot0; uint256 feeGrowthGlobal0X128; uint256 feeGrowthGlobal1X128; uint128 liquidity; mapping(int24 tick => TickInfo) ticks; mapping(int16 wordPos => uint256) tickBitmap; mapping(bytes32 positionKey => Position.State) positions; } /// @dev Common checks for valid tick inputs. function checkTicks(int24 tickLower, int24 tickUpper) private pure { if (tickLower >= tickUpper) TicksMisordered.selector.revertWith(tickLower, tickUpper); if (tickLower < TickMath.MIN_TICK) TickLowerOutOfBounds.selector.revertWith(tickLower); if (tickUpper > TickMath.MAX_TICK) TickUpperOutOfBounds.selector.revertWith(tickUpper); } function initialize(State storage self, uint160 sqrtPriceX96, uint24 lpFee) internal returns (int24 tick) { if (self.slot0.sqrtPriceX96() != 0) PoolAlreadyInitialized.selector.revertWith(); tick = TickMath.getTickAtSqrtPrice(sqrtPriceX96); // the initial protocolFee is 0 so doesn't need to be set self.slot0 = Slot0.wrap(bytes32(0)).setSqrtPriceX96(sqrtPriceX96).setTick(tick).setLpFee(lpFee); } function setProtocolFee(State storage self, uint24 protocolFee) internal { self.checkPoolInitialized(); self.slot0 = self.slot0.setProtocolFee(protocolFee); } /// @notice Only dynamic fee pools may update the lp fee. function setLPFee(State storage self, uint24 lpFee) internal { self.checkPoolInitialized(); self.slot0 = self.slot0.setLpFee(lpFee); } struct ModifyLiquidityParams { // the address that owns the position address owner; // the lower and upper tick of the position int24 tickLower; int24 tickUpper; // any change in liquidity int128 liquidityDelta; // the spacing between ticks int24 tickSpacing; // used to distinguish positions of the same owner, at the same tick range bytes32 salt; } struct ModifyLiquidityState { bool flippedLower; uint128 liquidityGrossAfterLower; bool flippedUpper; uint128 liquidityGrossAfterUpper; } /// @notice Effect changes to a position in a pool /// @dev PoolManager checks that the pool is initialized before calling /// @param params the position details and the change to the position's liquidity to effect /// @return delta the deltas of the token balances of the pool, from the liquidity change /// @return feeDelta the fees generated by the liquidity range function modifyLiquidity(State storage self, ModifyLiquidityParams memory params) internal returns (BalanceDelta delta, BalanceDelta feeDelta) { int128 liquidityDelta = params.liquidityDelta; int24 tickLower = params.tickLower; int24 tickUpper = params.tickUpper; checkTicks(tickLower, tickUpper); { ModifyLiquidityState memory state; // if we need to update the ticks, do it if (liquidityDelta != 0) { (state.flippedLower, state.liquidityGrossAfterLower) = updateTick(self, tickLower, liquidityDelta, false); (state.flippedUpper, state.liquidityGrossAfterUpper) = updateTick(self, tickUpper, liquidityDelta, true); // `>` and `>=` are logically equivalent here but `>=` is cheaper if (liquidityDelta >= 0) { uint128 maxLiquidityPerTick = tickSpacingToMaxLiquidityPerTick(params.tickSpacing); if (state.liquidityGrossAfterLower > maxLiquidityPerTick) { TickLiquidityOverflow.selector.revertWith(tickLower); } if (state.liquidityGrossAfterUpper > maxLiquidityPerTick) { TickLiquidityOverflow.selector.revertWith(tickUpper); } } if (state.flippedLower) { self.tickBitmap.flipTick(tickLower, params.tickSpacing); } if (state.flippedUpper) { self.tickBitmap.flipTick(tickUpper, params.tickSpacing); } } { (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) = getFeeGrowthInside(self, tickLower, tickUpper); Position.State storage position = self.positions.get(params.owner, tickLower, tickUpper, params.salt); (uint256 feesOwed0, uint256 feesOwed1) = position.update(liquidityDelta, feeGrowthInside0X128, feeGrowthInside1X128); // Fees earned from LPing are calculated, and returned feeDelta = toBalanceDelta(feesOwed0.toInt128(), feesOwed1.toInt128()); } // clear any tick data that is no longer needed if (liquidityDelta < 0) { if (state.flippedLower) { clearTick(self, tickLower); } if (state.flippedUpper) { clearTick(self, tickUpper); } } } if (liquidityDelta != 0) { Slot0 _slot0 = self.slot0; (int24 tick, uint160 sqrtPriceX96) = (_slot0.tick(), _slot0.sqrtPriceX96()); if (tick < tickLower) { // current tick is below the passed range; liquidity can only become in range by crossing from left to // right, when we'll need _more_ currency0 (it's becoming more valuable) so user must provide it delta = toBalanceDelta( SqrtPriceMath.getAmount0Delta( TickMath.getSqrtPriceAtTick(tickLower), TickMath.getSqrtPriceAtTick(tickUpper), liquidityDelta ).toInt128(), 0 ); } else if (tick < tickUpper) { delta = toBalanceDelta( SqrtPriceMath.getAmount0Delta(sqrtPriceX96, TickMath.getSqrtPriceAtTick(tickUpper), liquidityDelta) .toInt128(), SqrtPriceMath.getAmount1Delta(TickMath.getSqrtPriceAtTick(tickLower), sqrtPriceX96, liquidityDelta) .toInt128() ); self.liquidity = LiquidityMath.addDelta(self.liquidity, liquidityDelta); } else { // current tick is above the passed range; liquidity can only become in range by crossing from right to // left, when we'll need _more_ currency1 (it's becoming more valuable) so user must provide it delta = toBalanceDelta( 0, SqrtPriceMath.getAmount1Delta( TickMath.getSqrtPriceAtTick(tickLower), TickMath.getSqrtPriceAtTick(tickUpper), liquidityDelta ).toInt128() ); } } } // Tracks the state of a pool throughout a swap, and returns these values at the end of the swap struct SwapResult { // the current sqrt(price) uint160 sqrtPriceX96; // the tick associated with the current price int24 tick; // the current liquidity in range uint128 liquidity; } struct StepComputations { // the price at the beginning of the step uint160 sqrtPriceStartX96; // the next tick to swap to from the current tick in the swap direction int24 tickNext; // whether tickNext is initialized or not bool initialized; // sqrt(price) for the next tick (1/0) uint160 sqrtPriceNextX96; // how much is being swapped in in this step uint256 amountIn; // how much is being swapped out uint256 amountOut; // how much fee is being paid in uint256 feeAmount; // the global fee growth of the input token. updated in storage at the end of swap uint256 feeGrowthGlobalX128; } struct SwapParams { int256 amountSpecified; int24 tickSpacing; bool zeroForOne; uint160 sqrtPriceLimitX96; uint24 lpFeeOverride; } /// @notice Executes a swap against the state, and returns the amount deltas of the pool /// @dev PoolManager checks that the pool is initialized before calling function swap(State storage self, SwapParams memory params) internal returns (BalanceDelta swapDelta, uint256 amountToProtocol, uint24 swapFee, SwapResult memory result) { Slot0 slot0Start = self.slot0; bool zeroForOne = params.zeroForOne; uint256 protocolFee = zeroForOne ? slot0Start.protocolFee().getZeroForOneFee() : slot0Start.protocolFee().getOneForZeroFee(); // the amount remaining to be swapped in/out of the input/output asset. initially set to the amountSpecified int256 amountSpecifiedRemaining = params.amountSpecified; // the amount swapped out/in of the output/input asset. initially set to 0 int256 amountCalculated = 0; // initialize to the current sqrt(price) result.sqrtPriceX96 = slot0Start.sqrtPriceX96(); // initialize to the current tick result.tick = slot0Start.tick(); // initialize to the current liquidity result.liquidity = self.liquidity; // if the beforeSwap hook returned a valid fee override, use that as the LP fee, otherwise load from storage // lpFee, swapFee, and protocolFee are all in pips { uint24 lpFee = params.lpFeeOverride.isOverride() ? params.lpFeeOverride.removeOverrideFlagAndValidate() : slot0Start.lpFee(); swapFee = protocolFee == 0 ? lpFee : uint16(protocolFee).calculateSwapFee(lpFee); } // a swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee if (swapFee >= SwapMath.MAX_SWAP_FEE) { // if exactOutput if (params.amountSpecified > 0) { InvalidFeeForExactOut.selector.revertWith(); } } // swapFee is the pool's fee in pips (LP fee + protocol fee) // when the amount swapped is 0, there is no protocolFee applied and the fee amount paid to the protocol is set to 0 if (params.amountSpecified == 0) return (BalanceDeltaLibrary.ZERO_DELTA, 0, swapFee, result); if (zeroForOne) { if (params.sqrtPriceLimitX96 >= slot0Start.sqrtPriceX96()) { PriceLimitAlreadyExceeded.selector.revertWith(slot0Start.sqrtPriceX96(), params.sqrtPriceLimitX96); } // Swaps can never occur at MIN_TICK, only at MIN_TICK + 1, except at initialization of a pool // Under certain circumstances outlined below, the tick will preemptively reach MIN_TICK without swapping there if (params.sqrtPriceLimitX96 <= TickMath.MIN_SQRT_PRICE) { PriceLimitOutOfBounds.selector.revertWith(params.sqrtPriceLimitX96); } } else { if (params.sqrtPriceLimitX96 <= slot0Start.sqrtPriceX96()) { PriceLimitAlreadyExceeded.selector.revertWith(slot0Start.sqrtPriceX96(), params.sqrtPriceLimitX96); } if (params.sqrtPriceLimitX96 >= TickMath.MAX_SQRT_PRICE) { PriceLimitOutOfBounds.selector.revertWith(params.sqrtPriceLimitX96); } } StepComputations memory step; step.feeGrowthGlobalX128 = zeroForOne ? self.feeGrowthGlobal0X128 : self.feeGrowthGlobal1X128; // continue swapping as long as we haven't used the entire input/output and haven't reached the price limit while (!(amountSpecifiedRemaining == 0 || result.sqrtPriceX96 == params.sqrtPriceLimitX96)) { step.sqrtPriceStartX96 = result.sqrtPriceX96; (step.tickNext, step.initialized) = self.tickBitmap.nextInitializedTickWithinOneWord(result.tick, params.tickSpacing, zeroForOne); // ensure that we do not overshoot the min/max tick, as the tick bitmap is not aware of these bounds if (step.tickNext <= TickMath.MIN_TICK) { step.tickNext = TickMath.MIN_TICK; } if (step.tickNext >= TickMath.MAX_TICK) { step.tickNext = TickMath.MAX_TICK; } // get the price for the next tick step.sqrtPriceNextX96 = TickMath.getSqrtPriceAtTick(step.tickNext); // compute values to swap to the target tick, price limit, or point where input/output amount is exhausted (result.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep( result.sqrtPriceX96, SwapMath.getSqrtPriceTarget(zeroForOne, step.sqrtPriceNextX96, params.sqrtPriceLimitX96), result.liquidity, amountSpecifiedRemaining, swapFee ); // if exactOutput if (params.amountSpecified > 0) { unchecked { amountSpecifiedRemaining -= step.amountOut.toInt256(); } amountCalculated -= (step.amountIn + step.feeAmount).toInt256(); } else { // safe because we test that amountSpecified > amountIn + feeAmount in SwapMath unchecked { amountSpecifiedRemaining += (step.amountIn + step.feeAmount).toInt256(); } amountCalculated += step.amountOut.toInt256(); } // if the protocol fee is on, calculate how much is owed, decrement feeAmount, and increment protocolFee if (protocolFee > 0) { unchecked { // step.amountIn does not include the swap fee, as it's already been taken from it, // so add it back to get the total amountIn and use that to calculate the amount of fees owed to the protocol // cannot overflow due to limits on the size of protocolFee and params.amountSpecified // this rounds down to favor LPs over the protocol uint256 delta = (swapFee == protocolFee) ? step.feeAmount // lp fee is 0, so the entire fee is owed to the protocol instead : (step.amountIn + step.feeAmount) * protocolFee / ProtocolFeeLibrary.PIPS_DENOMINATOR; // subtract it from the total fee and add it to the protocol fee step.feeAmount -= delta; amountToProtocol += delta; } } // update global fee tracker if (result.liquidity > 0) { unchecked { // FullMath.mulDiv isn't needed as the numerator can't overflow uint256 since tokens have a max supply of type(uint128).max step.feeGrowthGlobalX128 += UnsafeMath.simpleMulDiv(step.feeAmount, FixedPoint128.Q128, result.liquidity); } } // Shift tick if we reached the next price, and preemptively decrement for zeroForOne swaps to tickNext - 1. // If the swap doesn't continue (if amountRemaining == 0 or sqrtPriceLimit is met), slot0.tick will be 1 less // than getTickAtSqrtPrice(slot0.sqrtPrice). This doesn't affect swaps, but donation calls should verify both // price and tick to reward the correct LPs. if (result.sqrtPriceX96 == step.sqrtPriceNextX96) { // if the tick is initialized, run the tick transition if (step.initialized) { (uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = zeroForOne ? (step.feeGrowthGlobalX128, self.feeGrowthGlobal1X128) : (self.feeGrowthGlobal0X128, step.feeGrowthGlobalX128); int128 liquidityNet = Pool.crossTick(self, step.tickNext, feeGrowthGlobal0X128, feeGrowthGlobal1X128); // if we're moving leftward, we interpret liquidityNet as the opposite sign // safe because liquidityNet cannot be type(int128).min unchecked { if (zeroForOne) liquidityNet = -liquidityNet; } result.liquidity = LiquidityMath.addDelta(result.liquidity, liquidityNet); } unchecked { result.tick = zeroForOne ? step.tickNext - 1 : step.tickNext; } } else if (result.sqrtPriceX96 != step.sqrtPriceStartX96) { // recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved result.tick = TickMath.getTickAtSqrtPrice(result.sqrtPriceX96); } } self.slot0 = slot0Start.setTick(result.tick).setSqrtPriceX96(result.sqrtPriceX96); // update liquidity if it changed if (self.liquidity != result.liquidity) self.liquidity = result.liquidity; // update fee growth global if (!zeroForOne) { self.feeGrowthGlobal1X128 = step.feeGrowthGlobalX128; } else { self.feeGrowthGlobal0X128 = step.feeGrowthGlobalX128; } unchecked { // "if currency1 is specified" if (zeroForOne != (params.amountSpecified < 0)) { swapDelta = toBalanceDelta( amountCalculated.toInt128(), (params.amountSpecified - amountSpecifiedRemaining).toInt128() ); } else { swapDelta = toBalanceDelta( (params.amountSpecified - amountSpecifiedRemaining).toInt128(), amountCalculated.toInt128() ); } } } /// @notice Donates the given amount of currency0 and currency1 to the pool function donate(State storage state, uint256 amount0, uint256 amount1) internal returns (BalanceDelta delta) { uint128 liquidity = state.liquidity; if (liquidity == 0) NoLiquidityToReceiveFees.selector.revertWith(); unchecked { // negation safe as amount0 and amount1 are always positive delta = toBalanceDelta(-(amount0.toInt128()), -(amount1.toInt128())); // FullMath.mulDiv is unnecessary because the numerator is bounded by type(int128).max * Q128, which is less than type(uint256).max if (amount0 > 0) { state.feeGrowthGlobal0X128 += UnsafeMath.simpleMulDiv(amount0, FixedPoint128.Q128, liquidity); } if (amount1 > 0) { state.feeGrowthGlobal1X128 += UnsafeMath.simpleMulDiv(amount1, FixedPoint128.Q128, liquidity); } } } /// @notice Retrieves fee growth data /// @param self The Pool state struct /// @param tickLower The lower tick boundary of the position /// @param tickUpper The upper tick boundary of the position /// @return feeGrowthInside0X128 The all-time fee growth in token0, per unit of liquidity, inside the position's tick boundaries /// @return feeGrowthInside1X128 The all-time fee growth in token1, per unit of liquidity, inside the position's tick boundaries function getFeeGrowthInside(State storage self, int24 tickLower, int24 tickUpper) internal view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) { TickInfo storage lower = self.ticks[tickLower]; TickInfo storage upper = self.ticks[tickUpper]; int24 tickCurrent = self.slot0.tick(); unchecked { if (tickCurrent < tickLower) { feeGrowthInside0X128 = lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128; feeGrowthInside1X128 = lower.feeGrowthOutside1X128 - upper.feeGrowthOutside1X128; } else if (tickCurrent >= tickUpper) { feeGrowthInside0X128 = upper.feeGrowthOutside0X128 - lower.feeGrowthOutside0X128; feeGrowthInside1X128 = upper.feeGrowthOutside1X128 - lower.feeGrowthOutside1X128; } else { feeGrowthInside0X128 = self.feeGrowthGlobal0X128 - lower.feeGrowthOutside0X128 - upper.feeGrowthOutside0X128; feeGrowthInside1X128 = self.feeGrowthGlobal1X128 - lower.feeGrowthOutside1X128 - upper.feeGrowthOutside1X128; } } } /// @notice Updates a tick and returns true if the tick was flipped from initialized to uninitialized, or vice versa /// @param self The mapping containing all tick information for initialized ticks /// @param tick The tick that will be updated /// @param liquidityDelta A new amount of liquidity to be added (subtracted) when tick is crossed from left to right (right to left) /// @param upper true for updating a position's upper tick, or false for updating a position's lower tick /// @return flipped Whether the tick was flipped from initialized to uninitialized, or vice versa /// @return liquidityGrossAfter The total amount of liquidity for all positions that references the tick after the update function updateTick(State storage self, int24 tick, int128 liquidityDelta, bool upper) internal returns (bool flipped, uint128 liquidityGrossAfter) { TickInfo storage info = self.ticks[tick]; uint128 liquidityGrossBefore = info.liquidityGross; int128 liquidityNetBefore = info.liquidityNet; liquidityGrossAfter = LiquidityMath.addDelta(liquidityGrossBefore, liquidityDelta); flipped = (liquidityGrossAfter == 0) != (liquidityGrossBefore == 0); if (liquidityGrossBefore == 0) { // by convention, we assume that all growth before a tick was initialized happened _below_ the tick if (tick <= self.slot0.tick()) { info.feeGrowthOutside0X128 = self.feeGrowthGlobal0X128; info.feeGrowthOutside1X128 = self.feeGrowthGlobal1X128; } } // when the lower (upper) tick is crossed left to right, liquidity must be added (removed) // when the lower (upper) tick is crossed right to left, liquidity must be removed (added) int128 liquidityNet = upper ? liquidityNetBefore - liquidityDelta : liquidityNetBefore + liquidityDelta; assembly ("memory-safe") { // liquidityGrossAfter and liquidityNet are packed in the first slot of `info` // So we can store them with a single sstore by packing them ourselves first sstore( info.slot, // bitwise OR to pack liquidityGrossAfter and liquidityNet or( // Put liquidityGrossAfter in the lower bits, clearing out the upper bits and(liquidityGrossAfter, 0xffffffffffffffffffffffffffffffff), // Shift liquidityNet to put it in the upper bits (no need for signextend since we're shifting left) shl(128, liquidityNet) ) ) } } /// @notice Derives max liquidity per tick from given tick spacing /// @dev Executed when adding liquidity /// @param tickSpacing The amount of required tick separation, realized in multiples of `tickSpacing` /// e.g., a tickSpacing of 3 requires ticks to be initialized every 3rd tick i.e., ..., -6, -3, 0, 3, 6, ... /// @return result The max liquidity per tick function tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) internal pure returns (uint128 result) { // Equivalent to: // int24 minTick = (TickMath.MIN_TICK / tickSpacing); // if (TickMath.MIN_TICK % tickSpacing != 0) minTick--; // int24 maxTick = (TickMath.MAX_TICK / tickSpacing); // uint24 numTicks = maxTick - minTick + 1; // return type(uint128).max / numTicks; int24 MAX_TICK = TickMath.MAX_TICK; int24 MIN_TICK = TickMath.MIN_TICK; // tick spacing will never be 0 since TickMath.MIN_TICK_SPACING is 1 assembly ("memory-safe") { tickSpacing := signextend(2, tickSpacing) let minTick := sub(sdiv(MIN_TICK, tickSpacing), slt(smod(MIN_TICK, tickSpacing), 0)) let maxTick := sdiv(MAX_TICK, tickSpacing) let numTicks := add(sub(maxTick, minTick), 1) result := div(sub(shl(128, 1), 1), numTicks) } } /// @notice Reverts if the given pool has not been initialized function checkPoolInitialized(State storage self) internal view { if (self.slot0.sqrtPriceX96() == 0) PoolNotInitialized.selector.revertWith(); } /// @notice Clears tick data /// @param self The mapping containing all initialized tick information for initialized ticks /// @param tick The tick that will be cleared function clearTick(State storage self, int24 tick) internal { delete self.ticks[tick]; } /// @notice Transitions to next tick as needed by price movement /// @param self The Pool state struct /// @param tick The destination tick of the transition /// @param feeGrowthGlobal0X128 The all-time global fee growth, per unit of liquidity, in token0 /// @param feeGrowthGlobal1X128 The all-time global fee growth, per unit of liquidity, in token1 /// @return liquidityNet The amount of liquidity added (subtracted) when tick is crossed from left to right (right to left) function crossTick(State storage self, int24 tick, uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) internal returns (int128 liquidityNet) { unchecked { TickInfo storage info = self.ticks[tick]; info.feeGrowthOutside0X128 = feeGrowthGlobal0X128 - info.feeGrowthOutside0X128; info.feeGrowthOutside1X128 = feeGrowthGlobal1X128 - info.feeGrowthOutside1X128; liquidityNet = info.liquidityNet; } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import {FullMath} from "./FullMath.sol"; import {FixedPoint128} from "./FixedPoint128.sol"; import {LiquidityMath} from "./LiquidityMath.sol"; import {CustomRevert} from "./CustomRevert.sol"; /// @title Position /// @notice Positions represent an owner address' liquidity between a lower and upper tick boundary /// @dev Positions store additional state for tracking fees owed to the position library Position { using CustomRevert for bytes4; /// @notice Cannot update a position with no liquidity error CannotUpdateEmptyPosition(); // info stored for each user's position struct State { // the amount of liquidity owned by this position uint128 liquidity; // fee growth per unit of liquidity as of the last update to liquidity or fees owed uint256 feeGrowthInside0LastX128; uint256 feeGrowthInside1LastX128; } /// @notice Returns the State struct of a position, given an owner and position boundaries /// @param self The mapping containing all user positions /// @param owner The address of the position owner /// @param tickLower The lower tick boundary of the position /// @param tickUpper The upper tick boundary of the position /// @param salt A unique value to differentiate between multiple positions in the same range /// @return position The position info struct of the given owners' position function get(mapping(bytes32 => State) storage self, address owner, int24 tickLower, int24 tickUpper, bytes32 salt) internal view returns (State storage position) { bytes32 positionKey = calculatePositionKey(owner, tickLower, tickUpper, salt); position = self[positionKey]; } /// @notice A helper function to calculate the position key /// @param owner The address of the position owner /// @param tickLower the lower tick boundary of the position /// @param tickUpper the upper tick boundary of the position /// @param salt A unique value to differentiate between multiple positions in the same range, by the same owner. Passed in by the caller. function calculatePositionKey(address owner, int24 tickLower, int24 tickUpper, bytes32 salt) internal pure returns (bytes32 positionKey) { // positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt)) assembly ("memory-safe") { let fmp := mload(0x40) mstore(add(fmp, 0x26), salt) // [0x26, 0x46) mstore(add(fmp, 0x06), tickUpper) // [0x23, 0x26) mstore(add(fmp, 0x03), tickLower) // [0x20, 0x23) mstore(fmp, owner) // [0x0c, 0x20) positionKey := keccak256(add(fmp, 0x0c), 0x3a) // len is 58 bytes // now clean the memory we used mstore(add(fmp, 0x40), 0) // fmp+0x40 held salt mstore(add(fmp, 0x20), 0) // fmp+0x20 held tickLower, tickUpper, salt mstore(fmp, 0) // fmp held owner } } /// @notice Credits accumulated fees to a user's position /// @param self The individual position to update /// @param liquidityDelta The change in pool liquidity as a result of the position update /// @param feeGrowthInside0X128 The all-time fee growth in currency0, per unit of liquidity, inside the position's tick boundaries /// @param feeGrowthInside1X128 The all-time fee growth in currency1, per unit of liquidity, inside the position's tick boundaries /// @return feesOwed0 The amount of currency0 owed to the position owner /// @return feesOwed1 The amount of currency1 owed to the position owner function update( State storage self, int128 liquidityDelta, uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128 ) internal returns (uint256 feesOwed0, uint256 feesOwed1) { uint128 liquidity = self.liquidity; if (liquidityDelta == 0) { // disallow pokes for 0 liquidity positions if (liquidity == 0) CannotUpdateEmptyPosition.selector.revertWith(); } else { self.liquidity = LiquidityMath.addDelta(liquidity, liquidityDelta); } // calculate accumulated fees. overflow in the subtraction of fee growth is expected unchecked { feesOwed0 = FullMath.mulDiv(feeGrowthInside0X128 - self.feeGrowthInside0LastX128, liquidity, FixedPoint128.Q128); feesOwed1 = FullMath.mulDiv(feeGrowthInside1X128 - self.feeGrowthInside1LastX128, liquidity, FixedPoint128.Q128); } // update the position self.feeGrowthInside0LastX128 = feeGrowthInside0X128; self.feeGrowthInside1LastX128 = feeGrowthInside1X128; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice library of functions related to protocol fees library ProtocolFeeLibrary { /// @notice Max protocol fee is 0.1% (1000 pips) /// @dev Increasing these values could lead to overflow in Pool.swap uint16 public constant MAX_PROTOCOL_FEE = 1000; /// @notice Thresholds used for optimized bounds checks on protocol fees uint24 internal constant FEE_0_THRESHOLD = 1001; uint24 internal constant FEE_1_THRESHOLD = 1001 << 12; /// @notice the protocol fee is represented in hundredths of a bip uint256 internal constant PIPS_DENOMINATOR = 1_000_000; function getZeroForOneFee(uint24 self) internal pure returns (uint16) { return uint16(self & 0xfff); } function getOneForZeroFee(uint24 self) internal pure returns (uint16) { return uint16(self >> 12); } function isValidProtocolFee(uint24 self) internal pure returns (bool valid) { // Equivalent to: getZeroForOneFee(self) <= MAX_PROTOCOL_FEE && getOneForZeroFee(self) <= MAX_PROTOCOL_FEE assembly ("memory-safe") { let isZeroForOneFeeOk := lt(and(self, 0xfff), FEE_0_THRESHOLD) let isOneForZeroFeeOk := lt(and(self, 0xfff000), FEE_1_THRESHOLD) valid := and(isZeroForOneFeeOk, isOneForZeroFeeOk) } } // The protocol fee is taken from the input amount first and then the LP fee is taken from the remaining // The swap fee is capped at 100% // Equivalent to protocolFee + lpFee(1_000_000 - protocolFee) / 1_000_000 (rounded up) /// @dev here `self` is just a single direction's protocol fee, not a packed type of 2 protocol fees function calculateSwapFee(uint16 self, uint24 lpFee) internal pure returns (uint24 swapFee) { // protocolFee + lpFee - (protocolFee * lpFee / 1_000_000) assembly ("memory-safe") { self := and(self, 0xfff) lpFee := and(lpFee, 0xffffff) let numerator := mul(self, lpFee) swapFee := sub(add(self, lpFee), div(numerator, PIPS_DENOMINATOR)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {CustomRevert} from "./CustomRevert.sol"; /// @title Safe casting methods /// @notice Contains methods for safely casting between types library SafeCast { using CustomRevert for bytes4; error SafeCastOverflow(); /// @notice Cast a uint256 to a uint160, revert on overflow /// @param x The uint256 to be downcasted /// @return y The downcasted integer, now type uint160 function toUint160(uint256 x) internal pure returns (uint160 y) { y = uint160(x); if (y != x) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a uint256 to a uint128, revert on overflow /// @param x The uint256 to be downcasted /// @return y The downcasted integer, now type uint128 function toUint128(uint256 x) internal pure returns (uint128 y) { y = uint128(x); if (x != y) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a int128 to a uint128, revert on overflow or underflow /// @param x The int128 to be casted /// @return y The casted integer, now type uint128 function toUint128(int128 x) internal pure returns (uint128 y) { if (x < 0) SafeCastOverflow.selector.revertWith(); y = uint128(x); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param x The int256 to be downcasted /// @return y The downcasted integer, now type int128 function toInt128(int256 x) internal pure returns (int128 y) { y = int128(x); if (y != x) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a uint256 to a int256, revert on overflow /// @param x The uint256 to be casted /// @return y The casted integer, now type int256 function toInt256(uint256 x) internal pure returns (int256 y) { y = int256(x); if (y < 0) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a uint256 to a int128, revert on overflow /// @param x The uint256 to be downcasted /// @return The downcasted integer, now type int128 function toInt128(uint256 x) internal pure returns (int128) { if (x >= 1 << 127) SafeCastOverflow.selector.revertWith(); return int128(int256(x)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {SafeCast} from "./SafeCast.sol"; import {FullMath} from "./FullMath.sol"; import {UnsafeMath} from "./UnsafeMath.sol"; import {FixedPoint96} from "./FixedPoint96.sol"; /// @title Functions based on Q64.96 sqrt price and liquidity /// @notice Contains the math that uses square root of price as a Q64.96 and liquidity to compute deltas library SqrtPriceMath { using SafeCast for uint256; error InvalidPriceOrLiquidity(); error InvalidPrice(); error NotEnoughLiquidity(); error PriceOverflow(); /// @notice Gets the next sqrt price given a delta of currency0 /// @dev Always rounds up, because in the exact output case (increasing price) we need to move the price at least /// far enough to get the desired output amount, and in the exact input case (decreasing price) we need to move the /// price less in order to not send too much output. /// The most precise formula for this is liquidity * sqrtPX96 / (liquidity +- amount * sqrtPX96), /// if this is impossible because of overflow, we calculate liquidity / (liquidity / sqrtPX96 +- amount). /// @param sqrtPX96 The starting price, i.e. before accounting for the currency0 delta /// @param liquidity The amount of usable liquidity /// @param amount How much of currency0 to add or remove from virtual reserves /// @param add Whether to add or remove the amount of currency0 /// @return The price after adding or removing amount, depending on add function getNextSqrtPriceFromAmount0RoundingUp(uint160 sqrtPX96, uint128 liquidity, uint256 amount, bool add) internal pure returns (uint160) { // we short circuit amount == 0 because the result is otherwise not guaranteed to equal the input price if (amount == 0) return sqrtPX96; uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; if (add) { unchecked { uint256 product = amount * sqrtPX96; if (product / amount == sqrtPX96) { uint256 denominator = numerator1 + product; if (denominator >= numerator1) { // always fits in 160 bits return uint160(FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator)); } } } // denominator is checked for overflow return uint160(UnsafeMath.divRoundingUp(numerator1, (numerator1 / sqrtPX96) + amount)); } else { unchecked { uint256 product = amount * sqrtPX96; // if the product overflows, we know the denominator underflows // in addition, we must check that the denominator does not underflow // equivalent: if (product / amount != sqrtPX96 || numerator1 <= product) revert PriceOverflow(); assembly ("memory-safe") { if iszero( and( eq(div(product, amount), and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff)), gt(numerator1, product) ) ) { mstore(0, 0xf5c787f1) // selector for PriceOverflow() revert(0x1c, 0x04) } } uint256 denominator = numerator1 - product; return FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator).toUint160(); } } } /// @notice Gets the next sqrt price given a delta of currency1 /// @dev Always rounds down, because in the exact output case (decreasing price) we need to move the price at least /// far enough to get the desired output amount, and in the exact input case (increasing price) we need to move the /// price less in order to not send too much output. /// The formula we compute is within <1 wei of the lossless version: sqrtPX96 +- amount / liquidity /// @param sqrtPX96 The starting price, i.e., before accounting for the currency1 delta /// @param liquidity The amount of usable liquidity /// @param amount How much of currency1 to add, or remove, from virtual reserves /// @param add Whether to add, or remove, the amount of currency1 /// @return The price after adding or removing `amount` function getNextSqrtPriceFromAmount1RoundingDown(uint160 sqrtPX96, uint128 liquidity, uint256 amount, bool add) internal pure returns (uint160) { // if we're adding (subtracting), rounding down requires rounding the quotient down (up) // in both cases, avoid a mulDiv for most inputs if (add) { uint256 quotient = ( amount <= type(uint160).max ? (amount << FixedPoint96.RESOLUTION) / liquidity : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity) ); return (uint256(sqrtPX96) + quotient).toUint160(); } else { uint256 quotient = ( amount <= type(uint160).max ? UnsafeMath.divRoundingUp(amount << FixedPoint96.RESOLUTION, liquidity) : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity) ); // equivalent: if (sqrtPX96 <= quotient) revert NotEnoughLiquidity(); assembly ("memory-safe") { if iszero(gt(and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff), quotient)) { mstore(0, 0x4323a555) // selector for NotEnoughLiquidity() revert(0x1c, 0x04) } } // always fits 160 bits unchecked { return uint160(sqrtPX96 - quotient); } } } /// @notice Gets the next sqrt price given an input amount of currency0 or currency1 /// @dev Throws if price or liquidity are 0, or if the next price is out of bounds /// @param sqrtPX96 The starting price, i.e., before accounting for the input amount /// @param liquidity The amount of usable liquidity /// @param amountIn How much of currency0, or currency1, is being swapped in /// @param zeroForOne Whether the amount in is currency0 or currency1 /// @return uint160 The price after adding the input amount to currency0 or currency1 function getNextSqrtPriceFromInput(uint160 sqrtPX96, uint128 liquidity, uint256 amountIn, bool zeroForOne) internal pure returns (uint160) { // equivalent: if (sqrtPX96 == 0 || liquidity == 0) revert InvalidPriceOrLiquidity(); assembly ("memory-safe") { if or( iszero(and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff)), iszero(and(liquidity, 0xffffffffffffffffffffffffffffffff)) ) { mstore(0, 0x4f2461b8) // selector for InvalidPriceOrLiquidity() revert(0x1c, 0x04) } } // round to make sure that we don't pass the target price return zeroForOne ? getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountIn, true) : getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountIn, true); } /// @notice Gets the next sqrt price given an output amount of currency0 or currency1 /// @dev Throws if price or liquidity are 0 or the next price is out of bounds /// @param sqrtPX96 The starting price before accounting for the output amount /// @param liquidity The amount of usable liquidity /// @param amountOut How much of currency0, or currency1, is being swapped out /// @param zeroForOne Whether the amount out is currency1 or currency0 /// @return uint160 The price after removing the output amount of currency0 or currency1 function getNextSqrtPriceFromOutput(uint160 sqrtPX96, uint128 liquidity, uint256 amountOut, bool zeroForOne) internal pure returns (uint160) { // equivalent: if (sqrtPX96 == 0 || liquidity == 0) revert InvalidPriceOrLiquidity(); assembly ("memory-safe") { if or( iszero(and(sqrtPX96, 0xffffffffffffffffffffffffffffffffffffffff)), iszero(and(liquidity, 0xffffffffffffffffffffffffffffffff)) ) { mstore(0, 0x4f2461b8) // selector for InvalidPriceOrLiquidity() revert(0x1c, 0x04) } } // round to make sure that we pass the target price return zeroForOne ? getNextSqrtPriceFromAmount1RoundingDown(sqrtPX96, liquidity, amountOut, false) : getNextSqrtPriceFromAmount0RoundingUp(sqrtPX96, liquidity, amountOut, false); } /// @notice Gets the amount0 delta between two prices /// @dev Calculates liquidity / sqrt(lower) - liquidity / sqrt(upper), /// i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower)) /// @param sqrtPriceAX96 A sqrt price /// @param sqrtPriceBX96 Another sqrt price /// @param liquidity The amount of usable liquidity /// @param roundUp Whether to round the amount up or down /// @return uint256 Amount of currency0 required to cover a position of size liquidity between the two passed prices function getAmount0Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity, bool roundUp) internal pure returns (uint256) { unchecked { if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); // equivalent: if (sqrtPriceAX96 == 0) revert InvalidPrice(); assembly ("memory-safe") { if iszero(and(sqrtPriceAX96, 0xffffffffffffffffffffffffffffffffffffffff)) { mstore(0, 0x00bfc921) // selector for InvalidPrice() revert(0x1c, 0x04) } } uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; uint256 numerator2 = sqrtPriceBX96 - sqrtPriceAX96; return roundUp ? UnsafeMath.divRoundingUp(FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtPriceBX96), sqrtPriceAX96) : FullMath.mulDiv(numerator1, numerator2, sqrtPriceBX96) / sqrtPriceAX96; } } /// @notice Equivalent to: `a >= b ? a - b : b - a` function absDiff(uint160 a, uint160 b) internal pure returns (uint256 res) { assembly ("memory-safe") { let diff := sub(and(a, 0xffffffffffffffffffffffffffffffffffffffff), and(b, 0xffffffffffffffffffffffffffffffffffffffff)) // mask = 0 if a >= b else -1 (all 1s) let mask := sar(255, diff) // if a >= b, res = a - b = 0 ^ (a - b) // if a < b, res = b - a = ~~(b - a) = ~(-(b - a) - 1) = ~(a - b - 1) = (-1) ^ (a - b - 1) // either way, res = mask ^ (a - b + mask) res := xor(mask, add(mask, diff)) } } /// @notice Gets the amount1 delta between two prices /// @dev Calculates liquidity * (sqrt(upper) - sqrt(lower)) /// @param sqrtPriceAX96 A sqrt price /// @param sqrtPriceBX96 Another sqrt price /// @param liquidity The amount of usable liquidity /// @param roundUp Whether to round the amount up, or down /// @return amount1 Amount of currency1 required to cover a position of size liquidity between the two passed prices function getAmount1Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint128 liquidity, bool roundUp) internal pure returns (uint256 amount1) { uint256 numerator = absDiff(sqrtPriceAX96, sqrtPriceBX96); uint256 denominator = FixedPoint96.Q96; uint256 _liquidity = uint256(liquidity); /** * Equivalent to: * amount1 = roundUp * ? FullMath.mulDivRoundingUp(liquidity, sqrtPriceBX96 - sqrtPriceAX96, FixedPoint96.Q96) * : FullMath.mulDiv(liquidity, sqrtPriceBX96 - sqrtPriceAX96, FixedPoint96.Q96); * Cannot overflow because `type(uint128).max * type(uint160).max >> 96 < (1 << 192)`. */ amount1 = FullMath.mulDiv(_liquidity, numerator, denominator); assembly ("memory-safe") { amount1 := add(amount1, and(gt(mulmod(_liquidity, numerator, denominator), 0), roundUp)) } } /// @notice Helper that gets signed currency0 delta /// @param sqrtPriceAX96 A sqrt price /// @param sqrtPriceBX96 Another sqrt price /// @param liquidity The change in liquidity for which to compute the amount0 delta /// @return int256 Amount of currency0 corresponding to the passed liquidityDelta between the two prices function getAmount0Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, int128 liquidity) internal pure returns (int256) { unchecked { return liquidity < 0 ? getAmount0Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(-liquidity), false).toInt256() : -getAmount0Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(liquidity), true).toInt256(); } } /// @notice Helper that gets signed currency1 delta /// @param sqrtPriceAX96 A sqrt price /// @param sqrtPriceBX96 Another sqrt price /// @param liquidity The change in liquidity for which to compute the amount1 delta /// @return int256 Amount of currency1 corresponding to the passed liquidityDelta between the two prices function getAmount1Delta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, int128 liquidity) internal pure returns (int256) { unchecked { return liquidity < 0 ? getAmount1Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(-liquidity), false).toInt256() : -getAmount1Delta(sqrtPriceAX96, sqrtPriceBX96, uint128(liquidity), true).toInt256(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolId} from "../types/PoolId.sol"; import {IPoolManager} from "../interfaces/IPoolManager.sol"; import {Position} from "./Position.sol"; /// @notice A helper library to provide state getters that use extsload library StateLibrary { /// @notice index of pools mapping in the PoolManager bytes32 public constant POOLS_SLOT = bytes32(uint256(6)); /// @notice index of feeGrowthGlobal0X128 in Pool.State uint256 public constant FEE_GROWTH_GLOBAL0_OFFSET = 1; // feeGrowthGlobal1X128 offset in Pool.State = 2 /// @notice index of liquidity in Pool.State uint256 public constant LIQUIDITY_OFFSET = 3; /// @notice index of TicksInfo mapping in Pool.State: mapping(int24 => TickInfo) ticks; uint256 public constant TICKS_OFFSET = 4; /// @notice index of tickBitmap mapping in Pool.State uint256 public constant TICK_BITMAP_OFFSET = 5; /// @notice index of Position.State mapping in Pool.State: mapping(bytes32 => Position.State) positions; uint256 public constant POSITIONS_OFFSET = 6; /** * @notice Get Slot0 of the pool: sqrtPriceX96, tick, protocolFee, lpFee * @dev Corresponds to pools[poolId].slot0 * @param manager The pool manager contract. * @param poolId The ID of the pool. * @return sqrtPriceX96 The square root of the price of the pool, in Q96 precision. * @return tick The current tick of the pool. * @return protocolFee The protocol fee of the pool. * @return lpFee The swap fee of the pool. */ function getSlot0(IPoolManager manager, PoolId poolId) internal view returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); bytes32 data = manager.extsload(stateSlot); // 24 bits |24bits|24bits |24 bits|160 bits // 0x000000 |000bb8|000000 |ffff75 |0000000000000000fe3aa841ba359daa0ea9eff7 // ---------- | fee |protocolfee | tick | sqrtPriceX96 assembly ("memory-safe") { // bottom 160 bits of data sqrtPriceX96 := and(data, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) // next 24 bits of data tick := signextend(2, shr(160, data)) // next 24 bits of data protocolFee := and(shr(184, data), 0xFFFFFF) // last 24 bits of data lpFee := and(shr(208, data), 0xFFFFFF) } } /** * @notice Retrieves the tick information of a pool at a specific tick. * @dev Corresponds to pools[poolId].ticks[tick] * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tick The tick to retrieve information for. * @return liquidityGross The total position liquidity that references this tick * @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left) * @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) * @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) */ function getTickInfo(IPoolManager manager, PoolId poolId, int24 tick) internal view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128 ) { bytes32 slot = _getTickInfoSlot(poolId, tick); // read all 3 words of the TickInfo struct bytes32[] memory data = manager.extsload(slot, 3); assembly ("memory-safe") { let firstWord := mload(add(data, 32)) liquidityNet := sar(128, firstWord) liquidityGross := and(firstWord, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) feeGrowthOutside0X128 := mload(add(data, 64)) feeGrowthOutside1X128 := mload(add(data, 96)) } } /** * @notice Retrieves the liquidity information of a pool at a specific tick. * @dev Corresponds to pools[poolId].ticks[tick].liquidityGross and pools[poolId].ticks[tick].liquidityNet. A more gas efficient version of getTickInfo * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tick The tick to retrieve liquidity for. * @return liquidityGross The total position liquidity that references this tick * @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left) */ function getTickLiquidity(IPoolManager manager, PoolId poolId, int24 tick) internal view returns (uint128 liquidityGross, int128 liquidityNet) { bytes32 slot = _getTickInfoSlot(poolId, tick); bytes32 value = manager.extsload(slot); assembly ("memory-safe") { liquidityNet := sar(128, value) liquidityGross := and(value, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) } } /** * @notice Retrieves the fee growth outside a tick range of a pool * @dev Corresponds to pools[poolId].ticks[tick].feeGrowthOutside0X128 and pools[poolId].ticks[tick].feeGrowthOutside1X128. A more gas efficient version of getTickInfo * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tick The tick to retrieve fee growth for. * @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) * @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) */ function getTickFeeGrowthOutside(IPoolManager manager, PoolId poolId, int24 tick) internal view returns (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128) { bytes32 slot = _getTickInfoSlot(poolId, tick); // offset by 1 word, since the first word is liquidityGross + liquidityNet bytes32[] memory data = manager.extsload(bytes32(uint256(slot) + 1), 2); assembly ("memory-safe") { feeGrowthOutside0X128 := mload(add(data, 32)) feeGrowthOutside1X128 := mload(add(data, 64)) } } /** * @notice Retrieves the global fee growth of a pool. * @dev Corresponds to pools[poolId].feeGrowthGlobal0X128 and pools[poolId].feeGrowthGlobal1X128 * @param manager The pool manager contract. * @param poolId The ID of the pool. * @return feeGrowthGlobal0 The global fee growth for token0. * @return feeGrowthGlobal1 The global fee growth for token1. * @dev Note that feeGrowthGlobal can be artificially inflated * For pools with a single liquidity position, actors can donate to themselves to freely inflate feeGrowthGlobal * atomically donating and collecting fees in the same unlockCallback may make the inflated value more extreme */ function getFeeGrowthGlobals(IPoolManager manager, PoolId poolId) internal view returns (uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State, `uint256 feeGrowthGlobal0X128` bytes32 slot_feeGrowthGlobal0X128 = bytes32(uint256(stateSlot) + FEE_GROWTH_GLOBAL0_OFFSET); // read the 2 words of feeGrowthGlobal bytes32[] memory data = manager.extsload(slot_feeGrowthGlobal0X128, 2); assembly ("memory-safe") { feeGrowthGlobal0 := mload(add(data, 32)) feeGrowthGlobal1 := mload(add(data, 64)) } } /** * @notice Retrieves total the liquidity of a pool. * @dev Corresponds to pools[poolId].liquidity * @param manager The pool manager contract. * @param poolId The ID of the pool. * @return liquidity The liquidity of the pool. */ function getLiquidity(IPoolManager manager, PoolId poolId) internal view returns (uint128 liquidity) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State: `uint128 liquidity` bytes32 slot = bytes32(uint256(stateSlot) + LIQUIDITY_OFFSET); liquidity = uint128(uint256(manager.extsload(slot))); } /** * @notice Retrieves the tick bitmap of a pool at a specific tick. * @dev Corresponds to pools[poolId].tickBitmap[tick] * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tick The tick to retrieve the bitmap for. * @return tickBitmap The bitmap of the tick. */ function getTickBitmap(IPoolManager manager, PoolId poolId, int16 tick) internal view returns (uint256 tickBitmap) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State: `mapping(int16 => uint256) tickBitmap;` bytes32 tickBitmapMapping = bytes32(uint256(stateSlot) + TICK_BITMAP_OFFSET); // slot id of the mapping key: `pools[poolId].tickBitmap[tick] bytes32 slot = keccak256(abi.encodePacked(int256(tick), tickBitmapMapping)); tickBitmap = uint256(manager.extsload(slot)); } /** * @notice Retrieves the position information of a pool without needing to calculate the `positionId`. * @dev Corresponds to pools[poolId].positions[positionId] * @param poolId The ID of the pool. * @param owner The owner of the liquidity position. * @param tickLower The lower tick of the liquidity range. * @param tickUpper The upper tick of the liquidity range. * @param salt The bytes32 randomness to further distinguish position state. * @return liquidity The liquidity of the position. * @return feeGrowthInside0LastX128 The fee growth inside the position for token0. * @return feeGrowthInside1LastX128 The fee growth inside the position for token1. */ function getPositionInfo( IPoolManager manager, PoolId poolId, address owner, int24 tickLower, int24 tickUpper, bytes32 salt ) internal view returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128) { // positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt)) bytes32 positionKey = Position.calculatePositionKey(owner, tickLower, tickUpper, salt); (liquidity, feeGrowthInside0LastX128, feeGrowthInside1LastX128) = getPositionInfo(manager, poolId, positionKey); } /** * @notice Retrieves the position information of a pool at a specific position ID. * @dev Corresponds to pools[poolId].positions[positionId] * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param positionId The ID of the position. * @return liquidity The liquidity of the position. * @return feeGrowthInside0LastX128 The fee growth inside the position for token0. * @return feeGrowthInside1LastX128 The fee growth inside the position for token1. */ function getPositionInfo(IPoolManager manager, PoolId poolId, bytes32 positionId) internal view returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128) { bytes32 slot = _getPositionInfoSlot(poolId, positionId); // read all 3 words of the Position.State struct bytes32[] memory data = manager.extsload(slot, 3); assembly ("memory-safe") { liquidity := mload(add(data, 32)) feeGrowthInside0LastX128 := mload(add(data, 64)) feeGrowthInside1LastX128 := mload(add(data, 96)) } } /** * @notice Retrieves the liquidity of a position. * @dev Corresponds to pools[poolId].positions[positionId].liquidity. More gas efficient for just retrieiving liquidity as compared to getPositionInfo * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param positionId The ID of the position. * @return liquidity The liquidity of the position. */ function getPositionLiquidity(IPoolManager manager, PoolId poolId, bytes32 positionId) internal view returns (uint128 liquidity) { bytes32 slot = _getPositionInfoSlot(poolId, positionId); liquidity = uint128(uint256(manager.extsload(slot))); } /** * @notice Calculate the fee growth inside a tick range of a pool * @dev pools[poolId].feeGrowthInside0LastX128 in Position.State is cached and can become stale. This function will calculate the up to date feeGrowthInside * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tickLower The lower tick of the range. * @param tickUpper The upper tick of the range. * @return feeGrowthInside0X128 The fee growth inside the tick range for token0. * @return feeGrowthInside1X128 The fee growth inside the tick range for token1. */ function getFeeGrowthInside(IPoolManager manager, PoolId poolId, int24 tickLower, int24 tickUpper) internal view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) { (uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = getFeeGrowthGlobals(manager, poolId); (uint256 lowerFeeGrowthOutside0X128, uint256 lowerFeeGrowthOutside1X128) = getTickFeeGrowthOutside(manager, poolId, tickLower); (uint256 upperFeeGrowthOutside0X128, uint256 upperFeeGrowthOutside1X128) = getTickFeeGrowthOutside(manager, poolId, tickUpper); (, int24 tickCurrent,,) = getSlot0(manager, poolId); unchecked { if (tickCurrent < tickLower) { feeGrowthInside0X128 = lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128; feeGrowthInside1X128 = lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128; } else if (tickCurrent >= tickUpper) { feeGrowthInside0X128 = upperFeeGrowthOutside0X128 - lowerFeeGrowthOutside0X128; feeGrowthInside1X128 = upperFeeGrowthOutside1X128 - lowerFeeGrowthOutside1X128; } else { feeGrowthInside0X128 = feeGrowthGlobal0X128 - lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128; feeGrowthInside1X128 = feeGrowthGlobal1X128 - lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128; } } } function _getPoolStateSlot(PoolId poolId) internal pure returns (bytes32) { return keccak256(abi.encodePacked(PoolId.unwrap(poolId), POOLS_SLOT)); } function _getTickInfoSlot(PoolId poolId, int24 tick) internal pure returns (bytes32) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State: `mapping(int24 => TickInfo) ticks` bytes32 ticksMappingSlot = bytes32(uint256(stateSlot) + TICKS_OFFSET); // slot key of the tick key: `pools[poolId].ticks[tick] return keccak256(abi.encodePacked(int256(tick), ticksMappingSlot)); } function _getPositionInfoSlot(PoolId poolId, bytes32 positionId) internal pure returns (bytes32) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State: `mapping(bytes32 => Position.State) positions;` bytes32 positionMapping = bytes32(uint256(stateSlot) + POSITIONS_OFFSET); // slot of the mapping key: `pools[poolId].positions[positionId] return keccak256(abi.encodePacked(positionId, positionMapping)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {FullMath} from "./FullMath.sol"; import {SqrtPriceMath} from "./SqrtPriceMath.sol"; /// @title Computes the result of a swap within ticks /// @notice Contains methods for computing the result of a swap within a single tick price range, i.e., a single tick. library SwapMath { /// @notice the swap fee is represented in hundredths of a bip, so the max is 100% /// @dev the swap fee is the total fee on a swap, including both LP and Protocol fee uint256 internal constant MAX_SWAP_FEE = 1e6; /// @notice Computes the sqrt price target for the next swap step /// @param zeroForOne The direction of the swap, true for currency0 to currency1, false for currency1 to currency0 /// @param sqrtPriceNextX96 The Q64.96 sqrt price for the next initialized tick /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this value /// after the swap. If one for zero, the price cannot be greater than this value after the swap /// @return sqrtPriceTargetX96 The price target for the next swap step function getSqrtPriceTarget(bool zeroForOne, uint160 sqrtPriceNextX96, uint160 sqrtPriceLimitX96) internal pure returns (uint160 sqrtPriceTargetX96) { assembly ("memory-safe") { // a flag to toggle between sqrtPriceNextX96 and sqrtPriceLimitX96 // when zeroForOne == true, nextOrLimit reduces to sqrtPriceNextX96 >= sqrtPriceLimitX96 // sqrtPriceTargetX96 = max(sqrtPriceNextX96, sqrtPriceLimitX96) // when zeroForOne == false, nextOrLimit reduces to sqrtPriceNextX96 < sqrtPriceLimitX96 // sqrtPriceTargetX96 = min(sqrtPriceNextX96, sqrtPriceLimitX96) sqrtPriceNextX96 := and(sqrtPriceNextX96, 0xffffffffffffffffffffffffffffffffffffffff) sqrtPriceLimitX96 := and(sqrtPriceLimitX96, 0xffffffffffffffffffffffffffffffffffffffff) let nextOrLimit := xor(lt(sqrtPriceNextX96, sqrtPriceLimitX96), and(zeroForOne, 0x1)) let symDiff := xor(sqrtPriceNextX96, sqrtPriceLimitX96) sqrtPriceTargetX96 := xor(sqrtPriceLimitX96, mul(symDiff, nextOrLimit)) } } /// @notice Computes the result of swapping some amount in, or amount out, given the parameters of the swap /// @dev If the swap's amountSpecified is negative, the combined fee and input amount will never exceed the absolute value of the remaining amount. /// @param sqrtPriceCurrentX96 The current sqrt price of the pool /// @param sqrtPriceTargetX96 The price that cannot be exceeded, from which the direction of the swap is inferred /// @param liquidity The usable liquidity /// @param amountRemaining How much input or output amount is remaining to be swapped in/out /// @param feePips The fee taken from the input amount, expressed in hundredths of a bip /// @return sqrtPriceNextX96 The price after swapping the amount in/out, not to exceed the price target /// @return amountIn The amount to be swapped in, of either currency0 or currency1, based on the direction of the swap /// @return amountOut The amount to be received, of either currency0 or currency1, based on the direction of the swap /// @return feeAmount The amount of input that will be taken as a fee /// @dev feePips must be no larger than MAX_SWAP_FEE for this function. We ensure that before setting a fee using LPFeeLibrary.isValid. function computeSwapStep( uint160 sqrtPriceCurrentX96, uint160 sqrtPriceTargetX96, uint128 liquidity, int256 amountRemaining, uint24 feePips ) internal pure returns (uint160 sqrtPriceNextX96, uint256 amountIn, uint256 amountOut, uint256 feeAmount) { unchecked { uint256 _feePips = feePips; // upcast once and cache bool zeroForOne = sqrtPriceCurrentX96 >= sqrtPriceTargetX96; bool exactIn = amountRemaining < 0; if (exactIn) { uint256 amountRemainingLessFee = FullMath.mulDiv(uint256(-amountRemaining), MAX_SWAP_FEE - _feePips, MAX_SWAP_FEE); amountIn = zeroForOne ? SqrtPriceMath.getAmount0Delta(sqrtPriceTargetX96, sqrtPriceCurrentX96, liquidity, true) : SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceTargetX96, liquidity, true); if (amountRemainingLessFee >= amountIn) { // `amountIn` is capped by the target price sqrtPriceNextX96 = sqrtPriceTargetX96; feeAmount = _feePips == MAX_SWAP_FEE ? amountIn // amountIn is always 0 here, as amountRemainingLessFee == 0 and amountRemainingLessFee >= amountIn : FullMath.mulDivRoundingUp(amountIn, _feePips, MAX_SWAP_FEE - _feePips); } else { // exhaust the remaining amount amountIn = amountRemainingLessFee; sqrtPriceNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput( sqrtPriceCurrentX96, liquidity, amountRemainingLessFee, zeroForOne ); // we didn't reach the target, so take the remainder of the maximum input as fee feeAmount = uint256(-amountRemaining) - amountIn; } amountOut = zeroForOne ? SqrtPriceMath.getAmount1Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, false) : SqrtPriceMath.getAmount0Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, false); } else { amountOut = zeroForOne ? SqrtPriceMath.getAmount1Delta(sqrtPriceTargetX96, sqrtPriceCurrentX96, liquidity, false) : SqrtPriceMath.getAmount0Delta(sqrtPriceCurrentX96, sqrtPriceTargetX96, liquidity, false); if (uint256(amountRemaining) >= amountOut) { // `amountOut` is capped by the target price sqrtPriceNextX96 = sqrtPriceTargetX96; } else { // cap the output amount to not exceed the remaining output amount amountOut = uint256(amountRemaining); sqrtPriceNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtPriceCurrentX96, liquidity, amountOut, zeroForOne); } amountIn = zeroForOne ? SqrtPriceMath.getAmount0Delta(sqrtPriceNextX96, sqrtPriceCurrentX96, liquidity, true) : SqrtPriceMath.getAmount1Delta(sqrtPriceCurrentX96, sqrtPriceNextX96, liquidity, true); // `feePips` cannot be `MAX_SWAP_FEE` for exact out feeAmount = FullMath.mulDivRoundingUp(amountIn, _feePips, MAX_SWAP_FEE - _feePips); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {BitMath} from "./BitMath.sol"; /// @title Packed tick initialized state library /// @notice Stores a packed mapping of tick index to its initialized state /// @dev The mapping uses int16 for keys since ticks are represented as int24 and there are 256 (2^8) values per word. library TickBitmap { /// @notice Thrown when the tick is not enumerated by the tick spacing /// @param tick the invalid tick /// @param tickSpacing The tick spacing of the pool error TickMisaligned(int24 tick, int24 tickSpacing); /// @dev round towards negative infinity function compress(int24 tick, int24 tickSpacing) internal pure returns (int24 compressed) { // compressed = tick / tickSpacing; // if (tick < 0 && tick % tickSpacing != 0) compressed--; assembly ("memory-safe") { tick := signextend(2, tick) tickSpacing := signextend(2, tickSpacing) compressed := sub( sdiv(tick, tickSpacing), // if (tick < 0 && tick % tickSpacing != 0) then tick % tickSpacing < 0, vice versa slt(smod(tick, tickSpacing), 0) ) } } /// @notice Computes the position in the mapping where the initialized bit for a tick lives /// @param tick The tick for which to compute the position /// @return wordPos The key in the mapping containing the word in which the bit is stored /// @return bitPos The bit position in the word where the flag is stored function position(int24 tick) internal pure returns (int16 wordPos, uint8 bitPos) { assembly ("memory-safe") { // signed arithmetic shift right wordPos := sar(8, signextend(2, tick)) bitPos := and(tick, 0xff) } } /// @notice Flips the initialized state for a given tick from false to true, or vice versa /// @param self The mapping in which to flip the tick /// @param tick The tick to flip /// @param tickSpacing The spacing between usable ticks function flipTick(mapping(int16 => uint256) storage self, int24 tick, int24 tickSpacing) internal { // Equivalent to the following Solidity: // if (tick % tickSpacing != 0) revert TickMisaligned(tick, tickSpacing); // (int16 wordPos, uint8 bitPos) = position(tick / tickSpacing); // uint256 mask = 1 << bitPos; // self[wordPos] ^= mask; assembly ("memory-safe") { tick := signextend(2, tick) tickSpacing := signextend(2, tickSpacing) // ensure that the tick is spaced if smod(tick, tickSpacing) { let fmp := mload(0x40) mstore(fmp, 0xd4d8f3e6) // selector for TickMisaligned(int24,int24) mstore(add(fmp, 0x20), tick) mstore(add(fmp, 0x40), tickSpacing) revert(add(fmp, 0x1c), 0x44) } tick := sdiv(tick, tickSpacing) // calculate the storage slot corresponding to the tick // wordPos = tick >> 8 mstore(0, sar(8, tick)) mstore(0x20, self.slot) // the slot of self[wordPos] is keccak256(abi.encode(wordPos, self.slot)) let slot := keccak256(0, 0x40) // mask = 1 << bitPos = 1 << (tick % 256) // self[wordPos] ^= mask sstore(slot, xor(sload(slot), shl(and(tick, 0xff), 1))) } } /// @notice Returns the next initialized tick contained in the same word (or adjacent word) as the tick that is either /// to the left (less than or equal to) or right (greater than) of the given tick /// @param self The mapping in which to compute the next initialized tick /// @param tick The starting tick /// @param tickSpacing The spacing between usable ticks /// @param lte Whether to search for the next initialized tick to the left (less than or equal to the starting tick) /// @return next The next initialized or uninitialized tick up to 256 ticks away from the current tick /// @return initialized Whether the next tick is initialized, as the function only searches within up to 256 ticks function nextInitializedTickWithinOneWord( mapping(int16 => uint256) storage self, int24 tick, int24 tickSpacing, bool lte ) internal view returns (int24 next, bool initialized) { unchecked { int24 compressed = compress(tick, tickSpacing); if (lte) { (int16 wordPos, uint8 bitPos) = position(compressed); // all the 1s at or to the right of the current bitPos uint256 mask = type(uint256).max >> (uint256(type(uint8).max) - bitPos); uint256 masked = self[wordPos] & mask; // if there are no initialized ticks to the right of or at the current tick, return rightmost in the word initialized = masked != 0; // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick next = initialized ? (compressed - int24(uint24(bitPos - BitMath.mostSignificantBit(masked)))) * tickSpacing : (compressed - int24(uint24(bitPos))) * tickSpacing; } else { // start from the word of the next tick, since the current tick state doesn't matter (int16 wordPos, uint8 bitPos) = position(++compressed); // all the 1s at or to the left of the bitPos uint256 mask = ~((1 << bitPos) - 1); uint256 masked = self[wordPos] & mask; // if there are no initialized ticks to the left of the current tick, return leftmost in the word initialized = masked != 0; // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick next = initialized ? (compressed + int24(uint24(BitMath.leastSignificantBit(masked) - bitPos))) * tickSpacing : (compressed + int24(uint24(type(uint8).max - bitPos))) * tickSpacing; } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {BitMath} from "./BitMath.sol"; import {CustomRevert} from "./CustomRevert.sol"; /// @title Math library for computing sqrt prices from ticks and vice versa /// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports /// prices between 2**-128 and 2**128 library TickMath { using CustomRevert for bytes4; /// @notice Thrown when the tick passed to #getSqrtPriceAtTick is not between MIN_TICK and MAX_TICK error InvalidTick(int24 tick); /// @notice Thrown when the price passed to #getTickAtSqrtPrice does not correspond to a price between MIN_TICK and MAX_TICK error InvalidSqrtPrice(uint160 sqrtPriceX96); /// @dev The minimum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**-128 /// @dev If ever MIN_TICK and MAX_TICK are not centered around 0, the absTick logic in getSqrtPriceAtTick cannot be used int24 internal constant MIN_TICK = -887272; /// @dev The maximum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**128 /// @dev If ever MIN_TICK and MAX_TICK are not centered around 0, the absTick logic in getSqrtPriceAtTick cannot be used int24 internal constant MAX_TICK = 887272; /// @dev The minimum tick spacing value drawn from the range of type int16 that is greater than 0, i.e. min from the range [1, 32767] int24 internal constant MIN_TICK_SPACING = 1; /// @dev The maximum tick spacing value drawn from the range of type int16, i.e. max from the range [1, 32767] int24 internal constant MAX_TICK_SPACING = type(int16).max; /// @dev The minimum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MIN_TICK) uint160 internal constant MIN_SQRT_PRICE = 4295128739; /// @dev The maximum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MAX_TICK) uint160 internal constant MAX_SQRT_PRICE = 1461446703485210103287273052203988822378723970342; /// @dev A threshold used for optimized bounds check, equals `MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1` uint160 internal constant MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE = 1461446703485210103287273052203988822378723970342 - 4295128739 - 1; /// @notice Given a tickSpacing, compute the maximum usable tick function maxUsableTick(int24 tickSpacing) internal pure returns (int24) { unchecked { return (MAX_TICK / tickSpacing) * tickSpacing; } } /// @notice Given a tickSpacing, compute the minimum usable tick function minUsableTick(int24 tickSpacing) internal pure returns (int24) { unchecked { return (MIN_TICK / tickSpacing) * tickSpacing; } } /// @notice Calculates sqrt(1.0001^tick) * 2^96 /// @dev Throws if |tick| > max tick /// @param tick The input tick for the above formula /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the price of the two assets (currency1/currency0) /// at the given tick function getSqrtPriceAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) { unchecked { uint256 absTick; assembly ("memory-safe") { tick := signextend(2, tick) // mask = 0 if tick >= 0 else -1 (all 1s) let mask := sar(255, tick) // if tick >= 0, |tick| = tick = 0 ^ tick // if tick < 0, |tick| = ~~|tick| = ~(-|tick| - 1) = ~(tick - 1) = (-1) ^ (tick - 1) // either way, |tick| = mask ^ (tick + mask) absTick := xor(mask, add(mask, tick)) } if (absTick > uint256(int256(MAX_TICK))) InvalidTick.selector.revertWith(tick); // The tick is decomposed into bits, and for each bit with index i that is set, the product of 1/sqrt(1.0001^(2^i)) // is calculated (using Q128.128). The constants used for this calculation are rounded to the nearest integer // Equivalent to: // price = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; // or price = int(2**128 / sqrt(1.0001)) if (absTick & 0x1) else 1 << 128 uint256 price; assembly ("memory-safe") { price := xor(shl(128, 1), mul(xor(shl(128, 1), 0xfffcb933bd6fad37aa2d162d1a594001), and(absTick, 0x1))) } if (absTick & 0x2 != 0) price = (price * 0xfff97272373d413259a46990580e213a) >> 128; if (absTick & 0x4 != 0) price = (price * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; if (absTick & 0x8 != 0) price = (price * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; if (absTick & 0x10 != 0) price = (price * 0xffcb9843d60f6159c9db58835c926644) >> 128; if (absTick & 0x20 != 0) price = (price * 0xff973b41fa98c081472e6896dfb254c0) >> 128; if (absTick & 0x40 != 0) price = (price * 0xff2ea16466c96a3843ec78b326b52861) >> 128; if (absTick & 0x80 != 0) price = (price * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; if (absTick & 0x100 != 0) price = (price * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; if (absTick & 0x200 != 0) price = (price * 0xf987a7253ac413176f2b074cf7815e54) >> 128; if (absTick & 0x400 != 0) price = (price * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; if (absTick & 0x800 != 0) price = (price * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; if (absTick & 0x1000 != 0) price = (price * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; if (absTick & 0x2000 != 0) price = (price * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; if (absTick & 0x4000 != 0) price = (price * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; if (absTick & 0x8000 != 0) price = (price * 0x31be135f97d08fd981231505542fcfa6) >> 128; if (absTick & 0x10000 != 0) price = (price * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; if (absTick & 0x20000 != 0) price = (price * 0x5d6af8dedb81196699c329225ee604) >> 128; if (absTick & 0x40000 != 0) price = (price * 0x2216e584f5fa1ea926041bedfe98) >> 128; if (absTick & 0x80000 != 0) price = (price * 0x48a170391f7dc42444e8fa2) >> 128; assembly ("memory-safe") { // if (tick > 0) price = type(uint256).max / price; if sgt(tick, 0) { price := div(not(0), price) } // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. // we then downcast because we know the result always fits within 160 bits due to our tick input constraint // we round up in the division so getTickAtSqrtPrice of the output price is always consistent // `sub(shl(32, 1), 1)` is `type(uint32).max` // `price + type(uint32).max` will not overflow because `price` fits in 192 bits sqrtPriceX96 := shr(32, add(price, sub(shl(32, 1), 1))) } } } /// @notice Calculates the greatest tick value such that getSqrtPriceAtTick(tick) <= sqrtPriceX96 /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_PRICE, as MIN_SQRT_PRICE is the lowest value getSqrtPriceAtTick may /// ever return. /// @param sqrtPriceX96 The sqrt price for which to compute the tick as a Q64.96 /// @return tick The greatest tick for which the getSqrtPriceAtTick(tick) is less than or equal to the input sqrtPriceX96 function getTickAtSqrtPrice(uint160 sqrtPriceX96) internal pure returns (int24 tick) { unchecked { // Equivalent: if (sqrtPriceX96 < MIN_SQRT_PRICE || sqrtPriceX96 >= MAX_SQRT_PRICE) revert InvalidSqrtPrice(); // second inequality must be >= because the price can never reach the price at the max tick // if sqrtPriceX96 < MIN_SQRT_PRICE, the `sub` underflows and `gt` is true // if sqrtPriceX96 >= MAX_SQRT_PRICE, sqrtPriceX96 - MIN_SQRT_PRICE > MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1 if ((sqrtPriceX96 - MIN_SQRT_PRICE) > MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE) { InvalidSqrtPrice.selector.revertWith(sqrtPriceX96); } uint256 price = uint256(sqrtPriceX96) << 32; uint256 r = price; uint256 msb = BitMath.mostSignificantBit(r); if (msb >= 128) r = price >> (msb - 127); else r = price << (127 - msb); int256 log_2 = (int256(msb) - 128) << 64; assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(63, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(62, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(61, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(60, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(59, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(58, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(57, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(56, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(55, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(54, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(53, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(52, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(51, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(50, f)) } int256 log_sqrt10001 = log_2 * 255738958999603826347141; // Q22.128 number // Magic number represents the ceiling of the maximum value of the error when approximating log_sqrt10001(x) int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); // Magic number represents the minimum value of the error when approximating log_sqrt10001(x), when // sqrtPrice is from the range (2^-64, 2^64). This is safe as MIN_SQRT_PRICE is more than 2^-64. If MIN_SQRT_PRICE // is changed, this may need to be changed too int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); tick = tickLow == tickHi ? tickLow : getSqrtPriceAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {IPoolManager} from "../interfaces/IPoolManager.sol"; import {Currency} from "../types/Currency.sol"; import {CurrencyReserves} from "./CurrencyReserves.sol"; import {NonzeroDeltaCount} from "./NonzeroDeltaCount.sol"; import {Lock} from "./Lock.sol"; /// @notice A helper library to provide state getters that use exttload library TransientStateLibrary { /// @notice returns the reserves for the synced currency /// @param manager The pool manager contract. /// @return uint256 The reserves of the currency. /// @dev returns 0 if the reserves are not synced or value is 0. /// Checks the synced currency to only return valid reserve values (after a sync and before a settle). function getSyncedReserves(IPoolManager manager) internal view returns (uint256) { if (getSyncedCurrency(manager).isAddressZero()) return 0; return uint256(manager.exttload(CurrencyReserves.RESERVES_OF_SLOT)); } function getSyncedCurrency(IPoolManager manager) internal view returns (Currency) { return Currency.wrap(address(uint160(uint256(manager.exttload(CurrencyReserves.CURRENCY_SLOT))))); } /// @notice Returns the number of nonzero deltas open on the PoolManager that must be zeroed out before the contract is locked function getNonzeroDeltaCount(IPoolManager manager) internal view returns (uint256) { return uint256(manager.exttload(NonzeroDeltaCount.NONZERO_DELTA_COUNT_SLOT)); } /// @notice Get the current delta for a caller in the given currency /// @param target The credited account address /// @param currency The currency for which to lookup the delta function currencyDelta(IPoolManager manager, address target, Currency currency) internal view returns (int256) { bytes32 key; assembly ("memory-safe") { mstore(0, and(target, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(32, and(currency, 0xffffffffffffffffffffffffffffffffffffffff)) key := keccak256(0, 64) } return int256(uint256(manager.exttload(key))); } /// @notice Returns whether the contract is unlocked or not function isUnlocked(IPoolManager manager) internal view returns (bool) { return manager.exttload(Lock.IS_UNLOCKED_SLOT) != 0x0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Math functions that do not check inputs or outputs /// @notice Contains methods that perform common math functions but do not do any overflow or underflow checks library UnsafeMath { /// @notice Returns ceil(x / y) /// @dev division by 0 will return 0, and should be checked externally /// @param x The dividend /// @param y The divisor /// @return z The quotient, ceil(x / y) function divRoundingUp(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly ("memory-safe") { z := add(div(x, y), gt(mod(x, y), 0)) } } /// @notice Calculates floor(a×b÷denominator) /// @dev division by 0 will return 0, and should be checked externally /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result, floor(a×b÷denominator) function simpleMulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { assembly ("memory-safe") { result := div(mul(a, b), denominator) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {SafeCast} from "../libraries/SafeCast.sol"; /// @dev Two `int128` values packed into a single `int256` where the upper 128 bits represent the amount0 /// and the lower 128 bits represent the amount1. type BalanceDelta is int256; using {add as +, sub as -, eq as ==, neq as !=} for BalanceDelta global; using BalanceDeltaLibrary for BalanceDelta global; using SafeCast for int256; function toBalanceDelta(int128 _amount0, int128 _amount1) pure returns (BalanceDelta balanceDelta) { assembly ("memory-safe") { balanceDelta := or(shl(128, _amount0), and(sub(shl(128, 1), 1), _amount1)) } } function add(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) { int256 res0; int256 res1; assembly ("memory-safe") { let a0 := sar(128, a) let a1 := signextend(15, a) let b0 := sar(128, b) let b1 := signextend(15, b) res0 := add(a0, b0) res1 := add(a1, b1) } return toBalanceDelta(res0.toInt128(), res1.toInt128()); } function sub(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) { int256 res0; int256 res1; assembly ("memory-safe") { let a0 := sar(128, a) let a1 := signextend(15, a) let b0 := sar(128, b) let b1 := signextend(15, b) res0 := sub(a0, b0) res1 := sub(a1, b1) } return toBalanceDelta(res0.toInt128(), res1.toInt128()); } function eq(BalanceDelta a, BalanceDelta b) pure returns (bool) { return BalanceDelta.unwrap(a) == BalanceDelta.unwrap(b); } function neq(BalanceDelta a, BalanceDelta b) pure returns (bool) { return BalanceDelta.unwrap(a) != BalanceDelta.unwrap(b); } /// @notice Library for getting the amount0 and amount1 deltas from the BalanceDelta type library BalanceDeltaLibrary { /// @notice A BalanceDelta of 0 BalanceDelta public constant ZERO_DELTA = BalanceDelta.wrap(0); function amount0(BalanceDelta balanceDelta) internal pure returns (int128 _amount0) { assembly ("memory-safe") { _amount0 := sar(128, balanceDelta) } } function amount1(BalanceDelta balanceDelta) internal pure returns (int128 _amount1) { assembly ("memory-safe") { _amount1 := signextend(15, balanceDelta) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // Return type of the beforeSwap hook. // Upper 128 bits is the delta in specified tokens. Lower 128 bits is delta in unspecified tokens (to match the afterSwap hook) type BeforeSwapDelta is int256; // Creates a BeforeSwapDelta from specified and unspecified function toBeforeSwapDelta(int128 deltaSpecified, int128 deltaUnspecified) pure returns (BeforeSwapDelta beforeSwapDelta) { assembly ("memory-safe") { beforeSwapDelta := or(shl(128, deltaSpecified), and(sub(shl(128, 1), 1), deltaUnspecified)) } } /// @notice Library for getting the specified and unspecified deltas from the BeforeSwapDelta type library BeforeSwapDeltaLibrary { /// @notice A BeforeSwapDelta of 0 BeforeSwapDelta public constant ZERO_DELTA = BeforeSwapDelta.wrap(0); /// extracts int128 from the upper 128 bits of the BeforeSwapDelta /// returned by beforeSwap function getSpecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaSpecified) { assembly ("memory-safe") { deltaSpecified := sar(128, delta) } } /// extracts int128 from the lower 128 bits of the BeforeSwapDelta /// returned by beforeSwap and afterSwap function getUnspecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaUnspecified) { assembly ("memory-safe") { deltaUnspecified := signextend(15, delta) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol"; import {CustomRevert} from "../libraries/CustomRevert.sol"; type Currency is address; using {greaterThan as >, lessThan as <, greaterThanOrEqualTo as >=, equals as ==} for Currency global; using CurrencyLibrary for Currency global; function equals(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) == Currency.unwrap(other); } function greaterThan(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) > Currency.unwrap(other); } function lessThan(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) < Currency.unwrap(other); } function greaterThanOrEqualTo(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) >= Currency.unwrap(other); } /// @title CurrencyLibrary /// @dev This library allows for transferring and holding native tokens and ERC20 tokens library CurrencyLibrary { /// @notice Additional context for ERC-7751 wrapped error when a native transfer fails error NativeTransferFailed(); /// @notice Additional context for ERC-7751 wrapped error when an ERC20 transfer fails error ERC20TransferFailed(); /// @notice A constant to represent the native currency Currency public constant ADDRESS_ZERO = Currency.wrap(address(0)); function transfer(Currency currency, address to, uint256 amount) internal { // altered from https://github.com/transmissions11/solmate/blob/44a9963d4c78111f77caa0e65d677b8b46d6f2e6/src/utils/SafeTransferLib.sol // modified custom error selectors bool success; if (currency.isAddressZero()) { assembly ("memory-safe") { // Transfer the ETH and revert if it fails. success := call(gas(), to, amount, 0, 0, 0, 0) } // revert with NativeTransferFailed, containing the bubbled up error as an argument if (!success) { CustomRevert.bubbleUpAndRevertWith(to, bytes4(0), NativeTransferFailed.selector); } } else { assembly ("memory-safe") { // Get a pointer to some free memory. let fmp := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(fmp, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(fmp, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(fmp, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), currency, 0, fmp, 68, 0, 32) ) // Now clean the memory we used mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were stored here mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored here } // revert with ERC20TransferFailed, containing the bubbled up error as an argument if (!success) { CustomRevert.bubbleUpAndRevertWith( Currency.unwrap(currency), IERC20Minimal.transfer.selector, ERC20TransferFailed.selector ); } } } function balanceOfSelf(Currency currency) internal view returns (uint256) { if (currency.isAddressZero()) { return address(this).balance; } else { return IERC20Minimal(Currency.unwrap(currency)).balanceOf(address(this)); } } function balanceOf(Currency currency, address owner) internal view returns (uint256) { if (currency.isAddressZero()) { return owner.balance; } else { return IERC20Minimal(Currency.unwrap(currency)).balanceOf(owner); } } function isAddressZero(Currency currency) internal pure returns (bool) { return Currency.unwrap(currency) == Currency.unwrap(ADDRESS_ZERO); } function toId(Currency currency) internal pure returns (uint256) { return uint160(Currency.unwrap(currency)); } // If the upper 12 bytes are non-zero, they will be zero-ed out // Therefore, fromId() and toId() are not inverses of each other function fromId(uint256 id) internal pure returns (Currency) { return Currency.wrap(address(uint160(id))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "./PoolKey.sol"; type PoolId is bytes32; /// @notice Library for computing the ID of a pool library PoolIdLibrary { /// @notice Returns value equal to keccak256(abi.encode(poolKey)) function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) { assembly ("memory-safe") { // 0xa0 represents the total size of the poolKey struct (5 slots of 32 bytes) poolId := keccak256(poolKey, 0xa0) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Currency} from "./Currency.sol"; import {IHooks} from "../interfaces/IHooks.sol"; import {PoolIdLibrary} from "./PoolId.sol"; using PoolIdLibrary for PoolKey global; /// @notice Returns the key for identifying a pool struct PoolKey { /// @notice The lower currency of the pool, sorted numerically Currency currency0; /// @notice The higher currency of the pool, sorted numerically Currency currency1; /// @notice The pool LP fee, capped at 1_000_000. If the highest bit is 1, the pool has a dynamic fee and must be exactly equal to 0x800000 uint24 fee; /// @notice Ticks that involve positions must be a multiple of tick spacing int24 tickSpacing; /// @notice The hooks of the pool IHooks hooks; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Slot0 is a packed version of solidity structure. * Using the packaged version saves gas by not storing the structure fields in memory slots. * * Layout: * 24 bits empty | 24 bits lpFee | 12 bits protocolFee 1->0 | 12 bits protocolFee 0->1 | 24 bits tick | 160 bits sqrtPriceX96 * * Fields in the direction from the least significant bit: * * The current price * uint160 sqrtPriceX96; * * The current tick * int24 tick; * * Protocol fee, expressed in hundredths of a bip, upper 12 bits are for 1->0, and the lower 12 are for 0->1 * the maximum is 1000 - meaning the maximum protocol fee is 0.1% * the protocolFee is taken from the input first, then the lpFee is taken from the remaining input * uint24 protocolFee; * * The current LP fee of the pool. If the pool is dynamic, this does not include the dynamic fee flag. * uint24 lpFee; */ type Slot0 is bytes32; using Slot0Library for Slot0 global; /// @notice Library for getting and setting values in the Slot0 type library Slot0Library { uint160 internal constant MASK_160_BITS = 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; uint24 internal constant MASK_24_BITS = 0xFFFFFF; uint8 internal constant TICK_OFFSET = 160; uint8 internal constant PROTOCOL_FEE_OFFSET = 184; uint8 internal constant LP_FEE_OFFSET = 208; // #### GETTERS #### function sqrtPriceX96(Slot0 _packed) internal pure returns (uint160 _sqrtPriceX96) { assembly ("memory-safe") { _sqrtPriceX96 := and(MASK_160_BITS, _packed) } } function tick(Slot0 _packed) internal pure returns (int24 _tick) { assembly ("memory-safe") { _tick := signextend(2, shr(TICK_OFFSET, _packed)) } } function protocolFee(Slot0 _packed) internal pure returns (uint24 _protocolFee) { assembly ("memory-safe") { _protocolFee := and(MASK_24_BITS, shr(PROTOCOL_FEE_OFFSET, _packed)) } } function lpFee(Slot0 _packed) internal pure returns (uint24 _lpFee) { assembly ("memory-safe") { _lpFee := and(MASK_24_BITS, shr(LP_FEE_OFFSET, _packed)) } } // #### SETTERS #### function setSqrtPriceX96(Slot0 _packed, uint160 _sqrtPriceX96) internal pure returns (Slot0 _result) { assembly ("memory-safe") { _result := or(and(not(MASK_160_BITS), _packed), and(MASK_160_BITS, _sqrtPriceX96)) } } function setTick(Slot0 _packed, int24 _tick) internal pure returns (Slot0 _result) { assembly ("memory-safe") { _result := or(and(not(shl(TICK_OFFSET, MASK_24_BITS)), _packed), shl(TICK_OFFSET, and(MASK_24_BITS, _tick))) } } function setProtocolFee(Slot0 _packed, uint24 _protocolFee) internal pure returns (Slot0 _result) { assembly ("memory-safe") { _result := or( and(not(shl(PROTOCOL_FEE_OFFSET, MASK_24_BITS)), _packed), shl(PROTOCOL_FEE_OFFSET, and(MASK_24_BITS, _protocolFee)) ) } } function setLpFee(Slot0 _packed, uint24 _lpFee) internal pure returns (Slot0 _result) { assembly ("memory-safe") { _result := or(and(not(shl(LP_FEE_OFFSET, MASK_24_BITS)), _packed), shl(LP_FEE_OFFSET, and(MASK_24_BITS, _lpFee))) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.2) (utils/Base64.sol) pragma solidity ^0.8.20; /** * @dev Provides a set of functions to operate with Base64 strings. */ library Base64 { /** * @dev Base64 Encoding/Decoding Table */ string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * @dev Converts a `bytes` to its Bytes64 `string` representation. */ function encode(bytes memory data) internal pure returns (string memory) { /** * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol */ if (data.length == 0) return ""; // Loads the table into memory string memory table = _TABLE; // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter // and split into 4 numbers of 6 bits. // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up // - `data.length + 2` -> Round up // - `/ 3` -> Number of 3-bytes chunks // - `4 *` -> 4 characters for each chunk string memory result = new string(4 * ((data.length + 2) / 3)); /// @solidity memory-safe-assembly assembly { // Prepare the lookup table (skip the first "length" byte) let tablePtr := add(table, 1) // Prepare result pointer, jump over length let resultPtr := add(result, 0x20) let dataPtr := data let endPtr := add(data, mload(data)) // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and // set it to zero to make sure no dirty bytes are read in that section. let afterPtr := add(endPtr, 0x20) let afterCache := mload(afterPtr) mstore(afterPtr, 0x00) // Run over the input, 3 bytes at a time for { } lt(dataPtr, endPtr) { } { // Advance 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // To write each character, shift the 3 byte (24 bits) chunk // 4 times in blocks of 6 bits for each character (18, 12, 6, 0) // and apply logical AND with 0x3F to bitmask the least significant 6 bits. // Use this as an index into the lookup table, mload an entire word // so the desired character is in the least significant byte, and // mstore8 this least significant byte into the result and continue. mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) resultPtr := add(resultPtr, 1) // Advance } // Reset the value that was cached mstore(afterPtr, afterCache) // When data `bytes` is not exactly 3 bytes long // it is padded with `=` characters at the end switch mod(mload(data), 3) case 1 { mstore8(sub(resultPtr, 1), 0x3d) mstore8(sub(resultPtr, 2), 0x3d) } case 2 { mstore8(sub(resultPtr, 1), 0x3d) } } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Create2.sol) pragma solidity ^0.8.20; /** * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer. * `CREATE2` can be used to compute in advance the address where a smart * contract will be deployed, which allows for interesting new mechanisms known * as 'counterfactual interactions'. * * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more * information. */ library Create2 { /** * @dev Not enough balance for performing a CREATE2 deploy. */ error Create2InsufficientBalance(uint256 balance, uint256 needed); /** * @dev There's no code to deploy. */ error Create2EmptyBytecode(); /** * @dev The deployment failed. */ error Create2FailedDeployment(); /** * @dev Deploys a contract using `CREATE2`. The address where the contract * will be deployed can be known in advance via {computeAddress}. * * The bytecode for a contract can be obtained from Solidity with * `type(contractName).creationCode`. * * Requirements: * * - `bytecode` must not be empty. * - `salt` must have not been used for `bytecode` already. * - the factory must have a balance of at least `amount`. * - if `amount` is non-zero, `bytecode` must have a `payable` constructor. */ function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) { if (address(this).balance < amount) { revert Create2InsufficientBalance(address(this).balance, amount); } if (bytecode.length == 0) { revert Create2EmptyBytecode(); } /// @solidity memory-safe-assembly assembly { addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt) } if (addr == address(0)) { revert Create2FailedDeployment(); } } /** * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the * `bytecodeHash` or `salt` will result in a new destination address. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) { return computeAddress(salt, bytecodeHash, address(this)); } /** * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) // Get free memory pointer // | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... | // |-------------------|---------------------------------------------------------------------------| // | bytecodeHash | CCCCCCCCCCCCC...CC | // | salt | BBBBBBBBBBBBB...BB | // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA | // | 0xFF | FF | // |-------------------|---------------------------------------------------------------------------| // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC | // | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ | mstore(add(ptr, 0x40), bytecodeHash) mstore(add(ptr, 0x20), salt) mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff mstore8(start, 0xff) addr := keccak256(start, 85) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Interface for functions to access any storage slot in a contract interface IExtsload { /// @notice Called by external contracts to access granular pool state /// @param slot Key of slot to sload /// @return value The value of the slot as bytes32 function extsload(bytes32 slot) external view returns (bytes32 value); /// @notice Called by external contracts to access granular pool state /// @param startSlot Key of slot to start sloading from /// @param nSlots Number of slots to load into return value /// @return values List of loaded values. function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory values); /// @notice Called by external contracts to access sparse pool state /// @param slots List of slots to SLOAD from. /// @return values List of loaded values. function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory values); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /// @notice Interface for functions to access any transient storage slot in a contract interface IExttload { /// @notice Called by external contracts to access transient storage of the contract /// @param slot Key of slot to tload /// @return value The value of the slot as bytes32 function exttload(bytes32 slot) external view returns (bytes32 value); /// @notice Called by external contracts to access sparse transient pool state /// @param slots List of slots to tload /// @return values List of loaded values function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory values); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "../types/PoolKey.sol"; import {BalanceDelta} from "../types/BalanceDelta.sol"; import {IPoolManager} from "./IPoolManager.sol"; import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol"; /// @notice V4 decides whether to invoke specific hooks by inspecting the least significant bits /// of the address that the hooks contract is deployed to. /// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400 /// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used. /// See the Hooks library for the full spec. /// @dev Should only be callable by the v4 PoolManager. interface IHooks { /// @notice The hook called before the state of a pool is initialized /// @param sender The initial msg.sender for the initialize call /// @param key The key for the pool being initialized /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 /// @return bytes4 The function selector for the hook function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96) external returns (bytes4); /// @notice The hook called after the state of a pool is initialized /// @param sender The initial msg.sender for the initialize call /// @param key The key for the pool being initialized /// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96 /// @param tick The current tick after the state of a pool is initialized /// @return bytes4 The function selector for the hook function afterInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, int24 tick) external returns (bytes4); /// @notice The hook called before liquidity is added /// @param sender The initial msg.sender for the add liquidity call /// @param key The key for the pool /// @param params The parameters for adding liquidity /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook /// @return bytes4 The function selector for the hook function beforeAddLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, bytes calldata hookData ) external returns (bytes4); /// @notice The hook called after liquidity is added /// @param sender The initial msg.sender for the add liquidity call /// @param key The key for the pool /// @param params The parameters for adding liquidity /// @param delta The caller's balance delta after adding liquidity; the sum of principal delta, fees accrued, and hook delta /// @param feesAccrued The fees accrued since the last time fees were collected from this position /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook /// @return bytes4 The function selector for the hook /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency function afterAddLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external returns (bytes4, BalanceDelta); /// @notice The hook called before liquidity is removed /// @param sender The initial msg.sender for the remove liquidity call /// @param key The key for the pool /// @param params The parameters for removing liquidity /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook /// @return bytes4 The function selector for the hook function beforeRemoveLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, bytes calldata hookData ) external returns (bytes4); /// @notice The hook called after liquidity is removed /// @param sender The initial msg.sender for the remove liquidity call /// @param key The key for the pool /// @param params The parameters for removing liquidity /// @param delta The caller's balance delta after removing liquidity; the sum of principal delta, fees accrued, and hook delta /// @param feesAccrued The fees accrued since the last time fees were collected from this position /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook /// @return bytes4 The function selector for the hook /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency function afterRemoveLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external returns (bytes4, BalanceDelta); /// @notice The hook called before a swap /// @param sender The initial msg.sender for the swap call /// @param key The key for the pool /// @param params The parameters for the swap /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook /// @return bytes4 The function selector for the hook /// @return BeforeSwapDelta The hook's delta in specified and unspecified currencies. Positive: the hook is owed/took currency, negative: the hook owes/sent currency /// @return uint24 Optionally override the lp fee, only used if three conditions are met: 1. the Pool has a dynamic fee, 2. the value's 2nd highest bit is set (23rd bit, 0x400000), and 3. the value is less than or equal to the maximum fee (1 million) function beforeSwap( address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata hookData ) external returns (bytes4, BeforeSwapDelta, uint24); /// @notice The hook called after a swap /// @param sender The initial msg.sender for the swap call /// @param key The key for the pool /// @param params The parameters for the swap /// @param delta The amount owed to the caller (positive) or owed to the pool (negative) /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook /// @return bytes4 The function selector for the hook /// @return int128 The hook's delta in unspecified currency. Positive: the hook is owed/took currency, negative: the hook owes/sent currency function afterSwap( address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, BalanceDelta delta, bytes calldata hookData ) external returns (bytes4, int128); /// @notice The hook called before donate /// @param sender The initial msg.sender for the donate call /// @param key The key for the pool /// @param amount0 The amount of token0 being donated /// @param amount1 The amount of token1 being donated /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook /// @return bytes4 The function selector for the hook function beforeDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external returns (bytes4); /// @notice The hook called after donate /// @param sender The initial msg.sender for the donate call /// @param key The key for the pool /// @param amount0 The amount of token0 being donated /// @param amount1 The amount of token1 being donated /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook /// @return bytes4 The function selector for the hook function afterDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {Currency} from "../types/Currency.sol"; import {PoolKey} from "../types/PoolKey.sol"; import {IHooks} from "./IHooks.sol"; import {IERC6909Claims} from "./external/IERC6909Claims.sol"; import {IProtocolFees} from "./IProtocolFees.sol"; import {BalanceDelta} from "../types/BalanceDelta.sol"; import {PoolId} from "../types/PoolId.sol"; import {IExtsload} from "./IExtsload.sol"; import {IExttload} from "./IExttload.sol"; /// @notice Interface for the PoolManager interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload, IExttload { /// @notice Thrown when a currency is not netted out after the contract is unlocked error CurrencyNotSettled(); /// @notice Thrown when trying to interact with a non-initialized pool error PoolNotInitialized(); /// @notice Thrown when unlock is called, but the contract is already unlocked error AlreadyUnlocked(); /// @notice Thrown when a function is called that requires the contract to be unlocked, but it is not error ManagerLocked(); /// @notice Pools are limited to type(int16).max tickSpacing in #initialize, to prevent overflow error TickSpacingTooLarge(int24 tickSpacing); /// @notice Pools must have a positive non-zero tickSpacing passed to #initialize error TickSpacingTooSmall(int24 tickSpacing); /// @notice PoolKey must have currencies where address(currency0) < address(currency1) error CurrenciesOutOfOrderOrEqual(address currency0, address currency1); /// @notice Thrown when a call to updateDynamicLPFee is made by an address that is not the hook, /// or on a pool that does not have a dynamic swap fee. error UnauthorizedDynamicLPFeeUpdate(); /// @notice Thrown when trying to swap amount of 0 error SwapAmountCannotBeZero(); ///@notice Thrown when native currency is passed to a non native settlement error NonzeroNativeValue(); /// @notice Thrown when `clear` is called with an amount that is not exactly equal to the open currency delta. error MustClearExactPositiveDelta(); /// @notice Emitted when a new pool is initialized /// @param id The abi encoded hash of the pool key struct for the new pool /// @param currency0 The first currency of the pool by address sort order /// @param currency1 The second currency of the pool by address sort order /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip /// @param tickSpacing The minimum number of ticks between initialized ticks /// @param hooks The hooks contract address for the pool, or address(0) if none /// @param sqrtPriceX96 The price of the pool on initialization /// @param tick The initial tick of the pool corresponding to the initialized price event Initialize( PoolId indexed id, Currency indexed currency0, Currency indexed currency1, uint24 fee, int24 tickSpacing, IHooks hooks, uint160 sqrtPriceX96, int24 tick ); /// @notice Emitted when a liquidity position is modified /// @param id The abi encoded hash of the pool key struct for the pool that was modified /// @param sender The address that modified the pool /// @param tickLower The lower tick of the position /// @param tickUpper The upper tick of the position /// @param liquidityDelta The amount of liquidity that was added or removed /// @param salt The extra data to make positions unique event ModifyLiquidity( PoolId indexed id, address indexed sender, int24 tickLower, int24 tickUpper, int256 liquidityDelta, bytes32 salt ); /// @notice Emitted for swaps between currency0 and currency1 /// @param id The abi encoded hash of the pool key struct for the pool that was modified /// @param sender The address that initiated the swap call, and that received the callback /// @param amount0 The delta of the currency0 balance of the pool /// @param amount1 The delta of the currency1 balance of the pool /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96 /// @param liquidity The liquidity of the pool after the swap /// @param tick The log base 1.0001 of the price of the pool after the swap /// @param fee The swap fee in hundredths of a bip event Swap( PoolId indexed id, address indexed sender, int128 amount0, int128 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick, uint24 fee ); /// @notice Emitted for donations /// @param id The abi encoded hash of the pool key struct for the pool that was donated to /// @param sender The address that initiated the donate call /// @param amount0 The amount donated in currency0 /// @param amount1 The amount donated in currency1 event Donate(PoolId indexed id, address indexed sender, uint256 amount0, uint256 amount1); /// @notice All interactions on the contract that account deltas require unlocking. A caller that calls `unlock` must implement /// `IUnlockCallback(msg.sender).unlockCallback(data)`, where they interact with the remaining functions on this contract. /// @dev The only functions callable without an unlocking are `initialize` and `updateDynamicLPFee` /// @param data Any data to pass to the callback, via `IUnlockCallback(msg.sender).unlockCallback(data)` /// @return The data returned by the call to `IUnlockCallback(msg.sender).unlockCallback(data)` function unlock(bytes calldata data) external returns (bytes memory); /// @notice Initialize the state for a given pool ID /// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee /// @param key The pool key for the pool to initialize /// @param sqrtPriceX96 The initial square root price /// @return tick The initial tick of the pool function initialize(PoolKey memory key, uint160 sqrtPriceX96) external returns (int24 tick); struct ModifyLiquidityParams { // the lower and upper tick of the position int24 tickLower; int24 tickUpper; // how to modify the liquidity int256 liquidityDelta; // a value to set if you want unique liquidity positions at the same range bytes32 salt; } /// @notice Modify the liquidity for the given pool /// @dev Poke by calling with a zero liquidityDelta /// @param key The pool to modify liquidity in /// @param params The parameters for modifying the liquidity /// @param hookData The data to pass through to the add/removeLiquidity hooks /// @return callerDelta The balance delta of the caller of modifyLiquidity. This is the total of both principal, fee deltas, and hook deltas if applicable /// @return feesAccrued The balance delta of the fees generated in the liquidity range. Returned for informational purposes function modifyLiquidity(PoolKey memory key, ModifyLiquidityParams memory params, bytes calldata hookData) external returns (BalanceDelta callerDelta, BalanceDelta feesAccrued); struct SwapParams { /// Whether to swap token0 for token1 or vice versa bool zeroForOne; /// The desired input amount if negative (exactIn), or the desired output amount if positive (exactOut) int256 amountSpecified; /// The sqrt price at which, if reached, the swap will stop executing uint160 sqrtPriceLimitX96; } /// @notice Swap against the given pool /// @param key The pool to swap in /// @param params The parameters for swapping /// @param hookData The data to pass through to the swap hooks /// @return swapDelta The balance delta of the address swapping /// @dev Swapping on low liquidity pools may cause unexpected swap amounts when liquidity available is less than amountSpecified. /// Additionally note that if interacting with hooks that have the BEFORE_SWAP_RETURNS_DELTA_FLAG or AFTER_SWAP_RETURNS_DELTA_FLAG /// the hook may alter the swap input/output. Integrators should perform checks on the returned swapDelta. function swap(PoolKey memory key, SwapParams memory params, bytes calldata hookData) external returns (BalanceDelta swapDelta); /// @notice Donate the given currency amounts to the in-range liquidity providers of a pool /// @dev Calls to donate can be frontrun adding just-in-time liquidity, with the aim of receiving a portion donated funds. /// Donors should keep this in mind when designing donation mechanisms. /// @dev This function donates to in-range LPs at slot0.tick. In certain edge-cases of the swap algorithm, the `sqrtPrice` of /// a pool can be at the lower boundary of tick `n`, but the `slot0.tick` of the pool is already `n - 1`. In this case a call to /// `donate` would donate to tick `n - 1` (slot0.tick) not tick `n` (getTickAtSqrtPrice(slot0.sqrtPriceX96)). /// Read the comments in `Pool.swap()` for more information about this. /// @param key The key of the pool to donate to /// @param amount0 The amount of currency0 to donate /// @param amount1 The amount of currency1 to donate /// @param hookData The data to pass through to the donate hooks /// @return BalanceDelta The delta of the caller after the donate function donate(PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) external returns (BalanceDelta); /// @notice Writes the current ERC20 balance of the specified currency to transient storage /// This is used to checkpoint balances for the manager and derive deltas for the caller. /// @dev This MUST be called before any ERC20 tokens are sent into the contract, but can be skipped /// for native tokens because the amount to settle is determined by the sent value. /// However, if an ERC20 token has been synced and not settled, and the caller instead wants to settle /// native funds, this function can be called with the native currency to then be able to settle the native currency function sync(Currency currency) external; /// @notice Called by the user to net out some value owed to the user /// @dev Will revert if the requested amount is not available, consider using `mint` instead /// @dev Can also be used as a mechanism for free flash loans /// @param currency The currency to withdraw from the pool manager /// @param to The address to withdraw to /// @param amount The amount of currency to withdraw function take(Currency currency, address to, uint256 amount) external; /// @notice Called by the user to pay what is owed /// @return paid The amount of currency settled function settle() external payable returns (uint256 paid); /// @notice Called by the user to pay on behalf of another address /// @param recipient The address to credit for the payment /// @return paid The amount of currency settled function settleFor(address recipient) external payable returns (uint256 paid); /// @notice WARNING - Any currency that is cleared, will be non-retrievable, and locked in the contract permanently. /// A call to clear will zero out a positive balance WITHOUT a corresponding transfer. /// @dev This could be used to clear a balance that is considered dust. /// Additionally, the amount must be the exact positive balance. This is to enforce that the caller is aware of the amount being cleared. function clear(Currency currency, uint256 amount) external; /// @notice Called by the user to move value into ERC6909 balance /// @param to The address to mint the tokens to /// @param id The currency address to mint to ERC6909s, as a uint256 /// @param amount The amount of currency to mint /// @dev The id is converted to a uint160 to correspond to a currency address /// If the upper 12 bytes are not 0, they will be 0-ed out function mint(address to, uint256 id, uint256 amount) external; /// @notice Called by the user to move value from ERC6909 balance /// @param from The address to burn the tokens from /// @param id The currency address to burn from ERC6909s, as a uint256 /// @param amount The amount of currency to burn /// @dev The id is converted to a uint160 to correspond to a currency address /// If the upper 12 bytes are not 0, they will be 0-ed out function burn(address from, uint256 id, uint256 amount) external; /// @notice Updates the pools lp fees for the a pool that has enabled dynamic lp fees. /// @dev A swap fee totaling MAX_SWAP_FEE (100%) makes exact output swaps impossible since the input is entirely consumed by the fee /// @param key The key of the pool to update dynamic LP fees for /// @param newDynamicLPFee The new dynamic pool LP fee function updateDynamicLPFee(PoolKey memory key, uint24 newDynamicLPFee) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Currency} from "../types/Currency.sol"; import {PoolId} from "../types/PoolId.sol"; import {PoolKey} from "../types/PoolKey.sol"; /// @notice Interface for all protocol-fee related functions in the pool manager interface IProtocolFees { /// @notice Thrown when protocol fee is set too high error ProtocolFeeTooLarge(uint24 fee); /// @notice Thrown when collectProtocolFees or setProtocolFee is not called by the controller. error InvalidCaller(); /// @notice Thrown when collectProtocolFees is attempted on a token that is synced. error ProtocolFeeCurrencySynced(); /// @notice Emitted when the protocol fee controller address is updated in setProtocolFeeController. event ProtocolFeeControllerUpdated(address indexed protocolFeeController); /// @notice Emitted when the protocol fee is updated for a pool. event ProtocolFeeUpdated(PoolId indexed id, uint24 protocolFee); /// @notice Given a currency address, returns the protocol fees accrued in that currency /// @param currency The currency to check /// @return amount The amount of protocol fees accrued in the currency function protocolFeesAccrued(Currency currency) external view returns (uint256 amount); /// @notice Sets the protocol fee for the given pool /// @param key The key of the pool to set a protocol fee for /// @param newProtocolFee The fee to set function setProtocolFee(PoolKey memory key, uint24 newProtocolFee) external; /// @notice Sets the protocol fee controller /// @param controller The new protocol fee controller function setProtocolFeeController(address controller) external; /// @notice Collects the protocol fees for a given recipient and currency, returning the amount collected /// @dev This will revert if the contract is unlocked /// @param recipient The address to receive the protocol fees /// @param currency The currency to withdraw /// @param amount The amount of currency to withdraw /// @return amountCollected The amount of currency successfully withdrawn function collectProtocolFees(address recipient, Currency currency, uint256 amount) external returns (uint256 amountCollected); /// @notice Returns the current protocol fee controller address /// @return address The current protocol fee controller address function protocolFeeController() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Interface for the callback executed when an address unlocks the pool manager interface IUnlockCallback { /// @notice Called by the pool manager on `msg.sender` when the manager is unlocked /// @param data The data that was passed to the call to unlock /// @return Any data that you want to be returned from the unlock call function unlockCallback(bytes calldata data) external returns (bytes memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Minimal ERC20 interface for Uniswap /// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3 interface IERC20Minimal { /// @notice Returns an account's balance in the token /// @param account The account for which to look up the number of tokens it has, i.e. its balance /// @return The number of tokens held by the account function balanceOf(address account) external view returns (uint256); /// @notice Transfers the amount of token from the `msg.sender` to the recipient /// @param recipient The account that will receive the amount transferred /// @param amount The number of tokens to send from the sender to the recipient /// @return Returns true for a successful transfer, false for an unsuccessful transfer function transfer(address recipient, uint256 amount) external returns (bool); /// @notice Returns the current allowance given to a spender by an owner /// @param owner The account of the token owner /// @param spender The account of the token spender /// @return The current allowance granted by `owner` to `spender` function allowance(address owner, address spender) external view returns (uint256); /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` /// @param spender The account which will be allowed to spend a given amount of the owners tokens /// @param amount The amount of tokens allowed to be used by `spender` /// @return Returns true for a successful approval, false for unsuccessful function approve(address spender, uint256 amount) external returns (bool); /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` /// @param sender The account from which the transfer will be initiated /// @param recipient The recipient of the transfer /// @param amount The amount of the transfer /// @return Returns true for a successful transfer, false for unsuccessful function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. /// @param from The account from which the tokens were sent, i.e. the balance decreased /// @param to The account to which the tokens were sent, i.e. the balance increased /// @param value The amount of tokens that were transferred event Transfer(address indexed from, address indexed to, uint256 value); /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. /// @param owner The account that approved spending of its tokens /// @param spender The account for which the spending allowance was modified /// @param value The new allowance from the owner to the spender event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Interface for claims over a contract balance, wrapped as a ERC6909 interface IERC6909Claims { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OperatorSet(address indexed owner, address indexed operator, bool approved); event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount); event Transfer(address caller, address indexed from, address indexed to, uint256 indexed id, uint256 amount); /*////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Owner balance of an id. /// @param owner The address of the owner. /// @param id The id of the token. /// @return amount The balance of the token. function balanceOf(address owner, uint256 id) external view returns (uint256 amount); /// @notice Spender allowance of an id. /// @param owner The address of the owner. /// @param spender The address of the spender. /// @param id The id of the token. /// @return amount The allowance of the token. function allowance(address owner, address spender, uint256 id) external view returns (uint256 amount); /// @notice Checks if a spender is approved by an owner as an operator /// @param owner The address of the owner. /// @param spender The address of the spender. /// @return approved The approval status. function isOperator(address owner, address spender) external view returns (bool approved); /// @notice Transfers an amount of an id from the caller to a receiver. /// @param receiver The address of the receiver. /// @param id The id of the token. /// @param amount The amount of the token. /// @return bool True, always, unless the function reverts function transfer(address receiver, uint256 id, uint256 amount) external returns (bool); /// @notice Transfers an amount of an id from a sender to a receiver. /// @param sender The address of the sender. /// @param receiver The address of the receiver. /// @param id The id of the token. /// @param amount The amount of the token. /// @return bool True, always, unless the function reverts function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool); /// @notice Approves an amount of an id to a spender. /// @param spender The address of the spender. /// @param id The id of the token. /// @param amount The amount of the token. /// @return bool True, always function approve(address spender, uint256 id, uint256 amount) external returns (bool); /// @notice Sets or removes an operator for the caller. /// @param operator The address of the operator. /// @param approved The approval status. /// @return bool True, always function setOperator(address operator, bool approved) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title BitMath /// @dev This library provides functionality for computing bit properties of an unsigned integer /// @author Solady (https://github.com/Vectorized/solady/blob/8200a70e8dc2a77ecb074fc2e99a2a0d36547522/src/utils/LibBit.sol) library BitMath { /// @notice Returns the index of the most significant bit of the number, /// where the least significant bit is at index 0 and the most significant bit is at index 255 /// @param x the value for which to compute the most significant bit, must be greater than 0 /// @return r the index of the most significant bit function mostSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0); assembly ("memory-safe") { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0x0706060506020500060203020504000106050205030304010505030400000000)) } } /// @notice Returns the index of the least significant bit of the number, /// where the least significant bit is at index 0 and the most significant bit is at index 255 /// @param x the value for which to compute the least significant bit, must be greater than 0 /// @return r the index of the least significant bit function leastSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0); assembly ("memory-safe") { // Isolate the least significant bit. x := and(x, sub(0, x)) // For the upper 3 bits of the result, use a De Bruijn-like lookup. // Credit to adhusson: https://blog.adhusson.com/cheap-find-first-set-evm/ // forgefmt: disable-next-item r := shl(5, shr(252, shl(shl(2, shr(250, mul(x, 0xb6db6db6ddddddddd34d34d349249249210842108c6318c639ce739cffffffff))), 0x8040405543005266443200005020610674053026020000107506200176117077))) // For the lower 5 bits of the result, use a De Bruijn lookup. // forgefmt: disable-next-item r := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f), 0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405)) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import {Currency} from "../types/Currency.sol"; import {CustomRevert} from "./CustomRevert.sol"; library CurrencyReserves { using CustomRevert for bytes4; /// bytes32(uint256(keccak256("ReservesOf")) - 1) bytes32 constant RESERVES_OF_SLOT = 0x1e0745a7db1623981f0b2a5d4232364c00787266eb75ad546f190e6cebe9bd95; /// bytes32(uint256(keccak256("Currency")) - 1) bytes32 constant CURRENCY_SLOT = 0x27e098c505d44ec3574004bca052aabf76bd35004c182099d8c575fb238593b9; function getSyncedCurrency() internal view returns (Currency currency) { assembly ("memory-safe") { currency := tload(CURRENCY_SLOT) } } function resetCurrency() internal { assembly ("memory-safe") { tstore(CURRENCY_SLOT, 0) } } function syncCurrencyAndReserves(Currency currency, uint256 value) internal { assembly ("memory-safe") { tstore(CURRENCY_SLOT, and(currency, 0xffffffffffffffffffffffffffffffffffffffff)) tstore(RESERVES_OF_SLOT, value) } } function getSyncedReserves() internal view returns (uint256 value) { assembly ("memory-safe") { value := tload(RESERVES_OF_SLOT) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Library for reverting with custom errors efficiently /// @notice Contains functions for reverting with custom errors with different argument types efficiently /// @dev To use this library, declare `using CustomRevert for bytes4;` and replace `revert CustomError()` with /// `CustomError.selector.revertWith()` /// @dev The functions may tamper with the free memory pointer but it is fine since the call context is exited immediately library CustomRevert { /// @dev ERC-7751 error for wrapping bubbled up reverts error WrappedError(address target, bytes4 selector, bytes reason, bytes details); /// @dev Reverts with the selector of a custom error in the scratch space function revertWith(bytes4 selector) internal pure { assembly ("memory-safe") { mstore(0, selector) revert(0, 0x04) } } /// @dev Reverts with a custom error with an address argument in the scratch space function revertWith(bytes4 selector, address addr) internal pure { assembly ("memory-safe") { mstore(0, selector) mstore(0x04, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) revert(0, 0x24) } } /// @dev Reverts with a custom error with an int24 argument in the scratch space function revertWith(bytes4 selector, int24 value) internal pure { assembly ("memory-safe") { mstore(0, selector) mstore(0x04, signextend(2, value)) revert(0, 0x24) } } /// @dev Reverts with a custom error with a uint160 argument in the scratch space function revertWith(bytes4 selector, uint160 value) internal pure { assembly ("memory-safe") { mstore(0, selector) mstore(0x04, and(value, 0xffffffffffffffffffffffffffffffffffffffff)) revert(0, 0x24) } } /// @dev Reverts with a custom error with two int24 arguments function revertWith(bytes4 selector, int24 value1, int24 value2) internal pure { assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, selector) mstore(add(fmp, 0x04), signextend(2, value1)) mstore(add(fmp, 0x24), signextend(2, value2)) revert(fmp, 0x44) } } /// @dev Reverts with a custom error with two uint160 arguments function revertWith(bytes4 selector, uint160 value1, uint160 value2) internal pure { assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, selector) mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff)) revert(fmp, 0x44) } } /// @dev Reverts with a custom error with two address arguments function revertWith(bytes4 selector, address value1, address value2) internal pure { assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, selector) mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff)) revert(fmp, 0x44) } } /// @notice bubble up the revert message returned by a call and revert with a wrapped ERC-7751 error /// @dev this method can be vulnerable to revert data bombs function bubbleUpAndRevertWith( address revertingContract, bytes4 revertingFunctionSelector, bytes4 additionalContext ) internal pure { bytes4 wrappedErrorSelector = WrappedError.selector; assembly ("memory-safe") { // Ensure the size of the revert data is a multiple of 32 bytes let encodedDataSize := mul(div(add(returndatasize(), 31), 32), 32) let fmp := mload(0x40) // Encode wrapped error selector, address, function selector, offset, additional context, size, revert reason mstore(fmp, wrappedErrorSelector) mstore(add(fmp, 0x04), and(revertingContract, 0xffffffffffffffffffffffffffffffffffffffff)) mstore( add(fmp, 0x24), and(revertingFunctionSelector, 0xffffffff00000000000000000000000000000000000000000000000000000000) ) // offset revert reason mstore(add(fmp, 0x44), 0x80) // offset additional context mstore(add(fmp, 0x64), add(0xa0, encodedDataSize)) // size revert reason mstore(add(fmp, 0x84), returndatasize()) // revert reason returndatacopy(add(fmp, 0xa4), 0, returndatasize()) // size additional context mstore(add(fmp, add(0xa4, encodedDataSize)), 0x04) // additional context mstore( add(fmp, add(0xc4, encodedDataSize)), and(additionalContext, 0xffffffff00000000000000000000000000000000000000000000000000000000) ) revert(fmp, add(0xe4, encodedDataSize)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title FixedPoint128 /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) library FixedPoint128 { uint256 internal constant Q128 = 0x100000000000000000000000000000000; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title FixedPoint96 /// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format) /// @dev Used in SqrtPriceMath.sol library FixedPoint96 { uint8 internal constant RESOLUTION = 96; uint256 internal constant Q96 = 0x1000000000000000000000000; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0 = a * b; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly ("memory-safe") { let mm := mulmod(a, b, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { assembly ("memory-safe") { result := div(prod0, denominator) } return result; } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly ("memory-safe") { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly ("memory-safe") { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = (0 - denominator) & denominator; // Divide denominator by power of two assembly ("memory-safe") { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly ("memory-safe") { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly ("memory-safe") { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the preconditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) { unchecked { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) != 0) { require(++result > 0); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "../types/PoolKey.sol"; import {IHooks} from "../interfaces/IHooks.sol"; import {SafeCast} from "./SafeCast.sol"; import {LPFeeLibrary} from "./LPFeeLibrary.sol"; import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol"; import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol"; import {IPoolManager} from "../interfaces/IPoolManager.sol"; import {ParseBytes} from "./ParseBytes.sol"; import {CustomRevert} from "./CustomRevert.sol"; /// @notice V4 decides whether to invoke specific hooks by inspecting the least significant bits /// of the address that the hooks contract is deployed to. /// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400 /// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used. library Hooks { using LPFeeLibrary for uint24; using Hooks for IHooks; using SafeCast for int256; using BeforeSwapDeltaLibrary for BeforeSwapDelta; using ParseBytes for bytes; using CustomRevert for bytes4; uint160 internal constant ALL_HOOK_MASK = uint160((1 << 14) - 1); uint160 internal constant BEFORE_INITIALIZE_FLAG = 1 << 13; uint160 internal constant AFTER_INITIALIZE_FLAG = 1 << 12; uint160 internal constant BEFORE_ADD_LIQUIDITY_FLAG = 1 << 11; uint160 internal constant AFTER_ADD_LIQUIDITY_FLAG = 1 << 10; uint160 internal constant BEFORE_REMOVE_LIQUIDITY_FLAG = 1 << 9; uint160 internal constant AFTER_REMOVE_LIQUIDITY_FLAG = 1 << 8; uint160 internal constant BEFORE_SWAP_FLAG = 1 << 7; uint160 internal constant AFTER_SWAP_FLAG = 1 << 6; uint160 internal constant BEFORE_DONATE_FLAG = 1 << 5; uint160 internal constant AFTER_DONATE_FLAG = 1 << 4; uint160 internal constant BEFORE_SWAP_RETURNS_DELTA_FLAG = 1 << 3; uint160 internal constant AFTER_SWAP_RETURNS_DELTA_FLAG = 1 << 2; uint160 internal constant AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 1; uint160 internal constant AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 0; struct Permissions { bool beforeInitialize; bool afterInitialize; bool beforeAddLiquidity; bool afterAddLiquidity; bool beforeRemoveLiquidity; bool afterRemoveLiquidity; bool beforeSwap; bool afterSwap; bool beforeDonate; bool afterDonate; bool beforeSwapReturnDelta; bool afterSwapReturnDelta; bool afterAddLiquidityReturnDelta; bool afterRemoveLiquidityReturnDelta; } /// @notice Thrown if the address will not lead to the specified hook calls being called /// @param hooks The address of the hooks contract error HookAddressNotValid(address hooks); /// @notice Hook did not return its selector error InvalidHookResponse(); /// @notice Additional context for ERC-7751 wrapped error when a hook call fails error HookCallFailed(); /// @notice The hook's delta changed the swap from exactIn to exactOut or vice versa error HookDeltaExceedsSwapAmount(); /// @notice Utility function intended to be used in hook constructors to ensure /// the deployed hooks address causes the intended hooks to be called /// @param permissions The hooks that are intended to be called /// @dev permissions param is memory as the function will be called from constructors function validateHookPermissions(IHooks self, Permissions memory permissions) internal pure { if ( permissions.beforeInitialize != self.hasPermission(BEFORE_INITIALIZE_FLAG) || permissions.afterInitialize != self.hasPermission(AFTER_INITIALIZE_FLAG) || permissions.beforeAddLiquidity != self.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG) || permissions.afterAddLiquidity != self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG) || permissions.beforeRemoveLiquidity != self.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG) || permissions.afterRemoveLiquidity != self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG) || permissions.beforeSwap != self.hasPermission(BEFORE_SWAP_FLAG) || permissions.afterSwap != self.hasPermission(AFTER_SWAP_FLAG) || permissions.beforeDonate != self.hasPermission(BEFORE_DONATE_FLAG) || permissions.afterDonate != self.hasPermission(AFTER_DONATE_FLAG) || permissions.beforeSwapReturnDelta != self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG) || permissions.afterSwapReturnDelta != self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG) || permissions.afterAddLiquidityReturnDelta != self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG) || permissions.afterRemoveLiquidityReturnDelta != self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG) ) { HookAddressNotValid.selector.revertWith(address(self)); } } /// @notice Ensures that the hook address includes at least one hook flag or dynamic fees, or is the 0 address /// @param self The hook to verify /// @param fee The fee of the pool the hook is used with /// @return bool True if the hook address is valid function isValidHookAddress(IHooks self, uint24 fee) internal pure returns (bool) { // The hook can only have a flag to return a hook delta on an action if it also has the corresponding action flag if (!self.hasPermission(BEFORE_SWAP_FLAG) && self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)) return false; if (!self.hasPermission(AFTER_SWAP_FLAG) && self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG)) return false; if (!self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG) && self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG)) { return false; } if ( !self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG) && self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG) ) return false; // If there is no hook contract set, then fee cannot be dynamic // If a hook contract is set, it must have at least 1 flag set, or have a dynamic fee return address(self) == address(0) ? !fee.isDynamicFee() : (uint160(address(self)) & ALL_HOOK_MASK > 0 || fee.isDynamicFee()); } /// @notice performs a hook call using the given calldata on the given hook that doesn't return a delta /// @return result The complete data returned by the hook function callHook(IHooks self, bytes memory data) internal returns (bytes memory result) { bool success; assembly ("memory-safe") { success := call(gas(), self, 0, add(data, 0x20), mload(data), 0, 0) } // Revert with FailedHookCall, containing any error message to bubble up if (!success) CustomRevert.bubbleUpAndRevertWith(address(self), bytes4(data), HookCallFailed.selector); // The call was successful, fetch the returned data assembly ("memory-safe") { // allocate result byte array from the free memory pointer result := mload(0x40) // store new free memory pointer at the end of the array padded to 32 bytes mstore(0x40, add(result, and(add(returndatasize(), 0x3f), not(0x1f)))) // store length in memory mstore(result, returndatasize()) // copy return data to result returndatacopy(add(result, 0x20), 0, returndatasize()) } // Length must be at least 32 to contain the selector. Check expected selector and returned selector match. if (result.length < 32 || result.parseSelector() != data.parseSelector()) { InvalidHookResponse.selector.revertWith(); } } /// @notice performs a hook call using the given calldata on the given hook /// @return int256 The delta returned by the hook function callHookWithReturnDelta(IHooks self, bytes memory data, bool parseReturn) internal returns (int256) { bytes memory result = callHook(self, data); // If this hook wasn't meant to return something, default to 0 delta if (!parseReturn) return 0; // A length of 64 bytes is required to return a bytes4, and a 32 byte delta if (result.length != 64) InvalidHookResponse.selector.revertWith(); return result.parseReturnDelta(); } /// @notice modifier to prevent calling a hook if they initiated the action modifier noSelfCall(IHooks self) { if (msg.sender != address(self)) { _; } } /// @notice calls beforeInitialize hook if permissioned and validates return value function beforeInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96) internal noSelfCall(self) { if (self.hasPermission(BEFORE_INITIALIZE_FLAG)) { self.callHook(abi.encodeCall(IHooks.beforeInitialize, (msg.sender, key, sqrtPriceX96))); } } /// @notice calls afterInitialize hook if permissioned and validates return value function afterInitialize(IHooks self, PoolKey memory key, uint160 sqrtPriceX96, int24 tick) internal noSelfCall(self) { if (self.hasPermission(AFTER_INITIALIZE_FLAG)) { self.callHook(abi.encodeCall(IHooks.afterInitialize, (msg.sender, key, sqrtPriceX96, tick))); } } /// @notice calls beforeModifyLiquidity hook if permissioned and validates return value function beforeModifyLiquidity( IHooks self, PoolKey memory key, IPoolManager.ModifyLiquidityParams memory params, bytes calldata hookData ) internal noSelfCall(self) { if (params.liquidityDelta > 0 && self.hasPermission(BEFORE_ADD_LIQUIDITY_FLAG)) { self.callHook(abi.encodeCall(IHooks.beforeAddLiquidity, (msg.sender, key, params, hookData))); } else if (params.liquidityDelta <= 0 && self.hasPermission(BEFORE_REMOVE_LIQUIDITY_FLAG)) { self.callHook(abi.encodeCall(IHooks.beforeRemoveLiquidity, (msg.sender, key, params, hookData))); } } /// @notice calls afterModifyLiquidity hook if permissioned and validates return value function afterModifyLiquidity( IHooks self, PoolKey memory key, IPoolManager.ModifyLiquidityParams memory params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) internal returns (BalanceDelta callerDelta, BalanceDelta hookDelta) { if (msg.sender == address(self)) return (delta, BalanceDeltaLibrary.ZERO_DELTA); callerDelta = delta; if (params.liquidityDelta > 0) { if (self.hasPermission(AFTER_ADD_LIQUIDITY_FLAG)) { hookDelta = BalanceDelta.wrap( self.callHookWithReturnDelta( abi.encodeCall( IHooks.afterAddLiquidity, (msg.sender, key, params, delta, feesAccrued, hookData) ), self.hasPermission(AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG) ) ); callerDelta = callerDelta - hookDelta; } } else { if (self.hasPermission(AFTER_REMOVE_LIQUIDITY_FLAG)) { hookDelta = BalanceDelta.wrap( self.callHookWithReturnDelta( abi.encodeCall( IHooks.afterRemoveLiquidity, (msg.sender, key, params, delta, feesAccrued, hookData) ), self.hasPermission(AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG) ) ); callerDelta = callerDelta - hookDelta; } } } /// @notice calls beforeSwap hook if permissioned and validates return value function beforeSwap(IHooks self, PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData) internal returns (int256 amountToSwap, BeforeSwapDelta hookReturn, uint24 lpFeeOverride) { amountToSwap = params.amountSpecified; if (msg.sender == address(self)) return (amountToSwap, BeforeSwapDeltaLibrary.ZERO_DELTA, lpFeeOverride); if (self.hasPermission(BEFORE_SWAP_FLAG)) { bytes memory result = callHook(self, abi.encodeCall(IHooks.beforeSwap, (msg.sender, key, params, hookData))); // A length of 96 bytes is required to return a bytes4, a 32 byte delta, and an LP fee if (result.length != 96) InvalidHookResponse.selector.revertWith(); // dynamic fee pools that want to override the cache fee, return a valid fee with the override flag. If override flag // is set but an invalid fee is returned, the transaction will revert. Otherwise the current LP fee will be used if (key.fee.isDynamicFee()) lpFeeOverride = result.parseFee(); // skip this logic for the case where the hook return is 0 if (self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)) { hookReturn = BeforeSwapDelta.wrap(result.parseReturnDelta()); // any return in unspecified is passed to the afterSwap hook for handling int128 hookDeltaSpecified = hookReturn.getSpecifiedDelta(); // Update the swap amount according to the hook's return, and check that the swap type doesn't change (exact input/output) if (hookDeltaSpecified != 0) { bool exactInput = amountToSwap < 0; amountToSwap += hookDeltaSpecified; if (exactInput ? amountToSwap > 0 : amountToSwap < 0) { HookDeltaExceedsSwapAmount.selector.revertWith(); } } } } } /// @notice calls afterSwap hook if permissioned and validates return value function afterSwap( IHooks self, PoolKey memory key, IPoolManager.SwapParams memory params, BalanceDelta swapDelta, bytes calldata hookData, BeforeSwapDelta beforeSwapHookReturn ) internal returns (BalanceDelta, BalanceDelta) { if (msg.sender == address(self)) return (swapDelta, BalanceDeltaLibrary.ZERO_DELTA); int128 hookDeltaSpecified = beforeSwapHookReturn.getSpecifiedDelta(); int128 hookDeltaUnspecified = beforeSwapHookReturn.getUnspecifiedDelta(); if (self.hasPermission(AFTER_SWAP_FLAG)) { hookDeltaUnspecified += self.callHookWithReturnDelta( abi.encodeCall(IHooks.afterSwap, (msg.sender, key, params, swapDelta, hookData)), self.hasPermission(AFTER_SWAP_RETURNS_DELTA_FLAG) ).toInt128(); } BalanceDelta hookDelta; if (hookDeltaUnspecified != 0 || hookDeltaSpecified != 0) { hookDelta = (params.amountSpecified < 0 == params.zeroForOne) ? toBalanceDelta(hookDeltaSpecified, hookDeltaUnspecified) : toBalanceDelta(hookDeltaUnspecified, hookDeltaSpecified); // the caller has to pay for (or receive) the hook's delta swapDelta = swapDelta - hookDelta; } return (swapDelta, hookDelta); } /// @notice calls beforeDonate hook if permissioned and validates return value function beforeDonate(IHooks self, PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) internal noSelfCall(self) { if (self.hasPermission(BEFORE_DONATE_FLAG)) { self.callHook(abi.encodeCall(IHooks.beforeDonate, (msg.sender, key, amount0, amount1, hookData))); } } /// @notice calls afterDonate hook if permissioned and validates return value function afterDonate(IHooks self, PoolKey memory key, uint256 amount0, uint256 amount1, bytes calldata hookData) internal noSelfCall(self) { if (self.hasPermission(AFTER_DONATE_FLAG)) { self.callHook(abi.encodeCall(IHooks.afterDonate, (msg.sender, key, amount0, amount1, hookData))); } } function hasPermission(IHooks self, uint160 flag) internal pure returns (bool) { return uint160(address(self)) & flag != 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {CustomRevert} from "./CustomRevert.sol"; /// @notice Library of helper functions for a pools LP fee library LPFeeLibrary { using LPFeeLibrary for uint24; using CustomRevert for bytes4; /// @notice Thrown when the static or dynamic fee on a pool exceeds 100%. error LPFeeTooLarge(uint24 fee); /// @notice An lp fee of exactly 0b1000000... signals a dynamic fee pool. This isn't a valid static fee as it is > MAX_LP_FEE uint24 public constant DYNAMIC_FEE_FLAG = 0x800000; /// @notice the second bit of the fee returned by beforeSwap is used to signal if the stored LP fee should be overridden in this swap // only dynamic-fee pools can return a fee via the beforeSwap hook uint24 public constant OVERRIDE_FEE_FLAG = 0x400000; /// @notice mask to remove the override fee flag from a fee returned by the beforeSwaphook uint24 public constant REMOVE_OVERRIDE_MASK = 0xBFFFFF; /// @notice the lp fee is represented in hundredths of a bip, so the max is 100% uint24 public constant MAX_LP_FEE = 1000000; /// @notice returns true if a pool's LP fee signals that the pool has a dynamic fee /// @param self The fee to check /// @return bool True of the fee is dynamic function isDynamicFee(uint24 self) internal pure returns (bool) { return self == DYNAMIC_FEE_FLAG; } /// @notice returns true if an LP fee is valid, aka not above the maximum permitted fee /// @param self The fee to check /// @return bool True of the fee is valid function isValid(uint24 self) internal pure returns (bool) { return self <= MAX_LP_FEE; } /// @notice validates whether an LP fee is larger than the maximum, and reverts if invalid /// @param self The fee to validate function validate(uint24 self) internal pure { if (!self.isValid()) LPFeeTooLarge.selector.revertWith(self); } /// @notice gets and validates the initial LP fee for a pool. Dynamic fee pools have an initial fee of 0. /// @dev if a dynamic fee pool wants a non-0 initial fee, it should call `updateDynamicLPFee` in the afterInitialize hook /// @param self The fee to get the initial LP from /// @return initialFee 0 if the fee is dynamic, otherwise the fee (if valid) function getInitialLPFee(uint24 self) internal pure returns (uint24) { // the initial fee for a dynamic fee pool is 0 if (self.isDynamicFee()) return 0; self.validate(); return self; } /// @notice returns true if the fee has the override flag set (2nd highest bit of the uint24) /// @param self The fee to check /// @return bool True of the fee has the override flag set function isOverride(uint24 self) internal pure returns (bool) { return self & OVERRIDE_FEE_FLAG != 0; } /// @notice returns a fee with the override flag removed /// @param self The fee to remove the override flag from /// @return fee The fee without the override flag set function removeOverrideFlag(uint24 self) internal pure returns (uint24) { return self & REMOVE_OVERRIDE_MASK; } /// @notice Removes the override flag and validates the fee (reverts if the fee is too large) /// @param self The fee to remove the override flag from, and then validate /// @return fee The fee without the override flag set (if valid) function removeOverrideFlagAndValidate(uint24 self) internal pure returns (uint24 fee) { fee = self.removeOverrideFlag(); fee.validate(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Math library for liquidity library LiquidityMath { /// @notice Add a signed liquidity delta to liquidity and revert if it overflows or underflows /// @param x The liquidity before change /// @param y The delta by which liquidity should be changed /// @return z The liquidity delta function addDelta(uint128 x, int128 y) internal pure returns (uint128 z) { assembly ("memory-safe") { z := add(and(x, 0xffffffffffffffffffffffffffffffff), signextend(15, y)) if shr(128, z) { // revert SafeCastOverflow() mstore(0, 0x93dafdf1) revert(0x1c, 0x04) } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; /// @notice This is a temporary library that allows us to use transient storage (tstore/tload) /// TODO: This library can be deleted when we have the transient keyword support in solidity. library Lock { // The slot holding the unlocked state, transiently. bytes32(uint256(keccak256("Unlocked")) - 1) bytes32 internal constant IS_UNLOCKED_SLOT = 0xc090fc4683624cfc3884e9d8de5eca132f2d0ec062aff75d43c0465d5ceeab23; function unlock() internal { assembly ("memory-safe") { // unlock tstore(IS_UNLOCKED_SLOT, true) } } function lock() internal { assembly ("memory-safe") { tstore(IS_UNLOCKED_SLOT, false) } } function isUnlocked() internal view returns (bool unlocked) { assembly ("memory-safe") { unlocked := tload(IS_UNLOCKED_SLOT) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; /// @notice This is a temporary library that allows us to use transient storage (tstore/tload) /// for the nonzero delta count. /// TODO: This library can be deleted when we have the transient keyword support in solidity. library NonzeroDeltaCount { // The slot holding the number of nonzero deltas. bytes32(uint256(keccak256("NonzeroDeltaCount")) - 1) bytes32 internal constant NONZERO_DELTA_COUNT_SLOT = 0x7d4b3164c6e45b97e7d87b7125a44c5828d005af88f9d751cfd78729c5d99a0b; function read() internal view returns (uint256 count) { assembly ("memory-safe") { count := tload(NONZERO_DELTA_COUNT_SLOT) } } function increment() internal { assembly ("memory-safe") { let count := tload(NONZERO_DELTA_COUNT_SLOT) count := add(count, 1) tstore(NONZERO_DELTA_COUNT_SLOT, count) } } /// @notice Potential to underflow. Ensure checks are performed by integrating contracts to ensure this does not happen. /// Current usage ensures this will not happen because we call decrement with known boundaries (only up to the number of times we call increment). function decrement() internal { assembly ("memory-safe") { let count := tload(NONZERO_DELTA_COUNT_SLOT) count := sub(count, 1) tstore(NONZERO_DELTA_COUNT_SLOT, count) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Parses bytes returned from hooks and the byte selector used to check return selectors from hooks. /// @dev parseSelector also is used to parse the expected selector /// For parsing hook returns, note that all hooks return either bytes4 or (bytes4, 32-byte-delta) or (bytes4, 32-byte-delta, uint24). library ParseBytes { function parseSelector(bytes memory result) internal pure returns (bytes4 selector) { // equivalent: (selector,) = abi.decode(result, (bytes4, int256)); assembly ("memory-safe") { selector := mload(add(result, 0x20)) } } function parseFee(bytes memory result) internal pure returns (uint24 lpFee) { // equivalent: (,, lpFee) = abi.decode(result, (bytes4, int256, uint24)); assembly ("memory-safe") { lpFee := mload(add(result, 0x60)) } } function parseReturnDelta(bytes memory result) internal pure returns (int256 hookReturn) { // equivalent: (, hookReturnDelta) = abi.decode(result, (bytes4, int256)); assembly ("memory-safe") { hookReturn := mload(add(result, 0x40)) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import {FullMath} from "./FullMath.sol"; import {FixedPoint128} from "./FixedPoint128.sol"; import {LiquidityMath} from "./LiquidityMath.sol"; import {CustomRevert} from "./CustomRevert.sol"; /// @title Position /// @notice Positions represent an owner address' liquidity between a lower and upper tick boundary /// @dev Positions store additional state for tracking fees owed to the position library Position { using CustomRevert for bytes4; /// @notice Cannot update a position with no liquidity error CannotUpdateEmptyPosition(); // info stored for each user's position struct State { // the amount of liquidity owned by this position uint128 liquidity; // fee growth per unit of liquidity as of the last update to liquidity or fees owed uint256 feeGrowthInside0LastX128; uint256 feeGrowthInside1LastX128; } /// @notice Returns the State struct of a position, given an owner and position boundaries /// @param self The mapping containing all user positions /// @param owner The address of the position owner /// @param tickLower The lower tick boundary of the position /// @param tickUpper The upper tick boundary of the position /// @param salt A unique value to differentiate between multiple positions in the same range /// @return position The position info struct of the given owners' position function get(mapping(bytes32 => State) storage self, address owner, int24 tickLower, int24 tickUpper, bytes32 salt) internal view returns (State storage position) { bytes32 positionKey = calculatePositionKey(owner, tickLower, tickUpper, salt); position = self[positionKey]; } /// @notice A helper function to calculate the position key /// @param owner The address of the position owner /// @param tickLower the lower tick boundary of the position /// @param tickUpper the upper tick boundary of the position /// @param salt A unique value to differentiate between multiple positions in the same range, by the same owner. Passed in by the caller. function calculatePositionKey(address owner, int24 tickLower, int24 tickUpper, bytes32 salt) internal pure returns (bytes32 positionKey) { // positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt)) assembly ("memory-safe") { let fmp := mload(0x40) mstore(add(fmp, 0x26), salt) // [0x26, 0x46) mstore(add(fmp, 0x06), tickUpper) // [0x23, 0x26) mstore(add(fmp, 0x03), tickLower) // [0x20, 0x23) mstore(fmp, owner) // [0x0c, 0x20) positionKey := keccak256(add(fmp, 0x0c), 0x3a) // len is 58 bytes // now clean the memory we used mstore(add(fmp, 0x40), 0) // fmp+0x40 held salt mstore(add(fmp, 0x20), 0) // fmp+0x20 held tickLower, tickUpper, salt mstore(fmp, 0) // fmp held owner } } /// @notice Credits accumulated fees to a user's position /// @param self The individual position to update /// @param liquidityDelta The change in pool liquidity as a result of the position update /// @param feeGrowthInside0X128 The all-time fee growth in currency0, per unit of liquidity, inside the position's tick boundaries /// @param feeGrowthInside1X128 The all-time fee growth in currency1, per unit of liquidity, inside the position's tick boundaries /// @return feesOwed0 The amount of currency0 owed to the position owner /// @return feesOwed1 The amount of currency1 owed to the position owner function update( State storage self, int128 liquidityDelta, uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128 ) internal returns (uint256 feesOwed0, uint256 feesOwed1) { uint128 liquidity = self.liquidity; if (liquidityDelta == 0) { // disallow pokes for 0 liquidity positions if (liquidity == 0) CannotUpdateEmptyPosition.selector.revertWith(); } else { self.liquidity = LiquidityMath.addDelta(liquidity, liquidityDelta); } // calculate accumulated fees. overflow in the subtraction of fee growth is expected unchecked { feesOwed0 = FullMath.mulDiv(feeGrowthInside0X128 - self.feeGrowthInside0LastX128, liquidity, FixedPoint128.Q128); feesOwed1 = FullMath.mulDiv(feeGrowthInside1X128 - self.feeGrowthInside1LastX128, liquidity, FixedPoint128.Q128); } // update the position self.feeGrowthInside0LastX128 = feeGrowthInside0X128; self.feeGrowthInside1LastX128 = feeGrowthInside1X128; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {CustomRevert} from "./CustomRevert.sol"; /// @title Safe casting methods /// @notice Contains methods for safely casting between types library SafeCast { using CustomRevert for bytes4; error SafeCastOverflow(); /// @notice Cast a uint256 to a uint160, revert on overflow /// @param x The uint256 to be downcasted /// @return y The downcasted integer, now type uint160 function toUint160(uint256 x) internal pure returns (uint160 y) { y = uint160(x); if (y != x) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a uint256 to a uint128, revert on overflow /// @param x The uint256 to be downcasted /// @return y The downcasted integer, now type uint128 function toUint128(uint256 x) internal pure returns (uint128 y) { y = uint128(x); if (x != y) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a int128 to a uint128, revert on overflow or underflow /// @param x The int128 to be casted /// @return y The casted integer, now type uint128 function toUint128(int128 x) internal pure returns (uint128 y) { if (x < 0) SafeCastOverflow.selector.revertWith(); y = uint128(x); } /// @notice Cast a int256 to a int128, revert on overflow or underflow /// @param x The int256 to be downcasted /// @return y The downcasted integer, now type int128 function toInt128(int256 x) internal pure returns (int128 y) { y = int128(x); if (y != x) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a uint256 to a int256, revert on overflow /// @param x The uint256 to be casted /// @return y The casted integer, now type int256 function toInt256(uint256 x) internal pure returns (int256 y) { y = int256(x); if (y < 0) SafeCastOverflow.selector.revertWith(); } /// @notice Cast a uint256 to a int128, revert on overflow /// @param x The uint256 to be downcasted /// @return The downcasted integer, now type int128 function toInt128(uint256 x) internal pure returns (int128) { if (x >= 1 << 127) SafeCastOverflow.selector.revertWith(); return int128(int256(x)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolId} from "../types/PoolId.sol"; import {IPoolManager} from "../interfaces/IPoolManager.sol"; import {Position} from "./Position.sol"; /// @notice A helper library to provide state getters that use extsload library StateLibrary { /// @notice index of pools mapping in the PoolManager bytes32 public constant POOLS_SLOT = bytes32(uint256(6)); /// @notice index of feeGrowthGlobal0X128 in Pool.State uint256 public constant FEE_GROWTH_GLOBAL0_OFFSET = 1; // feeGrowthGlobal1X128 offset in Pool.State = 2 /// @notice index of liquidity in Pool.State uint256 public constant LIQUIDITY_OFFSET = 3; /// @notice index of TicksInfo mapping in Pool.State: mapping(int24 => TickInfo) ticks; uint256 public constant TICKS_OFFSET = 4; /// @notice index of tickBitmap mapping in Pool.State uint256 public constant TICK_BITMAP_OFFSET = 5; /// @notice index of Position.State mapping in Pool.State: mapping(bytes32 => Position.State) positions; uint256 public constant POSITIONS_OFFSET = 6; /** * @notice Get Slot0 of the pool: sqrtPriceX96, tick, protocolFee, lpFee * @dev Corresponds to pools[poolId].slot0 * @param manager The pool manager contract. * @param poolId The ID of the pool. * @return sqrtPriceX96 The square root of the price of the pool, in Q96 precision. * @return tick The current tick of the pool. * @return protocolFee The protocol fee of the pool. * @return lpFee The swap fee of the pool. */ function getSlot0(IPoolManager manager, PoolId poolId) internal view returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); bytes32 data = manager.extsload(stateSlot); // 24 bits |24bits|24bits |24 bits|160 bits // 0x000000 |000bb8|000000 |ffff75 |0000000000000000fe3aa841ba359daa0ea9eff7 // ---------- | fee |protocolfee | tick | sqrtPriceX96 assembly ("memory-safe") { // bottom 160 bits of data sqrtPriceX96 := and(data, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) // next 24 bits of data tick := signextend(2, shr(160, data)) // next 24 bits of data protocolFee := and(shr(184, data), 0xFFFFFF) // last 24 bits of data lpFee := and(shr(208, data), 0xFFFFFF) } } /** * @notice Retrieves the tick information of a pool at a specific tick. * @dev Corresponds to pools[poolId].ticks[tick] * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tick The tick to retrieve information for. * @return liquidityGross The total position liquidity that references this tick * @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left) * @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) * @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) */ function getTickInfo(IPoolManager manager, PoolId poolId, int24 tick) internal view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128 ) { bytes32 slot = _getTickInfoSlot(poolId, tick); // read all 3 words of the TickInfo struct bytes32[] memory data = manager.extsload(slot, 3); assembly ("memory-safe") { let firstWord := mload(add(data, 32)) liquidityNet := sar(128, firstWord) liquidityGross := and(firstWord, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) feeGrowthOutside0X128 := mload(add(data, 64)) feeGrowthOutside1X128 := mload(add(data, 96)) } } /** * @notice Retrieves the liquidity information of a pool at a specific tick. * @dev Corresponds to pools[poolId].ticks[tick].liquidityGross and pools[poolId].ticks[tick].liquidityNet. A more gas efficient version of getTickInfo * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tick The tick to retrieve liquidity for. * @return liquidityGross The total position liquidity that references this tick * @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left) */ function getTickLiquidity(IPoolManager manager, PoolId poolId, int24 tick) internal view returns (uint128 liquidityGross, int128 liquidityNet) { bytes32 slot = _getTickInfoSlot(poolId, tick); bytes32 value = manager.extsload(slot); assembly ("memory-safe") { liquidityNet := sar(128, value) liquidityGross := and(value, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) } } /** * @notice Retrieves the fee growth outside a tick range of a pool * @dev Corresponds to pools[poolId].ticks[tick].feeGrowthOutside0X128 and pools[poolId].ticks[tick].feeGrowthOutside1X128. A more gas efficient version of getTickInfo * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tick The tick to retrieve fee growth for. * @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) * @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) */ function getTickFeeGrowthOutside(IPoolManager manager, PoolId poolId, int24 tick) internal view returns (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128) { bytes32 slot = _getTickInfoSlot(poolId, tick); // offset by 1 word, since the first word is liquidityGross + liquidityNet bytes32[] memory data = manager.extsload(bytes32(uint256(slot) + 1), 2); assembly ("memory-safe") { feeGrowthOutside0X128 := mload(add(data, 32)) feeGrowthOutside1X128 := mload(add(data, 64)) } } /** * @notice Retrieves the global fee growth of a pool. * @dev Corresponds to pools[poolId].feeGrowthGlobal0X128 and pools[poolId].feeGrowthGlobal1X128 * @param manager The pool manager contract. * @param poolId The ID of the pool. * @return feeGrowthGlobal0 The global fee growth for token0. * @return feeGrowthGlobal1 The global fee growth for token1. */ function getFeeGrowthGlobals(IPoolManager manager, PoolId poolId) internal view returns (uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State, `uint256 feeGrowthGlobal0X128` bytes32 slot_feeGrowthGlobal0X128 = bytes32(uint256(stateSlot) + FEE_GROWTH_GLOBAL0_OFFSET); // read the 2 words of feeGrowthGlobal bytes32[] memory data = manager.extsload(slot_feeGrowthGlobal0X128, 2); assembly ("memory-safe") { feeGrowthGlobal0 := mload(add(data, 32)) feeGrowthGlobal1 := mload(add(data, 64)) } } /** * @notice Retrieves total the liquidity of a pool. * @dev Corresponds to pools[poolId].liquidity * @param manager The pool manager contract. * @param poolId The ID of the pool. * @return liquidity The liquidity of the pool. */ function getLiquidity(IPoolManager manager, PoolId poolId) internal view returns (uint128 liquidity) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State: `uint128 liquidity` bytes32 slot = bytes32(uint256(stateSlot) + LIQUIDITY_OFFSET); liquidity = uint128(uint256(manager.extsload(slot))); } /** * @notice Retrieves the tick bitmap of a pool at a specific tick. * @dev Corresponds to pools[poolId].tickBitmap[tick] * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tick The tick to retrieve the bitmap for. * @return tickBitmap The bitmap of the tick. */ function getTickBitmap(IPoolManager manager, PoolId poolId, int16 tick) internal view returns (uint256 tickBitmap) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State: `mapping(int16 => uint256) tickBitmap;` bytes32 tickBitmapMapping = bytes32(uint256(stateSlot) + TICK_BITMAP_OFFSET); // slot id of the mapping key: `pools[poolId].tickBitmap[tick] bytes32 slot = keccak256(abi.encodePacked(int256(tick), tickBitmapMapping)); tickBitmap = uint256(manager.extsload(slot)); } /** * @notice Retrieves the position information of a pool without needing to calculate the `positionId`. * @dev Corresponds to pools[poolId].positions[positionId] * @param poolId The ID of the pool. * @param owner The owner of the liquidity position. * @param tickLower The lower tick of the liquidity range. * @param tickUpper The upper tick of the liquidity range. * @param salt The bytes32 randomness to further distinguish position state. * @return liquidity The liquidity of the position. * @return feeGrowthInside0LastX128 The fee growth inside the position for token0. * @return feeGrowthInside1LastX128 The fee growth inside the position for token1. */ function getPositionInfo( IPoolManager manager, PoolId poolId, address owner, int24 tickLower, int24 tickUpper, bytes32 salt ) internal view returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128) { // positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt)) bytes32 positionKey = Position.calculatePositionKey(owner, tickLower, tickUpper, salt); (liquidity, feeGrowthInside0LastX128, feeGrowthInside1LastX128) = getPositionInfo(manager, poolId, positionKey); } /** * @notice Retrieves the position information of a pool at a specific position ID. * @dev Corresponds to pools[poolId].positions[positionId] * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param positionId The ID of the position. * @return liquidity The liquidity of the position. * @return feeGrowthInside0LastX128 The fee growth inside the position for token0. * @return feeGrowthInside1LastX128 The fee growth inside the position for token1. */ function getPositionInfo(IPoolManager manager, PoolId poolId, bytes32 positionId) internal view returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128) { bytes32 slot = _getPositionInfoSlot(poolId, positionId); // read all 3 words of the Position.State struct bytes32[] memory data = manager.extsload(slot, 3); assembly ("memory-safe") { liquidity := mload(add(data, 32)) feeGrowthInside0LastX128 := mload(add(data, 64)) feeGrowthInside1LastX128 := mload(add(data, 96)) } } /** * @notice Retrieves the liquidity of a position. * @dev Corresponds to pools[poolId].positions[positionId].liquidity. More gas efficient for just retrieiving liquidity as compared to getPositionInfo * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param positionId The ID of the position. * @return liquidity The liquidity of the position. */ function getPositionLiquidity(IPoolManager manager, PoolId poolId, bytes32 positionId) internal view returns (uint128 liquidity) { bytes32 slot = _getPositionInfoSlot(poolId, positionId); liquidity = uint128(uint256(manager.extsload(slot))); } /** * @notice Calculate the fee growth inside a tick range of a pool * @dev pools[poolId].feeGrowthInside0LastX128 in Position.State is cached and can become stale. This function will calculate the up to date feeGrowthInside * @param manager The pool manager contract. * @param poolId The ID of the pool. * @param tickLower The lower tick of the range. * @param tickUpper The upper tick of the range. * @return feeGrowthInside0X128 The fee growth inside the tick range for token0. * @return feeGrowthInside1X128 The fee growth inside the tick range for token1. */ function getFeeGrowthInside(IPoolManager manager, PoolId poolId, int24 tickLower, int24 tickUpper) internal view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128) { (uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) = getFeeGrowthGlobals(manager, poolId); (uint256 lowerFeeGrowthOutside0X128, uint256 lowerFeeGrowthOutside1X128) = getTickFeeGrowthOutside(manager, poolId, tickLower); (uint256 upperFeeGrowthOutside0X128, uint256 upperFeeGrowthOutside1X128) = getTickFeeGrowthOutside(manager, poolId, tickUpper); (, int24 tickCurrent,,) = getSlot0(manager, poolId); unchecked { if (tickCurrent < tickLower) { feeGrowthInside0X128 = lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128; feeGrowthInside1X128 = lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128; } else if (tickCurrent >= tickUpper) { feeGrowthInside0X128 = upperFeeGrowthOutside0X128 - lowerFeeGrowthOutside0X128; feeGrowthInside1X128 = upperFeeGrowthOutside1X128 - lowerFeeGrowthOutside1X128; } else { feeGrowthInside0X128 = feeGrowthGlobal0X128 - lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128; feeGrowthInside1X128 = feeGrowthGlobal1X128 - lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128; } } } function _getPoolStateSlot(PoolId poolId) internal pure returns (bytes32) { return keccak256(abi.encodePacked(PoolId.unwrap(poolId), POOLS_SLOT)); } function _getTickInfoSlot(PoolId poolId, int24 tick) internal pure returns (bytes32) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State: `mapping(int24 => TickInfo) ticks` bytes32 ticksMappingSlot = bytes32(uint256(stateSlot) + TICKS_OFFSET); // slot key of the tick key: `pools[poolId].ticks[tick] return keccak256(abi.encodePacked(int256(tick), ticksMappingSlot)); } function _getPositionInfoSlot(PoolId poolId, bytes32 positionId) internal pure returns (bytes32) { // slot key of Pool.State value: `pools[poolId]` bytes32 stateSlot = _getPoolStateSlot(poolId); // Pool.State: `mapping(bytes32 => Position.State) positions;` bytes32 positionMapping = bytes32(uint256(stateSlot) + POSITIONS_OFFSET); // slot of the mapping key: `pools[poolId].positions[positionId] return keccak256(abi.encodePacked(positionId, positionMapping)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {BitMath} from "./BitMath.sol"; import {CustomRevert} from "./CustomRevert.sol"; /// @title Math library for computing sqrt prices from ticks and vice versa /// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports /// prices between 2**-128 and 2**128 library TickMath { using CustomRevert for bytes4; /// @notice Thrown when the tick passed to #getSqrtPriceAtTick is not between MIN_TICK and MAX_TICK error InvalidTick(int24 tick); /// @notice Thrown when the price passed to #getTickAtSqrtPrice does not correspond to a price between MIN_TICK and MAX_TICK error InvalidSqrtPrice(uint160 sqrtPriceX96); /// @dev The minimum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**-128 /// @dev If ever MIN_TICK and MAX_TICK are not centered around 0, the absTick logic in getSqrtPriceAtTick cannot be used int24 internal constant MIN_TICK = -887272; /// @dev The maximum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**128 /// @dev If ever MIN_TICK and MAX_TICK are not centered around 0, the absTick logic in getSqrtPriceAtTick cannot be used int24 internal constant MAX_TICK = 887272; /// @dev The minimum tick spacing value drawn from the range of type int16 that is greater than 0, i.e. min from the range [1, 32767] int24 internal constant MIN_TICK_SPACING = 1; /// @dev The maximum tick spacing value drawn from the range of type int16, i.e. max from the range [1, 32767] int24 internal constant MAX_TICK_SPACING = type(int16).max; /// @dev The minimum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MIN_TICK) uint160 internal constant MIN_SQRT_PRICE = 4295128739; /// @dev The maximum value that can be returned from #getSqrtPriceAtTick. Equivalent to getSqrtPriceAtTick(MAX_TICK) uint160 internal constant MAX_SQRT_PRICE = 1461446703485210103287273052203988822378723970342; /// @dev A threshold used for optimized bounds check, equals `MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1` uint160 internal constant MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE = 1461446703485210103287273052203988822378723970342 - 4295128739 - 1; /// @notice Given a tickSpacing, compute the maximum usable tick function maxUsableTick(int24 tickSpacing) internal pure returns (int24) { unchecked { return (MAX_TICK / tickSpacing) * tickSpacing; } } /// @notice Given a tickSpacing, compute the minimum usable tick function minUsableTick(int24 tickSpacing) internal pure returns (int24) { unchecked { return (MIN_TICK / tickSpacing) * tickSpacing; } } /// @notice Calculates sqrt(1.0001^tick) * 2^96 /// @dev Throws if |tick| > max tick /// @param tick The input tick for the above formula /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the price of the two assets (currency1/currency0) /// at the given tick function getSqrtPriceAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) { unchecked { uint256 absTick; assembly ("memory-safe") { tick := signextend(2, tick) // mask = 0 if tick >= 0 else -1 (all 1s) let mask := sar(255, tick) // if tick >= 0, |tick| = tick = 0 ^ tick // if tick < 0, |tick| = ~~|tick| = ~(-|tick| - 1) = ~(tick - 1) = (-1) ^ (tick - 1) // either way, |tick| = mask ^ (tick + mask) absTick := xor(mask, add(mask, tick)) } if (absTick > uint256(int256(MAX_TICK))) InvalidTick.selector.revertWith(tick); // The tick is decomposed into bits, and for each bit with index i that is set, the product of 1/sqrt(1.0001^(2^i)) // is calculated (using Q128.128). The constants used for this calculation are rounded to the nearest integer // Equivalent to: // price = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; // or price = int(2**128 / sqrt(1.0001)) if (absTick & 0x1) else 1 << 128 uint256 price; assembly ("memory-safe") { price := xor(shl(128, 1), mul(xor(shl(128, 1), 0xfffcb933bd6fad37aa2d162d1a594001), and(absTick, 0x1))) } if (absTick & 0x2 != 0) price = (price * 0xfff97272373d413259a46990580e213a) >> 128; if (absTick & 0x4 != 0) price = (price * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; if (absTick & 0x8 != 0) price = (price * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; if (absTick & 0x10 != 0) price = (price * 0xffcb9843d60f6159c9db58835c926644) >> 128; if (absTick & 0x20 != 0) price = (price * 0xff973b41fa98c081472e6896dfb254c0) >> 128; if (absTick & 0x40 != 0) price = (price * 0xff2ea16466c96a3843ec78b326b52861) >> 128; if (absTick & 0x80 != 0) price = (price * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; if (absTick & 0x100 != 0) price = (price * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; if (absTick & 0x200 != 0) price = (price * 0xf987a7253ac413176f2b074cf7815e54) >> 128; if (absTick & 0x400 != 0) price = (price * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; if (absTick & 0x800 != 0) price = (price * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; if (absTick & 0x1000 != 0) price = (price * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; if (absTick & 0x2000 != 0) price = (price * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; if (absTick & 0x4000 != 0) price = (price * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; if (absTick & 0x8000 != 0) price = (price * 0x31be135f97d08fd981231505542fcfa6) >> 128; if (absTick & 0x10000 != 0) price = (price * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; if (absTick & 0x20000 != 0) price = (price * 0x5d6af8dedb81196699c329225ee604) >> 128; if (absTick & 0x40000 != 0) price = (price * 0x2216e584f5fa1ea926041bedfe98) >> 128; if (absTick & 0x80000 != 0) price = (price * 0x48a170391f7dc42444e8fa2) >> 128; assembly ("memory-safe") { // if (tick > 0) price = type(uint256).max / price; if sgt(tick, 0) { price := div(not(0), price) } // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. // we then downcast because we know the result always fits within 160 bits due to our tick input constraint // we round up in the division so getTickAtSqrtPrice of the output price is always consistent // `sub(shl(32, 1), 1)` is `type(uint32).max` // `price + type(uint32).max` will not overflow because `price` fits in 192 bits sqrtPriceX96 := shr(32, add(price, sub(shl(32, 1), 1))) } } } /// @notice Calculates the greatest tick value such that getSqrtPriceAtTick(tick) <= sqrtPriceX96 /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_PRICE, as MIN_SQRT_PRICE is the lowest value getSqrtPriceAtTick may /// ever return. /// @param sqrtPriceX96 The sqrt price for which to compute the tick as a Q64.96 /// @return tick The greatest tick for which the getSqrtPriceAtTick(tick) is less than or equal to the input sqrtPriceX96 function getTickAtSqrtPrice(uint160 sqrtPriceX96) internal pure returns (int24 tick) { unchecked { // Equivalent: if (sqrtPriceX96 < MIN_SQRT_PRICE || sqrtPriceX96 >= MAX_SQRT_PRICE) revert InvalidSqrtPrice(); // second inequality must be >= because the price can never reach the price at the max tick // if sqrtPriceX96 < MIN_SQRT_PRICE, the `sub` underflows and `gt` is true // if sqrtPriceX96 >= MAX_SQRT_PRICE, sqrtPriceX96 - MIN_SQRT_PRICE > MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1 if ((sqrtPriceX96 - MIN_SQRT_PRICE) > MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE) { InvalidSqrtPrice.selector.revertWith(sqrtPriceX96); } uint256 price = uint256(sqrtPriceX96) << 32; uint256 r = price; uint256 msb = BitMath.mostSignificantBit(r); if (msb >= 128) r = price >> (msb - 127); else r = price << (127 - msb); int256 log_2 = (int256(msb) - 128) << 64; assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(63, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(62, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(61, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(60, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(59, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(58, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(57, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(56, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(55, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(54, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(53, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(52, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(51, f)) r := shr(f, r) } assembly ("memory-safe") { r := shr(127, mul(r, r)) let f := shr(128, r) log_2 := or(log_2, shl(50, f)) } int256 log_sqrt10001 = log_2 * 255738958999603826347141; // Q22.128 number // Magic number represents the ceiling of the maximum value of the error when approximating log_sqrt10001(x) int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); // Magic number represents the minimum value of the error when approximating log_sqrt10001(x), when // sqrtPrice is from the range (2^-64, 2^64). This is safe as MIN_SQRT_PRICE is more than 2^-64. If MIN_SQRT_PRICE // is changed, this may need to be changed too int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); tick = tickLow == tickHi ? tickLow : getSqrtPriceAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {IPoolManager} from "../interfaces/IPoolManager.sol"; import {Currency} from "../types/Currency.sol"; import {CurrencyReserves} from "./CurrencyReserves.sol"; import {NonzeroDeltaCount} from "./NonzeroDeltaCount.sol"; import {Lock} from "./Lock.sol"; /// @notice A helper library to provide state getters that use exttload library TransientStateLibrary { /// @notice returns the reserves for the synced currency /// @param manager The pool manager contract. /// @return uint256 The reserves of the currency. /// @dev returns 0 if the reserves are not synced or value is 0. /// Checks the synced currency to only return valid reserve values (after a sync and before a settle). function getSyncedReserves(IPoolManager manager) internal view returns (uint256) { if (getSyncedCurrency(manager).isAddressZero()) return 0; return uint256(manager.exttload(CurrencyReserves.RESERVES_OF_SLOT)); } function getSyncedCurrency(IPoolManager manager) internal view returns (Currency) { return Currency.wrap(address(uint160(uint256(manager.exttload(CurrencyReserves.CURRENCY_SLOT))))); } /// @notice Returns the number of nonzero deltas open on the PoolManager that must be zeroed out before the contract is locked function getNonzeroDeltaCount(IPoolManager manager) internal view returns (uint256) { return uint256(manager.exttload(NonzeroDeltaCount.NONZERO_DELTA_COUNT_SLOT)); } /// @notice Get the current delta for a caller in the given currency /// @param target The credited account address /// @param currency The currency for which to lookup the delta function currencyDelta(IPoolManager manager, address target, Currency currency) internal view returns (int256) { bytes32 key; assembly ("memory-safe") { mstore(0, and(target, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(32, and(currency, 0xffffffffffffffffffffffffffffffffffffffff)) key := keccak256(0, 64) } return int256(uint256(manager.exttload(key))); } /// @notice Returns whether the contract is unlocked or not function isUnlocked(IPoolManager manager) internal view returns (bool) { return manager.exttload(Lock.IS_UNLOCKED_SLOT) != 0x0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {SafeCast} from "../libraries/SafeCast.sol"; /// @dev Two `int128` values packed into a single `int256` where the upper 128 bits represent the amount0 /// and the lower 128 bits represent the amount1. type BalanceDelta is int256; using {add as +, sub as -, eq as ==, neq as !=} for BalanceDelta global; using BalanceDeltaLibrary for BalanceDelta global; using SafeCast for int256; function toBalanceDelta(int128 _amount0, int128 _amount1) pure returns (BalanceDelta balanceDelta) { assembly ("memory-safe") { balanceDelta := or(shl(128, _amount0), and(sub(shl(128, 1), 1), _amount1)) } } function add(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) { int256 res0; int256 res1; assembly ("memory-safe") { let a0 := sar(128, a) let a1 := signextend(15, a) let b0 := sar(128, b) let b1 := signextend(15, b) res0 := add(a0, b0) res1 := add(a1, b1) } return toBalanceDelta(res0.toInt128(), res1.toInt128()); } function sub(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) { int256 res0; int256 res1; assembly ("memory-safe") { let a0 := sar(128, a) let a1 := signextend(15, a) let b0 := sar(128, b) let b1 := signextend(15, b) res0 := sub(a0, b0) res1 := sub(a1, b1) } return toBalanceDelta(res0.toInt128(), res1.toInt128()); } function eq(BalanceDelta a, BalanceDelta b) pure returns (bool) { return BalanceDelta.unwrap(a) == BalanceDelta.unwrap(b); } function neq(BalanceDelta a, BalanceDelta b) pure returns (bool) { return BalanceDelta.unwrap(a) != BalanceDelta.unwrap(b); } /// @notice Library for getting the amount0 and amount1 deltas from the BalanceDelta type library BalanceDeltaLibrary { /// @notice A BalanceDelta of 0 BalanceDelta public constant ZERO_DELTA = BalanceDelta.wrap(0); function amount0(BalanceDelta balanceDelta) internal pure returns (int128 _amount0) { assembly ("memory-safe") { _amount0 := sar(128, balanceDelta) } } function amount1(BalanceDelta balanceDelta) internal pure returns (int128 _amount1) { assembly ("memory-safe") { _amount1 := signextend(15, balanceDelta) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // Return type of the beforeSwap hook. // Upper 128 bits is the delta in specified tokens. Lower 128 bits is delta in unspecified tokens (to match the afterSwap hook) type BeforeSwapDelta is int256; // Creates a BeforeSwapDelta from specified and unspecified function toBeforeSwapDelta(int128 deltaSpecified, int128 deltaUnspecified) pure returns (BeforeSwapDelta beforeSwapDelta) { assembly ("memory-safe") { beforeSwapDelta := or(shl(128, deltaSpecified), and(sub(shl(128, 1), 1), deltaUnspecified)) } } /// @notice Library for getting the specified and unspecified deltas from the BeforeSwapDelta type library BeforeSwapDeltaLibrary { /// @notice A BeforeSwapDelta of 0 BeforeSwapDelta public constant ZERO_DELTA = BeforeSwapDelta.wrap(0); /// extracts int128 from the upper 128 bits of the BeforeSwapDelta /// returned by beforeSwap function getSpecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaSpecified) { assembly ("memory-safe") { deltaSpecified := sar(128, delta) } } /// extracts int128 from the lower 128 bits of the BeforeSwapDelta /// returned by beforeSwap and afterSwap function getUnspecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaUnspecified) { assembly ("memory-safe") { deltaUnspecified := signextend(15, delta) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol"; import {CustomRevert} from "../libraries/CustomRevert.sol"; type Currency is address; using {greaterThan as >, lessThan as <, greaterThanOrEqualTo as >=, equals as ==} for Currency global; using CurrencyLibrary for Currency global; function equals(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) == Currency.unwrap(other); } function greaterThan(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) > Currency.unwrap(other); } function lessThan(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) < Currency.unwrap(other); } function greaterThanOrEqualTo(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) >= Currency.unwrap(other); } /// @title CurrencyLibrary /// @dev This library allows for transferring and holding native tokens and ERC20 tokens library CurrencyLibrary { /// @notice Additional context for ERC-7751 wrapped error when a native transfer fails error NativeTransferFailed(); /// @notice Additional context for ERC-7751 wrapped error when an ERC20 transfer fails error ERC20TransferFailed(); /// @notice A constant to represent the native currency Currency public constant ADDRESS_ZERO = Currency.wrap(address(0)); function transfer(Currency currency, address to, uint256 amount) internal { // altered from https://github.com/transmissions11/solmate/blob/44a9963d4c78111f77caa0e65d677b8b46d6f2e6/src/utils/SafeTransferLib.sol // modified custom error selectors bool success; if (currency.isAddressZero()) { assembly ("memory-safe") { // Transfer the ETH and revert if it fails. success := call(gas(), to, amount, 0, 0, 0, 0) } // revert with NativeTransferFailed, containing the bubbled up error as an argument if (!success) { CustomRevert.bubbleUpAndRevertWith(to, bytes4(0), NativeTransferFailed.selector); } } else { assembly ("memory-safe") { // Get a pointer to some free memory. let fmp := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(fmp, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(fmp, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(fmp, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), currency, 0, fmp, 68, 0, 32) ) // Now clean the memory we used mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were stored here mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored here } // revert with ERC20TransferFailed, containing the bubbled up error as an argument if (!success) { CustomRevert.bubbleUpAndRevertWith( Currency.unwrap(currency), IERC20Minimal.transfer.selector, ERC20TransferFailed.selector ); } } } function balanceOfSelf(Currency currency) internal view returns (uint256) { if (currency.isAddressZero()) { return address(this).balance; } else { return IERC20Minimal(Currency.unwrap(currency)).balanceOf(address(this)); } } function balanceOf(Currency currency, address owner) internal view returns (uint256) { if (currency.isAddressZero()) { return owner.balance; } else { return IERC20Minimal(Currency.unwrap(currency)).balanceOf(owner); } } function isAddressZero(Currency currency) internal pure returns (bool) { return Currency.unwrap(currency) == Currency.unwrap(ADDRESS_ZERO); } function toId(Currency currency) internal pure returns (uint256) { return uint160(Currency.unwrap(currency)); } // If the upper 12 bytes are non-zero, they will be zero-ed out // Therefore, fromId() and toId() are not inverses of each other function fromId(uint256 id) internal pure returns (Currency) { return Currency.wrap(address(uint160(id))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "./PoolKey.sol"; type PoolId is bytes32; /// @notice Library for computing the ID of a pool library PoolIdLibrary { /// @notice Returns value equal to keccak256(abi.encode(poolKey)) function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) { assembly ("memory-safe") { // 0xa0 represents the total size of the poolKey struct (5 slots of 32 bytes) poolId := keccak256(poolKey, 0xa0) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Currency} from "./Currency.sol"; import {IHooks} from "../interfaces/IHooks.sol"; import {PoolIdLibrary} from "./PoolId.sol"; using PoolIdLibrary for PoolKey global; /// @notice Returns the key for identifying a pool struct PoolKey { /// @notice The lower currency of the pool, sorted numerically Currency currency0; /// @notice The higher currency of the pool, sorted numerically Currency currency1; /// @notice The pool LP fee, capped at 1_000_000. If the highest bit is 1, the pool has a dynamic fee and must be exactly equal to 0x800000 uint24 fee; /// @notice Ticks that involve positions must be a multiple of tick spacing int24 tickSpacing; /// @notice The hooks of the pool IHooks hooks; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.26; import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; import {VanityAddressLib} from "./libraries/VanityAddressLib.sol"; import {IUniswapV4DeployerCompetition} from "./interfaces/IUniswapV4DeployerCompetition.sol"; /// @title UniswapV4DeployerCompetition /// @notice A contract to crowdsource a salt for the best Uniswap V4 address contract UniswapV4DeployerCompetition is IUniswapV4DeployerCompetition { using VanityAddressLib for address; /// @dev The salt for the best address found so far bytes32 public bestAddressSalt; /// @dev The submitter of the best address found so far address public bestAddressSubmitter; /// @dev The deadline for the competition uint256 public immutable competitionDeadline; /// @dev The init code hash of the V4 contract bytes32 public immutable initCodeHash; /// @dev The deployer who can initiate the deployment of the v4 PoolManager, until the exclusive deploy deadline. /// @dev After this deadline anyone can deploy. address public immutable deployer; /// @dev The deadline for exclusive deployment by deployer after deadline uint256 public immutable exclusiveDeployDeadline; constructor( bytes32 _initCodeHash, uint256 _competitionDeadline, address _exclusiveDeployer, uint256 _exclusiveDeployLength ) { initCodeHash = _initCodeHash; competitionDeadline = _competitionDeadline; exclusiveDeployDeadline = _competitionDeadline + _exclusiveDeployLength; deployer = _exclusiveDeployer; } /// @inheritdoc IUniswapV4DeployerCompetition function updateBestAddress(bytes32 salt) external { if (block.timestamp > competitionDeadline) { revert CompetitionOver(block.timestamp, competitionDeadline); } address saltSubAddress = address(bytes20(salt)); if (saltSubAddress != msg.sender && saltSubAddress != address(0)) revert InvalidSender(salt, msg.sender); address newAddress = Create2.computeAddress(salt, initCodeHash); address _bestAddress = bestAddress(); if (!newAddress.betterThan(_bestAddress)) { revert WorseAddress(newAddress, _bestAddress, newAddress.score(), _bestAddress.score()); } bestAddressSalt = salt; bestAddressSubmitter = msg.sender; emit NewAddressFound(newAddress, msg.sender, newAddress.score()); } /// @inheritdoc IUniswapV4DeployerCompetition function deploy(bytes memory bytecode) external { if (keccak256(bytecode) != initCodeHash) { revert InvalidBytecode(); } if (block.timestamp <= competitionDeadline) { revert CompetitionNotOver(block.timestamp, competitionDeadline); } if (msg.sender != deployer && block.timestamp <= exclusiveDeployDeadline) { // anyone can deploy after the deadline revert NotAllowedToDeploy(msg.sender, deployer); } // the owner of the contract must be encoded in the bytecode Create2.deploy(0, bestAddressSalt, bytecode); } /// @dev returns the best address found so far function bestAddress() public view returns (address) { return Create2.computeAddress(bestAddressSalt, initCodeHash); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.26; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; import {PathKey} from "./libraries/PathKey.sol"; import {CalldataDecoder} from "./libraries/CalldataDecoder.sol"; import {IV4Router} from "./interfaces/IV4Router.sol"; import {BaseActionsRouter} from "./base/BaseActionsRouter.sol"; import {DeltaResolver} from "./base/DeltaResolver.sol"; import {Actions} from "./libraries/Actions.sol"; import {ActionConstants} from "./libraries/ActionConstants.sol"; import {BipsLibrary} from "./libraries/BipsLibrary.sol"; /// @title UniswapV4Router /// @notice Abstract contract that contains all internal logic needed for routing through Uniswap v4 pools /// @dev the entry point to executing actions in this contract is calling `BaseActionsRouter._executeActions` /// An inheriting contract should call _executeActions at the point that they wish actions to be executed abstract contract V4Router is IV4Router, BaseActionsRouter, DeltaResolver { using SafeCast for *; using CalldataDecoder for bytes; using BipsLibrary for uint256; constructor(IPoolManager _poolManager) BaseActionsRouter(_poolManager) {} function _handleAction(uint256 action, bytes calldata params) internal override { // swap actions and payment actions in different blocks for gas efficiency if (action < Actions.SETTLE) { if (action == Actions.SWAP_EXACT_IN) { IV4Router.ExactInputParams calldata swapParams = params.decodeSwapExactInParams(); _swapExactInput(swapParams); return; } else if (action == Actions.SWAP_EXACT_IN_SINGLE) { IV4Router.ExactInputSingleParams calldata swapParams = params.decodeSwapExactInSingleParams(); _swapExactInputSingle(swapParams); return; } else if (action == Actions.SWAP_EXACT_OUT) { IV4Router.ExactOutputParams calldata swapParams = params.decodeSwapExactOutParams(); _swapExactOutput(swapParams); return; } else if (action == Actions.SWAP_EXACT_OUT_SINGLE) { IV4Router.ExactOutputSingleParams calldata swapParams = params.decodeSwapExactOutSingleParams(); _swapExactOutputSingle(swapParams); return; } } else { if (action == Actions.SETTLE_ALL) { (Currency currency, uint256 maxAmount) = params.decodeCurrencyAndUint256(); uint256 amount = _getFullDebt(currency); if (amount > maxAmount) revert V4TooMuchRequested(maxAmount, amount); _settle(currency, msgSender(), amount); return; } else if (action == Actions.TAKE_ALL) { (Currency currency, uint256 minAmount) = params.decodeCurrencyAndUint256(); uint256 amount = _getFullCredit(currency); if (amount < minAmount) revert V4TooLittleReceived(minAmount, amount); _take(currency, msgSender(), amount); return; } else if (action == Actions.SETTLE) { (Currency currency, uint256 amount, bool payerIsUser) = params.decodeCurrencyUint256AndBool(); _settle(currency, _mapPayer(payerIsUser), _mapSettleAmount(amount, currency)); return; } else if (action == Actions.TAKE) { (Currency currency, address recipient, uint256 amount) = params.decodeCurrencyAddressAndUint256(); _take(currency, _mapRecipient(recipient), _mapTakeAmount(amount, currency)); return; } else if (action == Actions.TAKE_PORTION) { (Currency currency, address recipient, uint256 bips) = params.decodeCurrencyAddressAndUint256(); _take(currency, _mapRecipient(recipient), _getFullCredit(currency).calculatePortion(bips)); return; } } revert UnsupportedAction(action); } function _swapExactInputSingle(IV4Router.ExactInputSingleParams calldata params) private { uint128 amountIn = params.amountIn; if (amountIn == ActionConstants.OPEN_DELTA) { amountIn = _getFullCredit(params.zeroForOne ? params.poolKey.currency0 : params.poolKey.currency1).toUint128(); } uint128 amountOut = _swap(params.poolKey, params.zeroForOne, -int256(uint256(amountIn)), params.hookData).toUint128(); if (amountOut < params.amountOutMinimum) revert V4TooLittleReceived(params.amountOutMinimum, amountOut); } function _swapExactInput(IV4Router.ExactInputParams calldata params) private { unchecked { // Caching for gas savings uint256 pathLength = params.path.length; uint128 amountOut; Currency currencyIn = params.currencyIn; uint128 amountIn = params.amountIn; if (amountIn == ActionConstants.OPEN_DELTA) amountIn = _getFullCredit(currencyIn).toUint128(); PathKey calldata pathKey; for (uint256 i = 0; i < pathLength; i++) { pathKey = params.path[i]; (PoolKey memory poolKey, bool zeroForOne) = pathKey.getPoolAndSwapDirection(currencyIn); // The output delta will always be positive, except for when interacting with certain hook pools amountOut = _swap(poolKey, zeroForOne, -int256(uint256(amountIn)), pathKey.hookData).toUint128(); amountIn = amountOut; currencyIn = pathKey.intermediateCurrency; } if (amountOut < params.amountOutMinimum) revert V4TooLittleReceived(params.amountOutMinimum, amountOut); } } function _swapExactOutputSingle(IV4Router.ExactOutputSingleParams calldata params) private { uint128 amountOut = params.amountOut; if (amountOut == ActionConstants.OPEN_DELTA) { amountOut = _getFullDebt(params.zeroForOne ? params.poolKey.currency1 : params.poolKey.currency0).toUint128(); } uint128 amountIn = ( uint256(-int256(_swap(params.poolKey, params.zeroForOne, int256(uint256(amountOut)), params.hookData))) ).toUint128(); if (amountIn > params.amountInMaximum) revert V4TooMuchRequested(params.amountInMaximum, amountIn); } function _swapExactOutput(IV4Router.ExactOutputParams calldata params) private { unchecked { // Caching for gas savings uint256 pathLength = params.path.length; uint128 amountIn; uint128 amountOut = params.amountOut; Currency currencyOut = params.currencyOut; PathKey calldata pathKey; if (amountOut == ActionConstants.OPEN_DELTA) { amountOut = _getFullDebt(currencyOut).toUint128(); } for (uint256 i = pathLength; i > 0; i--) { pathKey = params.path[i - 1]; (PoolKey memory poolKey, bool oneForZero) = pathKey.getPoolAndSwapDirection(currencyOut); // The output delta will always be negative, except for when interacting with certain hook pools amountIn = (uint256(-int256(_swap(poolKey, !oneForZero, int256(uint256(amountOut)), pathKey.hookData)))) .toUint128(); amountOut = amountIn; currencyOut = pathKey.intermediateCurrency; } if (amountIn > params.amountInMaximum) revert V4TooMuchRequested(params.amountInMaximum, amountIn); } } function _swap(PoolKey memory poolKey, bool zeroForOne, int256 amountSpecified, bytes calldata hookData) private returns (int128 reciprocalAmount) { // for protection of exactOut swaps, sqrtPriceLimit is not exposed as a feature in this contract unchecked { BalanceDelta delta = poolManager.swap( poolKey, IPoolManager.SwapParams( zeroForOne, amountSpecified, zeroForOne ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1 ), hookData ); reciprocalAmount = (zeroForOne == amountSpecified < 0) ? delta.amount1() : delta.amount0(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {SafeCallback} from "./SafeCallback.sol"; import {CalldataDecoder} from "../libraries/CalldataDecoder.sol"; import {ActionConstants} from "../libraries/ActionConstants.sol"; /// @notice Abstract contract for performing a combination of actions on Uniswap v4. /// @dev Suggested uint256 action values are defined in Actions.sol, however any definition can be used abstract contract BaseActionsRouter is SafeCallback { using CalldataDecoder for bytes; /// @notice emitted when different numbers of parameters and actions are provided error InputLengthMismatch(); /// @notice emitted when an inheriting contract does not support an action error UnsupportedAction(uint256 action); constructor(IPoolManager _poolManager) SafeCallback(_poolManager) {} /// @notice internal function that triggers the execution of a set of actions on v4 /// @dev inheriting contracts should call this function to trigger execution function _executeActions(bytes calldata unlockData) internal { poolManager.unlock(unlockData); } /// @notice function that is called by the PoolManager through the SafeCallback.unlockCallback /// @param data Abi encoding of (bytes actions, bytes[] params) /// where params[i] is the encoded parameters for actions[i] function _unlockCallback(bytes calldata data) internal override returns (bytes memory) { // abi.decode(data, (bytes, bytes[])); (bytes calldata actions, bytes[] calldata params) = data.decodeActionsRouterParams(); _executeActionsWithoutUnlock(actions, params); return ""; } function _executeActionsWithoutUnlock(bytes calldata actions, bytes[] calldata params) internal { uint256 numActions = actions.length; if (numActions != params.length) revert InputLengthMismatch(); for (uint256 actionIndex = 0; actionIndex < numActions; actionIndex++) { uint256 action = uint8(actions[actionIndex]); _handleAction(action, params[actionIndex]); } } /// @notice function to handle the parsing and execution of an action and its parameters function _handleAction(uint256 action, bytes calldata params) internal virtual; /// @notice function that returns address considered executor of the actions /// @dev The other context functions, _msgData and _msgValue, are not supported by this contract /// In many contracts this will be the address that calls the initial entry point that calls `_executeActions` /// `msg.sender` shouldn't be used, as this will be the v4 pool manager contract that calls `unlockCallback` /// If using ReentrancyLock.sol, this function can return _getLocker() function msgSender() public view virtual returns (address); /// @notice Calculates the address for a action function _mapRecipient(address recipient) internal view returns (address) { if (recipient == ActionConstants.MSG_SENDER) { return msgSender(); } else if (recipient == ActionConstants.ADDRESS_THIS) { return address(this); } else { return recipient; } } /// @notice Calculates the payer for an action function _mapPayer(bool payerIsUser) internal view returns (address) { return payerIsUser ? msgSender() : address(this); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {QuoterRevert} from "../libraries/QuoterRevert.sol"; import {SafeCallback} from "../base/SafeCallback.sol"; import {PoolId} from "@uniswap/v4-core/src/types/PoolId.sol"; import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; abstract contract BaseV4Quoter is SafeCallback { using QuoterRevert for *; error NotEnoughLiquidity(PoolId poolId); error NotSelf(); error UnexpectedCallSuccess(); constructor(IPoolManager _poolManager) SafeCallback(_poolManager) {} /// @dev Only this address may call this function. Used to mimic internal functions, using an /// external call to catch and parse revert reasons modifier selfOnly() { if (msg.sender != address(this)) revert NotSelf(); _; } function _unlockCallback(bytes calldata data) internal override returns (bytes memory) { (bool success, bytes memory returnData) = address(this).call(data); // Every quote path gathers a quote, and then reverts either with QuoteSwap(quoteAmount) or alternative error if (success) revert UnexpectedCallSuccess(); // Bubble the revert string, whether a valid quote or an alternative error returnData.bubbleReason(); } /// @dev Execute a swap and return the balance delta /// @notice if amountSpecified < 0, the swap is exactInput, otherwise exactOutput function _swap(PoolKey memory poolKey, bool zeroForOne, int256 amountSpecified, bytes calldata hookData) internal returns (BalanceDelta swapDelta) { swapDelta = poolManager.swap( poolKey, IPoolManager.SwapParams({ zeroForOne: zeroForOne, amountSpecified: amountSpecified, sqrtPriceLimitX96: zeroForOne ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1 }), hookData ); // Check that the pool was not illiquid. int128 amountSpecifiedActual = (zeroForOne == (amountSpecified < 0)) ? swapDelta.amount0() : swapDelta.amount1(); if (amountSpecifiedActual != amountSpecified) { revert NotEnoughLiquidity(poolKey.toId()); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {TransientStateLibrary} from "@uniswap/v4-core/src/libraries/TransientStateLibrary.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {ImmutableState} from "./ImmutableState.sol"; import {ActionConstants} from "../libraries/ActionConstants.sol"; /// @notice Abstract contract used to sync, send, and settle funds to the pool manager /// @dev Note that sync() is called before any erc-20 transfer in `settle`. abstract contract DeltaResolver is ImmutableState { using TransientStateLibrary for IPoolManager; /// @notice Emitted trying to settle a positive delta. error DeltaNotPositive(Currency currency); /// @notice Emitted trying to take a negative delta. error DeltaNotNegative(Currency currency); /// @notice Emitted when the contract does not have enough balance to wrap or unwrap. error InsufficientBalance(); /// @notice Take an amount of currency out of the PoolManager /// @param currency Currency to take /// @param recipient Address to receive the currency /// @param amount Amount to take /// @dev Returns early if the amount is 0 function _take(Currency currency, address recipient, uint256 amount) internal { if (amount == 0) return; poolManager.take(currency, recipient, amount); } /// @notice Pay and settle a currency to the PoolManager /// @dev The implementing contract must ensure that the `payer` is a secure address /// @param currency Currency to settle /// @param payer Address of the payer /// @param amount Amount to send /// @dev Returns early if the amount is 0 function _settle(Currency currency, address payer, uint256 amount) internal { if (amount == 0) return; poolManager.sync(currency); if (currency.isAddressZero()) { poolManager.settle{value: amount}(); } else { _pay(currency, payer, amount); poolManager.settle(); } } /// @notice Abstract function for contracts to implement paying tokens to the poolManager /// @dev The recipient of the payment should be the poolManager /// @param token The token to settle. This is known not to be the native currency /// @param payer The address who should pay tokens /// @param amount The number of tokens to send function _pay(Currency token, address payer, uint256 amount) internal virtual; /// @notice Obtain the full amount owed by this contract (negative delta) /// @param currency Currency to get the delta for /// @return amount The amount owed by this contract as a uint256 function _getFullDebt(Currency currency) internal view returns (uint256 amount) { int256 _amount = poolManager.currencyDelta(address(this), currency); // If the amount is positive, it should be taken not settled. if (_amount > 0) revert DeltaNotNegative(currency); // Casting is safe due to limits on the total supply of a pool amount = uint256(-_amount); } /// @notice Obtain the full credit owed to this contract (positive delta) /// @param currency Currency to get the delta for /// @return amount The amount owed to this contract as a uint256 function _getFullCredit(Currency currency) internal view returns (uint256 amount) { int256 _amount = poolManager.currencyDelta(address(this), currency); // If the amount is negative, it should be settled not taken. if (_amount < 0) revert DeltaNotPositive(currency); amount = uint256(_amount); } /// @notice Calculates the amount for a settle action function _mapSettleAmount(uint256 amount, Currency currency) internal view returns (uint256) { if (amount == ActionConstants.CONTRACT_BALANCE) { return currency.balanceOfSelf(); } else if (amount == ActionConstants.OPEN_DELTA) { return _getFullDebt(currency); } else { return amount; } } /// @notice Calculates the amount for a take action function _mapTakeAmount(uint256 amount, Currency currency) internal view returns (uint256) { if (amount == ActionConstants.OPEN_DELTA) { return _getFullCredit(currency); } else { return amount; } } /// @notice Calculates the sanitized amount before wrapping/unwrapping. /// @param inputCurrency The currency, either native or wrapped native, that this contract holds /// @param amount The amount to wrap or unwrap. Can be CONTRACT_BALANCE, OPEN_DELTA or a specific amount /// @param outputCurrency The currency after the wrap/unwrap that the user may owe a balance in on the poolManager function _mapWrapUnwrapAmount(Currency inputCurrency, uint256 amount, Currency outputCurrency) internal view returns (uint256) { // if wrapping, the balance in this contract is in ETH // if unwrapping, the balance in this contract is in WETH uint256 balance = inputCurrency.balanceOf(address(this)); if (amount == ActionConstants.CONTRACT_BALANCE) { // return early to avoid unnecessary balance check return balance; } if (amount == ActionConstants.OPEN_DELTA) { // if wrapping, the open currency on the PoolManager is WETH. // if unwrapping, the open currency on the PoolManager is ETH. // note that we use the DEBT amount. Positive deltas can be taken and then wrapped. amount = _getFullDebt(outputCurrency); } if (amount > balance) revert InsufficientBalance(); return amount; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IEIP712_v4} from "../interfaces/IEIP712_v4.sol"; /// @notice Generic EIP712 implementation /// @dev Maintains cross-chain replay protection in the event of a fork /// @dev Should not be delegatecall'd because DOMAIN_SEPARATOR returns the cached hash and does not recompute with the delegatecallers address /// @dev Reference: https://github.com/Uniswap/permit2/blob/3f17e8db813189a03950dc7fc8382524a095c053/src/EIP712.sol /// @dev Reference: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/7bd2b2aaf68c21277097166a9a51eb72ae239b34/contracts/utils/cryptography/EIP712.sol contract EIP712_v4 is IEIP712_v4 { // Cache the domain separator as an immutable value, but also store the chain id that it // corresponds to, in order to invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; bytes32 private immutable _HASHED_NAME; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); constructor(string memory name) { _HASHED_NAME = keccak256(bytes(name)); _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(); } /// @inheritdoc IEIP712_v4 function DOMAIN_SEPARATOR() public view returns (bytes32) { // uses cached version if chainid is unchanged from construction return block.chainid == _CACHED_CHAIN_ID ? _CACHED_DOMAIN_SEPARATOR : _buildDomainSeparator(); } /// @notice Builds a domain separator using the current chainId and contract address. function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _HASHED_NAME, block.chainid, address(this))); } /// @notice Creates an EIP-712 typed data hash function _hashTypedData(bytes32 dataHash) internal view returns (bytes32 digest) { // equal to keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), dataHash)); bytes32 domainSeparator = DOMAIN_SEPARATOR(); assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, hex"1901") mstore(add(fmp, 0x02), domainSeparator) mstore(add(fmp, 0x22), dataHash) digest := keccak256(fmp, 0x42) // now clean the memory we used mstore(fmp, 0) // fmp held "\x19\x01", domainSeparator mstore(add(fmp, 0x20), 0) // fmp+0x20 held domainSeparator, dataHash mstore(add(fmp, 0x40), 0) // fmp+0x40 held dataHash } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {IImmutableState} from "../interfaces/IImmutableState.sol"; /// @title Immutable State /// @notice A collection of immutable state variables, commonly used across multiple contracts contract ImmutableState is IImmutableState { /// @inheritdoc IImmutableState IPoolManager public immutable poolManager; /// @notice Thrown when the caller is not PoolManager error NotPoolManager(); /// @notice Only allow calls from the PoolManager contract modifier onlyPoolManager() { if (msg.sender != address(poolManager)) revert NotPoolManager(); _; } constructor(IPoolManager _poolManager) { poolManager = _poolManager; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IMulticall_v4} from "../interfaces/IMulticall_v4.sol"; /// @title Multicall_v4 /// @notice Enables calling multiple methods in a single call to the contract abstract contract Multicall_v4 is IMulticall_v4 { /// @inheritdoc IMulticall_v4 function multicall(bytes[] calldata data) external payable returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { (bool success, bytes memory result) = address(this).delegatecall(data[i]); if (!success) { // bubble up the revert reason assembly { revert(add(result, 0x20), mload(result)) } } results[i] = result; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IWETH9} from "../interfaces/external/IWETH9.sol"; import {ActionConstants} from "../libraries/ActionConstants.sol"; import {ImmutableState} from "./ImmutableState.sol"; /// @title Native Wrapper /// @notice Used for wrapping and unwrapping native abstract contract NativeWrapper is ImmutableState { /// @notice The address for WETH9 IWETH9 public immutable WETH9; /// @notice Thrown when an unexpected address sends ETH to this contract error InvalidEthSender(); constructor(IWETH9 _weth9) { WETH9 = _weth9; } /// @dev The amount should already be <= the current balance in this contract. function _wrap(uint256 amount) internal { if (amount > 0) WETH9.deposit{value: amount}(); } /// @dev The amount should already be <= the current balance in this contract. function _unwrap(uint256 amount) internal { if (amount > 0) WETH9.withdraw(amount); } receive() external payable { if (msg.sender != address(WETH9) && msg.sender != address(poolManager)) revert InvalidEthSender(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ISubscriber} from "../interfaces/ISubscriber.sol"; import {INotifier} from "../interfaces/INotifier.sol"; import {CustomRevert} from "@uniswap/v4-core/src/libraries/CustomRevert.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {PositionInfo} from "../libraries/PositionInfoLibrary.sol"; /// @notice Notifier is used to opt in to sending updates to external contracts about position modifications or transfers abstract contract Notifier is INotifier { using CustomRevert for *; ISubscriber private constant NO_SUBSCRIBER = ISubscriber(address(0)); /// @inheritdoc INotifier uint256 public immutable unsubscribeGasLimit; /// @inheritdoc INotifier mapping(uint256 tokenId => ISubscriber subscriber) public subscriber; constructor(uint256 _unsubscribeGasLimit) { unsubscribeGasLimit = _unsubscribeGasLimit; } /// @notice Only allow callers that are approved as spenders or operators of the tokenId /// @dev to be implemented by the parent contract (PositionManager) /// @param caller the address of the caller /// @param tokenId the tokenId of the position modifier onlyIfApproved(address caller, uint256 tokenId) virtual; /// @notice Enforces that the PoolManager is locked. modifier onlyIfPoolManagerLocked() virtual; function _setUnsubscribed(uint256 tokenId) internal virtual; function _setSubscribed(uint256 tokenId) internal virtual; /// @inheritdoc INotifier function subscribe(uint256 tokenId, address newSubscriber, bytes calldata data) external payable onlyIfPoolManagerLocked onlyIfApproved(msg.sender, tokenId) { ISubscriber _subscriber = subscriber[tokenId]; if (_subscriber != NO_SUBSCRIBER) revert AlreadySubscribed(tokenId, address(_subscriber)); _setSubscribed(tokenId); subscriber[tokenId] = ISubscriber(newSubscriber); bool success = _call(newSubscriber, abi.encodeCall(ISubscriber.notifySubscribe, (tokenId, data))); if (!success) { newSubscriber.bubbleUpAndRevertWith(ISubscriber.notifySubscribe.selector, SubscriptionReverted.selector); } emit Subscription(tokenId, newSubscriber); } /// @inheritdoc INotifier function unsubscribe(uint256 tokenId) external payable onlyIfPoolManagerLocked onlyIfApproved(msg.sender, tokenId) { _unsubscribe(tokenId); } function _unsubscribe(uint256 tokenId) internal { ISubscriber _subscriber = subscriber[tokenId]; if (_subscriber == NO_SUBSCRIBER) revert NotSubscribed(); _setUnsubscribed(tokenId); delete subscriber[tokenId]; if (address(_subscriber).code.length > 0) { // require that the remaining gas is sufficient to notify the subscriber // otherwise, users can select a gas limit where .notifyUnsubscribe hits OutOfGas yet the // transaction/unsubscription can still succeed if (gasleft() < unsubscribeGasLimit) GasLimitTooLow.selector.revertWith(); try _subscriber.notifyUnsubscribe{gas: unsubscribeGasLimit}(tokenId) {} catch {} } emit Unsubscription(tokenId, address(_subscriber)); } /// @dev note this function also deletes the subscriber address from the mapping function _removeSubscriberAndNotifyBurn( uint256 tokenId, address owner, PositionInfo info, uint256 liquidity, BalanceDelta feesAccrued ) internal { address _subscriber = address(subscriber[tokenId]); // remove the subscriber delete subscriber[tokenId]; bool success = _call(_subscriber, abi.encodeCall(ISubscriber.notifyBurn, (tokenId, owner, info, liquidity, feesAccrued))); if (!success) { _subscriber.bubbleUpAndRevertWith(ISubscriber.notifyBurn.selector, BurnNotificationReverted.selector); } } function _notifyModifyLiquidity(uint256 tokenId, int256 liquidityChange, BalanceDelta feesAccrued) internal { address _subscriber = address(subscriber[tokenId]); bool success = _call( _subscriber, abi.encodeCall(ISubscriber.notifyModifyLiquidity, (tokenId, liquidityChange, feesAccrued)) ); if (!success) { _subscriber.bubbleUpAndRevertWith( ISubscriber.notifyModifyLiquidity.selector, ModifyLiquidityNotificationReverted.selector ); } } function _call(address target, bytes memory encodedCall) internal returns (bool success) { if (target.code.length == 0) NoCodeSubscriber.selector.revertWith(); assembly ("memory-safe") { success := call(gas(), target, 0, add(encodedCall, 0x20), mload(encodedCall), 0, 0) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ImmutableState} from "./ImmutableState.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {IPoolInitializer_v4} from "../interfaces/IPoolInitializer_v4.sol"; /// @title Pool Initializer /// @notice Initializes a Uniswap v4 Pool /// @dev Enables create pool + mint liquidity in a single transaction with multicall abstract contract PoolInitializer_v4 is ImmutableState, IPoolInitializer_v4 { /// @inheritdoc IPoolInitializer_v4 function initializePool(PoolKey calldata key, uint160 sqrtPriceX96) external payable returns (int24) { try poolManager.initialize(key, sqrtPriceX96) returns (int24 tick) { return tick; } catch { return type(int24).max; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {Locker} from "../libraries/Locker.sol"; /// @notice A transient reentrancy lock, that stores the caller's address as the lock contract ReentrancyLock { error ContractLocked(); modifier isNotLocked() { if (Locker.get() != address(0)) revert ContractLocked(); Locker.set(msg.sender); _; Locker.set(address(0)); } function _getLocker() internal view returns (address) { return Locker.get(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IUnlockCallback} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {ImmutableState} from "./ImmutableState.sol"; /// @title Safe Callback /// @notice A contract that only allows the Uniswap v4 PoolManager to call the unlockCallback abstract contract SafeCallback is ImmutableState, IUnlockCallback { constructor(IPoolManager _poolManager) ImmutableState(_poolManager) {} /// @inheritdoc IUnlockCallback /// @dev We force the onlyPoolManager modifier by exposing a virtual function after the onlyPoolManager check. function unlockCallback(bytes calldata data) external onlyPoolManager returns (bytes memory) { return _unlockCallback(data); } /// @dev to be implemented by the child contract, to safely guarantee the logic is only executed by the PoolManager function _unlockCallback(bytes calldata data) internal virtual returns (bytes memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IUnorderedNonce} from "../interfaces/IUnorderedNonce.sol"; /// @title Unordered Nonce /// @notice Contract state and methods for using unordered nonces in signatures contract UnorderedNonce is IUnorderedNonce { /// @inheritdoc IUnorderedNonce mapping(address owner => mapping(uint256 word => uint256 bitmap)) public nonces; /// @notice Consume a nonce, reverting if it has already been used /// @param owner address, the owner/signer of the nonce /// @param nonce uint256, the nonce to consume. The top 248 bits are the word, the bottom 8 bits indicate the bit position function _useUnorderedNonce(address owner, uint256 nonce) internal { uint256 wordPos = nonce >> 8; uint256 bitPos = uint8(nonce); uint256 bit = 1 << bitPos; uint256 flipped = nonces[owner][wordPos] ^= bit; if (flipped & bit == 0) revert NonceAlreadyUsed(); } /// @inheritdoc IUnorderedNonce function revokeNonce(uint256 nonce) external payable { _useUnorderedNonce(msg.sender, nonce); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title IEIP712_v4 /// @notice Interface for the EIP712 contract interface IEIP712_v4 { /// @notice Returns the domain separator for the current chain. /// @return bytes32 The domain separator function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title IERC721Permit_v4 /// @notice Interface for the ERC721Permit_v4 contract interface IERC721Permit_v4 { error SignatureDeadlineExpired(); error NoSelfPermit(); error Unauthorized(); /// @notice Approve of a specific token ID for spending by spender via signature /// @param spender The account that is being approved /// @param tokenId The ID of the token that is being approved for spending /// @param deadline The deadline timestamp by which the call must be mined for the approve to work /// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word /// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v) /// @dev payable so it can be multicalled with NATIVE related actions function permit(address spender, uint256 tokenId, uint256 deadline, uint256 nonce, bytes calldata signature) external payable; /// @notice Set an operator with full permission to an owner's tokens via signature /// @param owner The address that is setting the operator /// @param operator The address that will be set as an operator for the owner /// @param approved The permission to set on the operator /// @param deadline The deadline timestamp by which the call must be mined for the approve to work /// @param nonce a unique value, for an owner, to prevent replay attacks; an unordered nonce where the top 248 bits correspond to a word and the bottom 8 bits calculate the bit position of the word /// @param signature Concatenated data from a valid secp256k1 signature from the holder, i.e. abi.encodePacked(r, s, v) /// @dev payable so it can be multicalled with NATIVE related actions function permitForAll( address owner, address operator, bool approved, uint256 deadline, uint256 nonce, bytes calldata signature ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; /// @title IImmutableState /// @notice Interface for the ImmutableState contract interface IImmutableState { /// @notice The Uniswap v4 PoolManager contract function poolManager() external view returns (IPoolManager); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title IMulticall_v4 /// @notice Interface for the Multicall_v4 contract interface IMulticall_v4 { /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` is passed onto all subcalls, even if a previous subcall has consumed the ether. /// Subcalls can instead use `address(this).value` to see the available ETH, and consume it using {value: x}. /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ISubscriber} from "./ISubscriber.sol"; /// @title INotifier /// @notice Interface for the Notifier contract interface INotifier { /// @notice Thrown when unsubscribing without a subscriber error NotSubscribed(); /// @notice Thrown when a subscriber does not have code error NoCodeSubscriber(); /// @notice Thrown when a user specifies a gas limit too low to avoid valid unsubscribe notifications error GasLimitTooLow(); /// @notice Wraps the revert message of the subscriber contract on a reverting subscription error SubscriptionReverted(address subscriber, bytes reason); /// @notice Wraps the revert message of the subscriber contract on a reverting modify liquidity notification error ModifyLiquidityNotificationReverted(address subscriber, bytes reason); /// @notice Wraps the revert message of the subscriber contract on a reverting burn notification error BurnNotificationReverted(address subscriber, bytes reason); /// @notice Thrown when a tokenId already has a subscriber error AlreadySubscribed(uint256 tokenId, address subscriber); /// @notice Emitted on a successful call to subscribe event Subscription(uint256 indexed tokenId, address indexed subscriber); /// @notice Emitted on a successful call to unsubscribe event Unsubscription(uint256 indexed tokenId, address indexed subscriber); /// @notice Returns the subscriber for a respective position /// @param tokenId the ERC721 tokenId /// @return subscriber the subscriber contract function subscriber(uint256 tokenId) external view returns (ISubscriber subscriber); /// @notice Enables the subscriber to receive notifications for a respective position /// @param tokenId the ERC721 tokenId /// @param newSubscriber the address of the subscriber contract /// @param data caller-provided data that's forwarded to the subscriber contract /// @dev Calling subscribe when a position is already subscribed will revert /// @dev payable so it can be multicalled with NATIVE related actions /// @dev will revert if pool manager is locked function subscribe(uint256 tokenId, address newSubscriber, bytes calldata data) external payable; /// @notice Removes the subscriber from receiving notifications for a respective position /// @param tokenId the ERC721 tokenId /// @dev Callers must specify a high gas limit (remaining gas should be higher than unsubscriberGasLimit) such that the subscriber can be notified /// @dev payable so it can be multicalled with NATIVE related actions /// @dev Must always allow a user to unsubscribe. In the case of a malicious subscriber, a user can always unsubscribe safely, ensuring liquidity is always modifiable. /// @dev will revert if pool manager is locked function unsubscribe(uint256 tokenId) external payable; /// @notice Returns and determines the maximum allowable gas-used for notifying unsubscribe /// @return uint256 the maximum gas limit when notifying a subscriber's `notifyUnsubscribe` function function unsubscribeGasLimit() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; /// @title IPoolInitializer_v4 /// @notice Interface for the PoolInitializer_v4 contract interface IPoolInitializer_v4 { /// @notice Initialize a Uniswap v4 Pool /// @dev If the pool is already initialized, this function will not revert and just return type(int24).max /// @param key The PoolKey of the pool to initialize /// @param sqrtPriceX96 The initial starting price of the pool, expressed as a sqrtPriceX96 /// @return The current tick of the pool, or type(int24).max if the pool creation failed, or the pool already existed function initializePool(PoolKey calldata key, uint160 sqrtPriceX96) external payable returns (int24); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol"; import {PoolId} from "@uniswap/v4-core/src/types/PoolId.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {Position} from "@uniswap/v4-core/src/libraries/Position.sol"; import {IImmutableState} from "../interfaces/IImmutableState.sol"; /// @title IStateView /// @notice Interface for the StateView contract interface IStateView is IImmutableState { /// @notice Get Slot0 of the pool: sqrtPriceX96, tick, protocolFee, lpFee /// @dev Corresponds to pools[poolId].slot0 /// @param poolId The ID of the pool. /// @return sqrtPriceX96 The square root of the price of the pool, in Q96 precision. /// @return tick The current tick of the pool. /// @return protocolFee The protocol fee of the pool. /// @return lpFee The swap fee of the pool. function getSlot0(PoolId poolId) external view returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee); /// @notice Retrieves the tick information of a pool at a specific tick. /// @dev Corresponds to pools[poolId].ticks[tick] /// @param poolId The ID of the pool. /// @param tick The tick to retrieve information for. /// @return liquidityGross The total position liquidity that references this tick /// @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left) /// @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) /// @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) function getTickInfo(PoolId poolId, int24 tick) external view returns ( uint128 liquidityGross, int128 liquidityNet, uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128 ); /// @notice Retrieves the liquidity information of a pool at a specific tick. /// @dev Corresponds to pools[poolId].ticks[tick].liquidityGross and pools[poolId].ticks[tick].liquidityNet. A more gas efficient version of getTickInfo /// @param poolId The ID of the pool. /// @param tick The tick to retrieve liquidity for. /// @return liquidityGross The total position liquidity that references this tick /// @return liquidityNet The amount of net liquidity added (subtracted) when tick is crossed from left to right (right to left) function getTickLiquidity(PoolId poolId, int24 tick) external view returns (uint128 liquidityGross, int128 liquidityNet); /// @notice Retrieves the fee growth outside a tick range of a pool /// @dev Corresponds to pools[poolId].ticks[tick].feeGrowthOutside0X128 and pools[poolId].ticks[tick].feeGrowthOutside1X128. A more gas efficient version of getTickInfo /// @param poolId The ID of the pool. /// @param tick The tick to retrieve fee growth for. /// @return feeGrowthOutside0X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) /// @return feeGrowthOutside1X128 fee growth per unit of liquidity on the _other_ side of this tick (relative to the current tick) function getTickFeeGrowthOutside(PoolId poolId, int24 tick) external view returns (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128); /// @notice Retrieves the global fee growth of a pool. /// @dev Corresponds to pools[poolId].feeGrowthGlobal0X128 and pools[poolId].feeGrowthGlobal1X128 /// @param poolId The ID of the pool. /// @return feeGrowthGlobal0 The global fee growth for token0. /// @return feeGrowthGlobal1 The global fee growth for token1. function getFeeGrowthGlobals(PoolId poolId) external view returns (uint256 feeGrowthGlobal0, uint256 feeGrowthGlobal1); /// @notice Retrieves the total liquidity of a pool. /// @dev Corresponds to pools[poolId].liquidity /// @param poolId The ID of the pool. /// @return liquidity The liquidity of the pool. function getLiquidity(PoolId poolId) external view returns (uint128 liquidity); /// @notice Retrieves the tick bitmap of a pool at a specific tick. /// @dev Corresponds to pools[poolId].tickBitmap[tick] /// @param poolId The ID of the pool. /// @param tick The tick to retrieve the bitmap for. /// @return tickBitmap The bitmap of the tick. function getTickBitmap(PoolId poolId, int16 tick) external view returns (uint256 tickBitmap); /// @notice Retrieves the position info without needing to calculate the `positionId`. /// @dev Corresponds to pools[poolId].positions[positionId] /// @param poolId The ID of the pool. /// @param owner The owner of the liquidity position. /// @param tickLower The lower tick of the liquidity range. /// @param tickUpper The upper tick of the liquidity range. /// @param salt The bytes32 randomness to further distinguish position state. /// @return liquidity The liquidity of the position. /// @return feeGrowthInside0LastX128 The fee growth inside the position for token0. /// @return feeGrowthInside1LastX128 The fee growth inside the position for token1. function getPositionInfo(PoolId poolId, address owner, int24 tickLower, int24 tickUpper, bytes32 salt) external view returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128); /// @notice Retrieves the position information of a pool at a specific position ID. /// @dev Corresponds to pools[poolId].positions[positionId] /// @param poolId The ID of the pool. /// @param positionId The ID of the position. /// @return liquidity The liquidity of the position. /// @return feeGrowthInside0LastX128 The fee growth inside the position for token0. /// @return feeGrowthInside1LastX128 The fee growth inside the position for token1. function getPositionInfo(PoolId poolId, bytes32 positionId) external view returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128); /// @notice Retrieves the liquidity of a position. /// @dev Corresponds to pools[poolId].positions[positionId].liquidity. More gas efficient for just retrieving liquidity as compared to getPositionInfo /// @param poolId The ID of the pool. /// @param positionId The ID of the position. /// @return liquidity The liquidity of the position. function getPositionLiquidity(PoolId poolId, bytes32 positionId) external view returns (uint128 liquidity); /// @notice Calculate the fee growth inside a tick range of a pool /// @dev pools[poolId].feeGrowthInside0LastX128 in Position.Info is cached and can become stale. This function will calculate the up to date feeGrowthInside /// @param poolId The ID of the pool. /// @param tickLower The lower tick of the range. /// @param tickUpper The upper tick of the range. /// @return feeGrowthInside0X128 The fee growth inside the tick range for token0. /// @return feeGrowthInside1X128 The fee growth inside the tick range for token1. function getFeeGrowthInside(PoolId poolId, int24 tickLower, int24 tickUpper) external view returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {PositionInfo} from "../libraries/PositionInfoLibrary.sol"; /// @title ISubscriber /// @notice Interface that a Subscriber contract should implement to receive updates from the v4 position manager interface ISubscriber { /// @notice Called when a position subscribes to this subscriber contract /// @param tokenId the token ID of the position /// @param data additional data passed in by the caller function notifySubscribe(uint256 tokenId, bytes memory data) external; /// @notice Called when a position unsubscribes from the subscriber /// @dev This call's gas is capped at `unsubscribeGasLimit` (set at deployment) /// @dev Because of EIP-150, solidity may only allocate 63/64 of gasleft() /// @param tokenId the token ID of the position function notifyUnsubscribe(uint256 tokenId) external; /// @notice Called when a position is burned /// @param tokenId the token ID of the position /// @param owner the current owner of the tokenId /// @param info information about the position /// @param liquidity the amount of liquidity decreased in the position, may be 0 /// @param feesAccrued the fees accrued by the position if liquidity was decreased function notifyBurn(uint256 tokenId, address owner, PositionInfo info, uint256 liquidity, BalanceDelta feesAccrued) external; /// @notice Called when a position modifies its liquidity or collects fees /// @param tokenId the token ID of the position /// @param liquidityChange the change in liquidity on the underlying position /// @param feesAccrued the fees to be collected from the position as a result of the modifyLiquidity call /// @dev Note that feesAccrued can be artificially inflated by a malicious user /// Pools with a single liquidity position can inflate feeGrowthGlobal (and consequently feesAccrued) by donating to themselves; /// atomically donating and collecting fees within the same unlockCallback may further inflate feeGrowthGlobal/feesAccrued function notifyModifyLiquidity(uint256 tokenId, int256 liquidityChange, BalanceDelta feesAccrued) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.26; /// @title IUniswapV4DeployerCompetition /// @notice Interface for the UniswapV4DeployerCompetition contract interface IUniswapV4DeployerCompetition { event NewAddressFound(address indexed bestAddress, address indexed submitter, uint256 score); error InvalidBytecode(); error CompetitionNotOver(uint256 currentTime, uint256 deadline); error CompetitionOver(uint256 currentTime, uint256 deadline); error NotAllowedToDeploy(address sender, address deployer); error WorseAddress(address newAddress, address bestAddress, uint256 newScore, uint256 bestScore); error InvalidSender(bytes32 salt, address sender); /// @notice Updates the best address if the new address has a better vanity score /// @param salt The salt to use to compute the new address with CREATE2 /// @dev The first 20 bytes of the salt must be either address(0) or msg.sender function updateBestAddress(bytes32 salt) external; /// @notice deploys the Uniswap v4 PoolManager contract /// @param bytecode The bytecode of the Uniswap v4 PoolManager contract /// @dev The bytecode must match the initCodeHash function deploy(bytes memory bytecode) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title IUnorderedNonce /// @notice Interface for the UnorderedNonce contract interface IUnorderedNonce { error NonceAlreadyUsed(); /// @notice mapping of nonces consumed by each address, where a nonce is a single bit on the 256-bit bitmap /// @dev word is at most type(uint248).max function nonces(address owner, uint256 word) external view returns (uint256); /// @notice Revoke a nonce by spending it, preventing it from being used again /// @dev Used in cases where a valid nonce has not been broadcasted onchain, and the owner wants to revoke the validity of the nonce /// @dev payable so it can be multicalled with native-token related actions function revokeNonce(uint256 nonce) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {PathKey} from "../libraries/PathKey.sol"; import {IImmutableState} from "./IImmutableState.sol"; /// @title IV4Quoter /// @notice Interface for the V4Quoter contract interface IV4Quoter is IImmutableState { struct QuoteExactSingleParams { PoolKey poolKey; bool zeroForOne; uint128 exactAmount; bytes hookData; } struct QuoteExactParams { Currency exactCurrency; PathKey[] path; uint128 exactAmount; } /// @notice Returns the delta amounts for a given exact input swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactSingleParams` /// poolKey The key for identifying a V4 pool /// zeroForOne If the swap is from currency0 to currency1 /// exactAmount The desired input amount /// hookData arbitrary hookData to pass into the associated hooks /// @return amountOut The output quote for the exactIn swap /// @return gasEstimate Estimated gas units used for the swap function quoteExactInputSingle(QuoteExactSingleParams memory params) external returns (uint256 amountOut, uint256 gasEstimate); /// @notice Returns the delta amounts along the swap path for a given exact input swap /// @param params the params for the quote, encoded as 'QuoteExactParams' /// currencyIn The input currency of the swap /// path The path of the swap encoded as PathKeys that contains currency, fee, tickSpacing, and hook info /// exactAmount The desired input amount /// @return amountOut The output quote for the exactIn swap /// @return gasEstimate Estimated gas units used for the swap function quoteExactInput(QuoteExactParams memory params) external returns (uint256 amountOut, uint256 gasEstimate); /// @notice Returns the delta amounts for a given exact output swap of a single pool /// @param params The params for the quote, encoded as `QuoteExactSingleParams` /// poolKey The key for identifying a V4 pool /// zeroForOne If the swap is from currency0 to currency1 /// exactAmount The desired output amount /// hookData arbitrary hookData to pass into the associated hooks /// @return amountIn The input quote for the exactOut swap /// @return gasEstimate Estimated gas units used for the swap function quoteExactOutputSingle(QuoteExactSingleParams memory params) external returns (uint256 amountIn, uint256 gasEstimate); /// @notice Returns the delta amounts along the swap path for a given exact output swap /// @param params the params for the quote, encoded as 'QuoteExactParams' /// currencyOut The output currency of the swap /// path The path of the swap encoded as PathKeys that contains currency, fee, tickSpacing, and hook info /// exactAmount The desired output amount /// @return amountIn The input quote for the exactOut swap /// @return gasEstimate Estimated gas units used for the swap function quoteExactOutput(QuoteExactParams memory params) external returns (uint256 amountIn, uint256 gasEstimate); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {PathKey} from "../libraries/PathKey.sol"; import {IImmutableState} from "./IImmutableState.sol"; /// @title IV4Router /// @notice Interface for the V4Router contract interface IV4Router is IImmutableState { /// @notice Emitted when an exactInput swap does not receive its minAmountOut error V4TooLittleReceived(uint256 minAmountOutReceived, uint256 amountReceived); /// @notice Emitted when an exactOutput is asked for more than its maxAmountIn error V4TooMuchRequested(uint256 maxAmountInRequested, uint256 amountRequested); /// @notice Parameters for a single-hop exact-input swap struct ExactInputSingleParams { PoolKey poolKey; bool zeroForOne; uint128 amountIn; uint128 amountOutMinimum; bytes hookData; } /// @notice Parameters for a multi-hop exact-input swap struct ExactInputParams { Currency currencyIn; PathKey[] path; uint128 amountIn; uint128 amountOutMinimum; } /// @notice Parameters for a single-hop exact-output swap struct ExactOutputSingleParams { PoolKey poolKey; bool zeroForOne; uint128 amountOut; uint128 amountInMaximum; bytes hookData; } /// @notice Parameters for a multi-hop exact-output swap struct ExactOutputParams { Currency currencyOut; PathKey[] path; uint128 amountOut; uint128 amountInMaximum; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @title IWETH9 interface IWETH9 is IERC20 { /// @notice Deposit ether to get wrapped ether function deposit() external payable; /// @notice Withdraw wrapped ether to get ether function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Action Constants /// @notice Common constants used in actions /// @dev Constants are gas efficient alternatives to their literal values library ActionConstants { /// @notice used to signal that an action should use the input value of the open delta on the pool manager /// or of the balance that the contract holds uint128 internal constant OPEN_DELTA = 0; /// @notice used to signal that an action should use the contract's entire balance of a currency /// This value is equivalent to 1<<255, i.e. a singular 1 in the most significant bit. uint256 internal constant CONTRACT_BALANCE = 0x8000000000000000000000000000000000000000000000000000000000000000; /// @notice used to signal that the recipient of an action should be the msgSender address internal constant MSG_SENDER = address(1); /// @notice used to signal that the recipient of an action should be the address(this) address internal constant ADDRESS_THIS = address(2); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice Library to define different pool actions. /// @dev These are suggested common commands, however additional commands should be defined as required /// Some of these actions are not supported in the Router contracts or Position Manager contracts, but are left as they may be helpful commands for other peripheral contracts. library Actions { // pool actions // liquidity actions uint256 internal constant INCREASE_LIQUIDITY = 0x00; uint256 internal constant DECREASE_LIQUIDITY = 0x01; uint256 internal constant MINT_POSITION = 0x02; uint256 internal constant BURN_POSITION = 0x03; uint256 internal constant INCREASE_LIQUIDITY_FROM_DELTAS = 0x04; uint256 internal constant MINT_POSITION_FROM_DELTAS = 0x05; // swapping uint256 internal constant SWAP_EXACT_IN_SINGLE = 0x06; uint256 internal constant SWAP_EXACT_IN = 0x07; uint256 internal constant SWAP_EXACT_OUT_SINGLE = 0x08; uint256 internal constant SWAP_EXACT_OUT = 0x09; // donate // note this is not supported in the position manager or router uint256 internal constant DONATE = 0x0a; // closing deltas on the pool manager // settling uint256 internal constant SETTLE = 0x0b; uint256 internal constant SETTLE_ALL = 0x0c; uint256 internal constant SETTLE_PAIR = 0x0d; // taking uint256 internal constant TAKE = 0x0e; uint256 internal constant TAKE_ALL = 0x0f; uint256 internal constant TAKE_PORTION = 0x10; uint256 internal constant TAKE_PAIR = 0x11; uint256 internal constant CLOSE_CURRENCY = 0x12; uint256 internal constant CLEAR_OR_TAKE = 0x13; uint256 internal constant SWEEP = 0x14; uint256 internal constant WRAP = 0x15; uint256 internal constant UNWRAP = 0x16; // minting/burning 6909s to close deltas // note this is not supported in the position manager or router uint256 internal constant MINT_6909 = 0x17; uint256 internal constant BURN_6909 = 0x18; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title AddressStringUtil /// @notice provides utility functions for converting addresses to strings /// @dev Reference: https://github.com/Uniswap/solidity-lib/blob/master/contracts/libraries/AddressStringUtil.sol library AddressStringUtil { error InvalidAddressLength(uint256 len); /// @notice Converts an address to the uppercase hex string, extracting only len bytes (up to 20, multiple of 2) /// @param addr the address to convert /// @param len the number of bytes to extract /// @return the hex string function toAsciiString(address addr, uint256 len) internal pure returns (string memory) { if (!(len % 2 == 0 && len > 0 && len <= 40)) { revert InvalidAddressLength(len); } bytes memory s = new bytes(len); uint256 addrNum = uint256(uint160(addr)); for (uint256 i = 0; i < len / 2; i++) { // shift right and truncate all but the least significant byte to extract the byte at position 19-i uint8 b = uint8(addrNum >> (8 * (19 - i))); // first hex character is the most significant 4 bits uint8 hi = b >> 4; // second hex character is the least significant 4 bits uint8 lo = b - (hi << 4); s[2 * i] = char(hi); s[2 * i + 1] = char(lo); } return string(s); } /// @notice Converts a value into is corresponding ASCII character for the hex representation // hi and lo are only 4 bits and between 0 and 16 // uses upper case for the characters /// @param b the value to convert /// @return c the ASCII character function char(uint8 b) private pure returns (bytes1 c) { if (b < 10) { return bytes1(b + 0x30); } else { return bytes1(b + 0x37); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title For calculating a percentage of an amount, using bips library BipsLibrary { uint256 internal constant BPS_DENOMINATOR = 10_000; /// @notice emitted when an invalid percentage is provided error InvalidBips(); /// @param amount The total amount to calculate a percentage of /// @param bips The percentage to calculate, in bips function calculatePortion(uint256 amount, uint256 bips) internal pure returns (uint256) { if (bips > BPS_DENOMINATOR) revert InvalidBips(); return (amount * bips) / BPS_DENOMINATOR; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {IV4Router} from "../interfaces/IV4Router.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; /// @title Library for abi decoding in calldata library CalldataDecoder { using CalldataDecoder for bytes; error SliceOutOfBounds(); /// @notice mask used for offsets and lengths to ensure no overflow /// @dev no sane abi encoding will pass in an offset or length greater than type(uint32).max /// (note that this does deviate from standard solidity behavior and offsets/lengths will /// be interpreted as mod type(uint32).max which will only impact malicious/buggy callers) uint256 constant OFFSET_OR_LENGTH_MASK = 0xffffffff; uint256 constant OFFSET_OR_LENGTH_MASK_AND_WORD_ALIGN = 0xffffffe0; /// @notice equivalent to SliceOutOfBounds.selector, stored in least-significant bits uint256 constant SLICE_ERROR_SELECTOR = 0x3b99b53d; /// @dev equivalent to: abi.decode(params, (bytes, bytes[])) in calldata (requires strict abi encoding) function decodeActionsRouterParams(bytes calldata _bytes) internal pure returns (bytes calldata actions, bytes[] calldata params) { assembly ("memory-safe") { // Strict encoding requires that the data begin with: // 0x00: 0x40 (offset to `actions.length`) // 0x20: 0x60 + actions.length (offset to `params.length`) // 0x40: `actions.length` // 0x60: beginning of actions // Verify actions offset matches strict encoding let invalidData := xor(calldataload(_bytes.offset), 0x40) actions.offset := add(_bytes.offset, 0x60) actions.length := and(calldataload(add(_bytes.offset, 0x40)), OFFSET_OR_LENGTH_MASK) // Round actions length up to be word-aligned, and add 0x60 (for the first 3 words of encoding) let paramsLengthOffset := add(and(add(actions.length, 0x1f), OFFSET_OR_LENGTH_MASK_AND_WORD_ALIGN), 0x60) // Verify params offset matches strict encoding invalidData := or(invalidData, xor(calldataload(add(_bytes.offset, 0x20)), paramsLengthOffset)) let paramsLengthPointer := add(_bytes.offset, paramsLengthOffset) params.length := and(calldataload(paramsLengthPointer), OFFSET_OR_LENGTH_MASK) params.offset := add(paramsLengthPointer, 0x20) // Expected offset for `params[0]` is params.length * 32 // As the first `params.length` slots are pointers to each of the array element lengths let tailOffset := shl(5, params.length) let expectedOffset := tailOffset for { let offset := 0 } lt(offset, tailOffset) { offset := add(offset, 32) } { let itemLengthOffset := calldataload(add(params.offset, offset)) // Verify that the offset matches the expected offset from strict encoding invalidData := or(invalidData, xor(itemLengthOffset, expectedOffset)) let itemLengthPointer := add(params.offset, itemLengthOffset) let length := add(and(add(calldataload(itemLengthPointer), 0x1f), OFFSET_OR_LENGTH_MASK_AND_WORD_ALIGN), 0x20) expectedOffset := add(expectedOffset, length) } // if the data encoding was invalid, or the provided bytes string isnt as long as the encoding says, revert if or(invalidData, lt(add(_bytes.length, _bytes.offset), add(params.offset, expectedOffset))) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } } } /// @dev equivalent to: abi.decode(params, (uint256, uint256, uint128, uint128, bytes)) in calldata function decodeModifyLiquidityParams(bytes calldata params) internal pure returns (uint256 tokenId, uint256 liquidity, uint128 amount0, uint128 amount1, bytes calldata hookData) { // no length check performed, as there is a length check in `toBytes` assembly ("memory-safe") { tokenId := calldataload(params.offset) liquidity := calldataload(add(params.offset, 0x20)) amount0 := calldataload(add(params.offset, 0x40)) amount1 := calldataload(add(params.offset, 0x60)) } hookData = params.toBytes(4); } /// @dev equivalent to: abi.decode(params, (uint256, uint128, uint128, bytes)) in calldata function decodeIncreaseLiquidityFromDeltasParams(bytes calldata params) internal pure returns (uint256 tokenId, uint128 amount0Max, uint128 amount1Max, bytes calldata hookData) { // no length check performed, as there is a length check in `toBytes` assembly ("memory-safe") { tokenId := calldataload(params.offset) amount0Max := calldataload(add(params.offset, 0x20)) amount1Max := calldataload(add(params.offset, 0x40)) } hookData = params.toBytes(3); } /// @dev equivalent to: abi.decode(params, (PoolKey, int24, int24, uint256, uint128, uint128, address, bytes)) in calldata function decodeMintParams(bytes calldata params) internal pure returns ( PoolKey calldata poolKey, int24 tickLower, int24 tickUpper, uint256 liquidity, uint128 amount0Max, uint128 amount1Max, address owner, bytes calldata hookData ) { // no length check performed, as there is a length check in `toBytes` assembly ("memory-safe") { poolKey := params.offset tickLower := calldataload(add(params.offset, 0xa0)) tickUpper := calldataload(add(params.offset, 0xc0)) liquidity := calldataload(add(params.offset, 0xe0)) amount0Max := calldataload(add(params.offset, 0x100)) amount1Max := calldataload(add(params.offset, 0x120)) owner := calldataload(add(params.offset, 0x140)) } hookData = params.toBytes(11); } /// @dev equivalent to: abi.decode(params, (PoolKey, int24, int24, uint128, uint128, address, bytes)) in calldata function decodeMintFromDeltasParams(bytes calldata params) internal pure returns ( PoolKey calldata poolKey, int24 tickLower, int24 tickUpper, uint128 amount0Max, uint128 amount1Max, address owner, bytes calldata hookData ) { // no length check performed, as there is a length check in `toBytes` assembly ("memory-safe") { poolKey := params.offset tickLower := calldataload(add(params.offset, 0xa0)) tickUpper := calldataload(add(params.offset, 0xc0)) amount0Max := calldataload(add(params.offset, 0xe0)) amount1Max := calldataload(add(params.offset, 0x100)) owner := calldataload(add(params.offset, 0x120)) } hookData = params.toBytes(10); } /// @dev equivalent to: abi.decode(params, (uint256, uint128, uint128, bytes)) in calldata function decodeBurnParams(bytes calldata params) internal pure returns (uint256 tokenId, uint128 amount0Min, uint128 amount1Min, bytes calldata hookData) { // no length check performed, as there is a length check in `toBytes` assembly ("memory-safe") { tokenId := calldataload(params.offset) amount0Min := calldataload(add(params.offset, 0x20)) amount1Min := calldataload(add(params.offset, 0x40)) } hookData = params.toBytes(3); } /// @dev equivalent to: abi.decode(params, (IV4Router.ExactInputParams)) function decodeSwapExactInParams(bytes calldata params) internal pure returns (IV4Router.ExactInputParams calldata swapParams) { // ExactInputParams is a variable length struct so we just have to look up its location assembly ("memory-safe") { // only safety checks for the minimum length, where path is empty // 0xa0 = 5 * 0x20 -> 3 elements, path offset, and path length 0 if lt(params.length, 0xa0) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } swapParams := add(params.offset, calldataload(params.offset)) } } /// @dev equivalent to: abi.decode(params, (IV4Router.ExactInputSingleParams)) function decodeSwapExactInSingleParams(bytes calldata params) internal pure returns (IV4Router.ExactInputSingleParams calldata swapParams) { // ExactInputSingleParams is a variable length struct so we just have to look up its location assembly ("memory-safe") { // only safety checks for the minimum length, where hookData is empty // 0x140 = 10 * 0x20 -> 8 elements, bytes offset, and bytes length 0 if lt(params.length, 0x140) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } swapParams := add(params.offset, calldataload(params.offset)) } } /// @dev equivalent to: abi.decode(params, (IV4Router.ExactOutputParams)) function decodeSwapExactOutParams(bytes calldata params) internal pure returns (IV4Router.ExactOutputParams calldata swapParams) { // ExactOutputParams is a variable length struct so we just have to look up its location assembly ("memory-safe") { // only safety checks for the minimum length, where path is empty // 0xa0 = 5 * 0x20 -> 3 elements, path offset, and path length 0 if lt(params.length, 0xa0) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } swapParams := add(params.offset, calldataload(params.offset)) } } /// @dev equivalent to: abi.decode(params, (IV4Router.ExactOutputSingleParams)) function decodeSwapExactOutSingleParams(bytes calldata params) internal pure returns (IV4Router.ExactOutputSingleParams calldata swapParams) { // ExactOutputSingleParams is a variable length struct so we just have to look up its location assembly ("memory-safe") { // only safety checks for the minimum length, where hookData is empty // 0x140 = 10 * 0x20 -> 8 elements, bytes offset, and bytes length 0 if lt(params.length, 0x140) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } swapParams := add(params.offset, calldataload(params.offset)) } } /// @dev equivalent to: abi.decode(params, (Currency)) in calldata function decodeCurrency(bytes calldata params) internal pure returns (Currency currency) { assembly ("memory-safe") { if lt(params.length, 0x20) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } currency := calldataload(params.offset) } } /// @dev equivalent to: abi.decode(params, (Currency, Currency)) in calldata function decodeCurrencyPair(bytes calldata params) internal pure returns (Currency currency0, Currency currency1) { assembly ("memory-safe") { if lt(params.length, 0x40) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } currency0 := calldataload(params.offset) currency1 := calldataload(add(params.offset, 0x20)) } } /// @dev equivalent to: abi.decode(params, (Currency, Currency, address)) in calldata function decodeCurrencyPairAndAddress(bytes calldata params) internal pure returns (Currency currency0, Currency currency1, address _address) { assembly ("memory-safe") { if lt(params.length, 0x60) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } currency0 := calldataload(params.offset) currency1 := calldataload(add(params.offset, 0x20)) _address := calldataload(add(params.offset, 0x40)) } } /// @dev equivalent to: abi.decode(params, (Currency, address)) in calldata function decodeCurrencyAndAddress(bytes calldata params) internal pure returns (Currency currency, address _address) { assembly ("memory-safe") { if lt(params.length, 0x40) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } currency := calldataload(params.offset) _address := calldataload(add(params.offset, 0x20)) } } /// @dev equivalent to: abi.decode(params, (Currency, address, uint256)) in calldata function decodeCurrencyAddressAndUint256(bytes calldata params) internal pure returns (Currency currency, address _address, uint256 amount) { assembly ("memory-safe") { if lt(params.length, 0x60) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } currency := calldataload(params.offset) _address := calldataload(add(params.offset, 0x20)) amount := calldataload(add(params.offset, 0x40)) } } /// @dev equivalent to: abi.decode(params, (Currency, uint256)) in calldata function decodeCurrencyAndUint256(bytes calldata params) internal pure returns (Currency currency, uint256 amount) { assembly ("memory-safe") { if lt(params.length, 0x40) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } currency := calldataload(params.offset) amount := calldataload(add(params.offset, 0x20)) } } /// @dev equivalent to: abi.decode(params, (uint256)) in calldata function decodeUint256(bytes calldata params) internal pure returns (uint256 amount) { assembly ("memory-safe") { if lt(params.length, 0x20) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } amount := calldataload(params.offset) } } /// @dev equivalent to: abi.decode(params, (Currency, uint256, bool)) in calldata function decodeCurrencyUint256AndBool(bytes calldata params) internal pure returns (Currency currency, uint256 amount, bool boolean) { assembly ("memory-safe") { if lt(params.length, 0x60) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } currency := calldataload(params.offset) amount := calldataload(add(params.offset, 0x20)) boolean := calldataload(add(params.offset, 0x40)) } } /// @notice Decode the `_arg`-th element in `_bytes` as `bytes` /// @param _bytes The input bytes string to extract a bytes string from /// @param _arg The index of the argument to extract function toBytes(bytes calldata _bytes, uint256 _arg) internal pure returns (bytes calldata res) { uint256 length; assembly ("memory-safe") { // The offset of the `_arg`-th element is `32 * arg`, which stores the offset of the length pointer. // shl(5, x) is equivalent to mul(32, x) let lengthPtr := add(_bytes.offset, and(calldataload(add(_bytes.offset, shl(5, _arg))), OFFSET_OR_LENGTH_MASK)) // the number of bytes in the bytes string length := and(calldataload(lengthPtr), OFFSET_OR_LENGTH_MASK) // the offset where the bytes string begins let offset := add(lengthPtr, 0x20) // assign the return parameters res.length := length res.offset := offset // if the provided bytes string isnt as long as the encoding says, revert if lt(add(_bytes.length, _bytes.offset), add(length, offset)) { mstore(0, SLICE_ERROR_SELECTOR) revert(0x1c, 4) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title CurrencyRatioSortOrder /// @notice Provides constants for sorting currencies when displaying price ratios /// Currencies given larger values will be in the numerator of the price ratio /// @dev Reference: https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/TokenRatioSortOrder.sol library CurrencyRatioSortOrder { int256 constant NUMERATOR_MOST = 300; int256 constant NUMERATOR_MORE = 200; int256 constant NUMERATOR = 100; int256 constant DENOMINATOR_MOST = -300; int256 constant DENOMINATOR_MORE = -200; int256 constant DENOMINATOR = -100; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol"; import {FullMath} from "@uniswap/v4-core/src/libraries/FullMath.sol"; import {LPFeeLibrary} from "@uniswap/v4-core/src/libraries/LPFeeLibrary.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; import {Base64} from "openzeppelin-contracts/contracts/utils/Base64.sol"; import {SVG} from "./SVG.sol"; import {HexStrings} from "./HexStrings.sol"; /// @title Descriptor /// @notice Describes NFT token positions /// @dev Reference: https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/NFTDescriptor.sol library Descriptor { using TickMath for int24; using Strings for uint256; using HexStrings for uint256; using LPFeeLibrary for uint24; uint256 constant sqrt10X128 = 1076067327063303206878105757264492625226; struct ConstructTokenURIParams { uint256 tokenId; address quoteCurrency; address baseCurrency; string quoteCurrencySymbol; string baseCurrencySymbol; uint8 quoteCurrencyDecimals; uint8 baseCurrencyDecimals; bool flipRatio; int24 tickLower; int24 tickUpper; int24 tickCurrent; int24 tickSpacing; uint24 fee; address poolManager; address hooks; } /// @notice Constructs the token URI for a Uniswap v4 NFT /// @param params Parameters needed to construct the token URI /// @return The token URI as a string function constructTokenURI(ConstructTokenURIParams memory params) internal pure returns (string memory) { string memory name = generateName(params, feeToPercentString(params.fee)); string memory descriptionPartOne = generateDescriptionPartOne( escapeSpecialCharacters(params.quoteCurrencySymbol), escapeSpecialCharacters(params.baseCurrencySymbol), addressToString(params.poolManager) ); string memory descriptionPartTwo = generateDescriptionPartTwo( params.tokenId.toString(), escapeSpecialCharacters(params.baseCurrencySymbol), params.quoteCurrency == address(0) ? "Native" : addressToString(params.quoteCurrency), params.baseCurrency == address(0) ? "Native" : addressToString(params.baseCurrency), params.hooks == address(0) ? "No Hook" : addressToString(params.hooks), feeToPercentString(params.fee) ); string memory image = Base64.encode(bytes(generateSVGImage(params))); return string( abi.encodePacked( "data:application/json;base64,", Base64.encode( bytes( abi.encodePacked( '{"name":"', name, '", "description":"', descriptionPartOne, descriptionPartTwo, '", "image": "', "data:image/svg+xml;base64,", image, '"}' ) ) ) ) ); } /// @notice Escapes special characters in a string if they are present function escapeSpecialCharacters(string memory symbol) internal pure returns (string memory) { bytes memory symbolBytes = bytes(symbol); uint8 specialCharCount = 0; // count the amount of double quotes, form feeds, new lines, carriage returns, or tabs in the symbol for (uint8 i = 0; i < symbolBytes.length; i++) { if (isSpecialCharacter(symbolBytes[i])) { specialCharCount++; } } if (specialCharCount > 0) { // create a new bytes array with enough space to hold the original bytes plus space for the backslashes to escape the special characters bytes memory escapedBytes = new bytes(symbolBytes.length + specialCharCount); uint256 index; for (uint8 i = 0; i < symbolBytes.length; i++) { // add a '\' before any double quotes, form feeds, new lines, carriage returns, or tabs if (isSpecialCharacter(symbolBytes[i])) { escapedBytes[index++] = "\\"; } // copy each byte from original string to the new array escapedBytes[index++] = symbolBytes[i]; } return string(escapedBytes); } return symbol; } /// @notice Generates the first part of the description for a Uniswap v4 NFT /// @param quoteCurrencySymbol The symbol of the quote currency /// @param baseCurrencySymbol The symbol of the base currency /// @param poolManager The address of the pool manager /// @return The first part of the description function generateDescriptionPartOne( string memory quoteCurrencySymbol, string memory baseCurrencySymbol, string memory poolManager ) private pure returns (string memory) { // displays quote currency first, then base currency return string( abi.encodePacked( "This NFT represents a liquidity position in a Uniswap v4 ", quoteCurrencySymbol, "-", baseCurrencySymbol, " pool. ", "The owner of this NFT can modify or redeem the position.\\n", "\\nPool Manager Address: ", poolManager, "\\n", quoteCurrencySymbol ) ); } /// @notice Generates the second part of the description for a Uniswap v4 NFTs /// @param tokenId The token ID /// @param baseCurrencySymbol The symbol of the base currency /// @param quoteCurrency The address of the quote currency /// @param baseCurrency The address of the base currency /// @param hooks The address of the hooks contract /// @param feeTier The fee tier of the pool /// @return The second part of the description function generateDescriptionPartTwo( string memory tokenId, string memory baseCurrencySymbol, string memory quoteCurrency, string memory baseCurrency, string memory hooks, string memory feeTier ) private pure returns (string memory) { return string( abi.encodePacked( " Address: ", quoteCurrency, "\\n", baseCurrencySymbol, " Address: ", baseCurrency, "\\nHook Address: ", hooks, "\\nFee Tier: ", feeTier, "\\nToken ID: ", tokenId, "\\n\\n", unicode"⚠️ DISCLAIMER: Due diligence is imperative when assessing this NFT. Make sure currency addresses match the expected currencies, as currency symbols may be imitated." ) ); } /// @notice Generates the name for a Uniswap v4 NFT /// @param params Parameters needed to generate the name /// @param feeTier The fee tier of the pool /// @return The name of the NFT function generateName(ConstructTokenURIParams memory params, string memory feeTier) private pure returns (string memory) { // image shows in terms of price, ie quoteCurrency/baseCurrency return string( abi.encodePacked( "Uniswap - ", feeTier, " - ", escapeSpecialCharacters(params.quoteCurrencySymbol), "/", escapeSpecialCharacters(params.baseCurrencySymbol), " - ", tickToDecimalString( !params.flipRatio ? params.tickLower : params.tickUpper, params.tickSpacing, params.baseCurrencyDecimals, params.quoteCurrencyDecimals, params.flipRatio ), "<>", tickToDecimalString( !params.flipRatio ? params.tickUpper : params.tickLower, params.tickSpacing, params.baseCurrencyDecimals, params.quoteCurrencyDecimals, params.flipRatio ) ) ); } struct DecimalStringParams { // significant figures of decimal uint256 sigfigs; // length of decimal string uint8 bufferLength; // ending index for significant figures (funtion works backwards when copying sigfigs) uint8 sigfigIndex; // index of decimal place (0 if no decimal) uint8 decimalIndex; // start index for trailing/leading 0's for very small/large numbers uint8 zerosStartIndex; // end index for trailing/leading 0's for very small/large numbers uint8 zerosEndIndex; // true if decimal number is less than one bool isLessThanOne; // true if string should include "%" bool isPercent; } function generateDecimalString(DecimalStringParams memory params) private pure returns (string memory) { bytes memory buffer = new bytes(params.bufferLength); if (params.isPercent) { buffer[buffer.length - 1] = "%"; } if (params.isLessThanOne) { buffer[0] = "0"; buffer[1] = "."; } // add leading/trailing 0's for (uint256 zerosCursor = params.zerosStartIndex; zerosCursor < params.zerosEndIndex + 1; zerosCursor++) { // converts the ASCII code for 0 (which is 48) into a bytes1 to store in the buffer buffer[zerosCursor] = bytes1(uint8(48)); } // add sigfigs while (params.sigfigs > 0) { if (params.decimalIndex > 0 && params.sigfigIndex == params.decimalIndex) { buffer[params.sigfigIndex--] = "."; } buffer[params.sigfigIndex] = bytes1(uint8(48 + (params.sigfigs % 10))); // can overflow when sigfigIndex = 0 unchecked { params.sigfigIndex--; } params.sigfigs /= 10; } return string(buffer); } /// @notice Gets the price (quote/base) at a specific tick in decimal form /// MIN or MAX are returned if tick is at the bottom or top of the price curve /// @param tick The tick (either tickLower or tickUpper) /// @param tickSpacing The tick spacing of the pool /// @param baseCurrencyDecimals The decimals of the base currency /// @param quoteCurrencyDecimals The decimals of the quote currency /// @param flipRatio True if the ratio was flipped /// @return The ratio value as a string function tickToDecimalString( int24 tick, int24 tickSpacing, uint8 baseCurrencyDecimals, uint8 quoteCurrencyDecimals, bool flipRatio ) internal pure returns (string memory) { if (tick == (TickMath.MIN_TICK / tickSpacing) * tickSpacing) { return !flipRatio ? "MIN" : "MAX"; } else if (tick == (TickMath.MAX_TICK / tickSpacing) * tickSpacing) { return !flipRatio ? "MAX" : "MIN"; } else { uint160 sqrtRatioX96 = TickMath.getSqrtPriceAtTick(tick); if (flipRatio) { sqrtRatioX96 = uint160(uint256(1 << 192) / sqrtRatioX96); } return fixedPointToDecimalString(sqrtRatioX96, baseCurrencyDecimals, quoteCurrencyDecimals); } } function sigfigsRounded(uint256 value, uint8 digits) private pure returns (uint256, bool) { bool extraDigit; if (digits > 5) { value = value / (10 ** (digits - 5)); } bool roundUp = value % 10 > 4; value = value / 10; if (roundUp) { value = value + 1; } // 99999 -> 100000 gives an extra sigfig if (value == 100000) { value /= 10; extraDigit = true; } return (value, extraDigit); } /// @notice Adjusts the sqrt price for different currencies with different decimals /// @param sqrtRatioX96 The sqrt price at a specific tick /// @param baseCurrencyDecimals The decimals of the base currency /// @param quoteCurrencyDecimals The decimals of the quote currency /// @return adjustedSqrtRatioX96 The adjusted sqrt price function adjustForDecimalPrecision(uint160 sqrtRatioX96, uint8 baseCurrencyDecimals, uint8 quoteCurrencyDecimals) private pure returns (uint256 adjustedSqrtRatioX96) { uint256 difference = abs(int256(uint256(baseCurrencyDecimals)) - (int256(uint256(quoteCurrencyDecimals)))); if (difference > 0 && difference <= 18) { if (baseCurrencyDecimals > quoteCurrencyDecimals) { adjustedSqrtRatioX96 = sqrtRatioX96 * (10 ** (difference / 2)); if (difference % 2 == 1) { adjustedSqrtRatioX96 = FullMath.mulDiv(adjustedSqrtRatioX96, sqrt10X128, 1 << 128); } } else { adjustedSqrtRatioX96 = sqrtRatioX96 / (10 ** (difference / 2)); if (difference % 2 == 1) { adjustedSqrtRatioX96 = FullMath.mulDiv(adjustedSqrtRatioX96, 1 << 128, sqrt10X128); } } } else { adjustedSqrtRatioX96 = uint256(sqrtRatioX96); } } /// @notice Absolute value of a signed integer /// @param x The signed integer /// @return The absolute value of x function abs(int256 x) private pure returns (uint256) { return uint256(x >= 0 ? x : -x); } function fixedPointToDecimalString(uint160 sqrtRatioX96, uint8 baseCurrencyDecimals, uint8 quoteCurrencyDecimals) internal pure returns (string memory) { uint256 adjustedSqrtRatioX96 = adjustForDecimalPrecision(sqrtRatioX96, baseCurrencyDecimals, quoteCurrencyDecimals); uint256 value = FullMath.mulDiv(adjustedSqrtRatioX96, adjustedSqrtRatioX96, 1 << 64); bool priceBelow1 = adjustedSqrtRatioX96 < 2 ** 96; if (priceBelow1) { // 10 ** 43 is precision needed to retreive 5 sigfigs of smallest possible price + 1 for rounding value = FullMath.mulDiv(value, 10 ** 44, 1 << 128); } else { // leave precision for 4 decimal places + 1 place for rounding value = FullMath.mulDiv(value, 10 ** 5, 1 << 128); } // get digit count uint256 temp = value; uint8 digits; while (temp != 0) { digits++; temp /= 10; } // don't count extra digit kept for rounding digits = digits - 1; // address rounding (uint256 sigfigs, bool extraDigit) = sigfigsRounded(value, digits); if (extraDigit) { digits++; } DecimalStringParams memory params; if (priceBelow1) { // 7 bytes ( "0." and 5 sigfigs) + leading 0's bytes params.bufferLength = uint8(uint8(7) + (uint8(43) - digits)); params.zerosStartIndex = 2; params.zerosEndIndex = uint8(uint256(43) - digits + 1); params.sigfigIndex = uint8(params.bufferLength - 1); } else if (digits >= 9) { // no decimal in price string params.bufferLength = uint8(digits - 4); params.zerosStartIndex = 5; params.zerosEndIndex = uint8(params.bufferLength - 1); params.sigfigIndex = 4; } else { // 5 sigfigs surround decimal params.bufferLength = 6; params.sigfigIndex = 5; params.decimalIndex = uint8(digits - 5 + 1); } params.sigfigs = sigfigs; params.isLessThanOne = priceBelow1; params.isPercent = false; return generateDecimalString(params); } /// @notice Converts fee amount in pips to decimal string with percent sign /// @param fee fee amount /// @return fee as a decimal string with percent sign function feeToPercentString(uint24 fee) internal pure returns (string memory) { if (fee.isDynamicFee()) { return "Dynamic"; } if (fee == 0) { return "0%"; } uint24 temp = fee; uint256 digits; uint8 numSigfigs; // iterates over each digit of fee by dividing temp by 10 in each iteration until temp becomes 0 // calculates number of digits and number of significant figures (non-zero digits) while (temp != 0) { if (numSigfigs > 0) { // count all digits preceding least significant figure numSigfigs++; } else if (temp % 10 != 0) { numSigfigs++; } digits++; temp /= 10; } DecimalStringParams memory params; uint256 nZeros; if (digits >= 5) { // represents fee greater than or equal to 1% // if decimal > 1 (5th digit is the ones place) uint256 decimalPlace = digits - numSigfigs >= 4 ? 0 : 1; nZeros = digits - 5 < numSigfigs - 1 ? 0 : digits - 5 - (numSigfigs - 1); params.zerosStartIndex = numSigfigs; params.zerosEndIndex = uint8(params.zerosStartIndex + nZeros - 1); params.sigfigIndex = uint8(params.zerosStartIndex - 1 + decimalPlace); params.bufferLength = uint8(nZeros + numSigfigs + 1 + decimalPlace); } else { // represents fee less than 1% // else if decimal < 1 nZeros = 5 - digits; // number of zeros, inlcuding the zero before decimal params.zerosStartIndex = 2; // leading zeros will start after the decimal point params.zerosEndIndex = uint8(nZeros + params.zerosStartIndex - 1); // end index for leading zeros params.bufferLength = uint8(nZeros + numSigfigs + 2); // total length of string buffer, including "0." and "%" params.sigfigIndex = uint8(params.bufferLength - 2); // index of starting signficant figure params.isLessThanOne = true; } params.sigfigs = uint256(fee) / (10 ** (digits - numSigfigs)); // the signficant figures of the fee params.isPercent = true; params.decimalIndex = digits > 4 ? uint8(digits - 4) : 0; // based on total number of digits in the fee return generateDecimalString(params); } function addressToString(address addr) internal pure returns (string memory) { return (uint256(uint160(addr))).toHexString(20); } /// @notice Generates the SVG image for a Uniswap v4 NFT /// @param params Parameters needed to generate the SVG image /// @return svg The SVG image as a string function generateSVGImage(ConstructTokenURIParams memory params) internal pure returns (string memory svg) { SVG.SVGParams memory svgParams = SVG.SVGParams({ quoteCurrency: addressToString(params.quoteCurrency), baseCurrency: addressToString(params.baseCurrency), hooks: params.hooks, quoteCurrencySymbol: params.quoteCurrencySymbol, baseCurrencySymbol: params.baseCurrencySymbol, feeTier: feeToPercentString(params.fee), tickLower: params.tickLower, tickUpper: params.tickUpper, tickSpacing: params.tickSpacing, overRange: overRange(params.tickLower, params.tickUpper, params.tickCurrent), tokenId: params.tokenId, color0: currencyToColorHex(uint256(uint160(params.quoteCurrency)), 136), color1: currencyToColorHex(uint256(uint160(params.baseCurrency)), 136), color2: currencyToColorHex(uint256(uint160(params.quoteCurrency)), 0), color3: currencyToColorHex(uint256(uint160(params.baseCurrency)), 0), x1: scale(getCircleCoord(uint256(uint160(params.quoteCurrency)), 16, params.tokenId), 0, 255, 16, 274), y1: scale(getCircleCoord(uint256(uint160(params.baseCurrency)), 16, params.tokenId), 0, 255, 100, 484), x2: scale(getCircleCoord(uint256(uint160(params.quoteCurrency)), 32, params.tokenId), 0, 255, 16, 274), y2: scale(getCircleCoord(uint256(uint160(params.baseCurrency)), 32, params.tokenId), 0, 255, 100, 484), x3: scale(getCircleCoord(uint256(uint160(params.quoteCurrency)), 48, params.tokenId), 0, 255, 16, 274), y3: scale(getCircleCoord(uint256(uint160(params.baseCurrency)), 48, params.tokenId), 0, 255, 100, 484) }); return SVG.generateSVG(svgParams); } /// @notice Checks if the current price is within your position range, above, or below /// @param tickLower The lower tick /// @param tickUpper The upper tick /// @param tickCurrent The current tick /// @return 0 if the current price is within the position range, -1 if below, 1 if above function overRange(int24 tickLower, int24 tickUpper, int24 tickCurrent) private pure returns (int8) { if (tickCurrent < tickLower) { return -1; } else if (tickCurrent > tickUpper) { return 1; } else { return 0; } } function isSpecialCharacter(bytes1 b) private pure returns (bool) { return b == '"' || b == "\u000c" || b == "\n" || b == "\r" || b == "\t"; } function scale(uint256 n, uint256 inMn, uint256 inMx, uint256 outMn, uint256 outMx) private pure returns (string memory) { return ((n - inMn) * (outMx - outMn) / (inMx - inMn) + outMn).toString(); } function currencyToColorHex(uint256 currency, uint256 offset) internal pure returns (string memory str) { return string((currency >> offset).toHexStringNoPrefix(3)); } function getCircleCoord(uint256 currency, uint256 offset, uint256 tokenId) internal pure returns (uint256) { return (sliceCurrencyHex(currency, offset) * tokenId) % 255; } function sliceCurrencyHex(uint256 currency, uint256 offset) internal pure returns (uint256) { return uint256(uint8(currency >> offset)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library ERC721PermitHash { /// @dev Value is equal to keccak256("Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)"); bytes32 constant PERMIT_TYPEHASH = 0x49ecf333e5b8c95c40fdafc95c1ad136e8914a8fb55e9dc8bb01eaa83a2df9ad; /// @dev Value is equal to keccak256("PermitForAll(address operator,bool approved,uint256 nonce,uint256 deadline)"); bytes32 constant PERMIT_FOR_ALL_TYPEHASH = 0x6673cb397ee2a50b6b8401653d3638b4ac8b3db9c28aa6870ffceb7574ec2f76; /// @notice Hashes the data that will be signed for IERC721Permit_v4.permit() /// @param spender The address which may spend the tokenId /// @param tokenId The tokenId of the owner, which may be spent by spender /// @param nonce A unique non-ordered value for each signature to prevent replay attacks /// @param deadline The time at which the signature expires /// @return digest The hash of the data to be signed; the equivalent to keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, nonce, deadline)); function hashPermit(address spender, uint256 tokenId, uint256 nonce, uint256 deadline) internal pure returns (bytes32 digest) { // equivalent to: keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, nonce, deadline)); assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, PERMIT_TYPEHASH) mstore(add(fmp, 0x20), and(spender, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(add(fmp, 0x40), tokenId) mstore(add(fmp, 0x60), nonce) mstore(add(fmp, 0x80), deadline) digest := keccak256(fmp, 0xa0) // now clean the memory we used mstore(fmp, 0) // fmp held PERMIT_TYPEHASH mstore(add(fmp, 0x20), 0) // fmp+0x20 held spender mstore(add(fmp, 0x40), 0) // fmp+0x40 held tokenId mstore(add(fmp, 0x60), 0) // fmp+0x60 held nonce mstore(add(fmp, 0x80), 0) // fmp+0x80 held deadline } } /// @notice Hashes the data that will be signed for IERC721Permit_v4.permit() /// @param operator The address which may spend any of the owner's tokenIds /// @param approved true if the operator is to have full permission over the owner's tokenIds; false otherwise /// @param nonce A unique non-ordered value for each signature to prevent replay attacks /// @param deadline The time at which the signature expires /// @return digest The hash of the data to be signed; the equivalent to keccak256(abi.encode(PERMIT_FOR_ALL_TYPEHASH, operator, approved, nonce, deadline)); function hashPermitForAll(address operator, bool approved, uint256 nonce, uint256 deadline) internal pure returns (bytes32 digest) { // equivalent to: keccak256(abi.encode(PERMIT_FOR_ALL_TYPEHASH, operator, approved, nonce, deadline)); assembly ("memory-safe") { let fmp := mload(0x40) mstore(fmp, PERMIT_FOR_ALL_TYPEHASH) mstore(add(fmp, 0x20), and(operator, 0xffffffffffffffffffffffffffffffffffffffff)) mstore(add(fmp, 0x40), and(approved, 0x1)) mstore(add(fmp, 0x60), nonce) mstore(add(fmp, 0x80), deadline) digest := keccak256(fmp, 0xa0) // now clean the memory we used mstore(fmp, 0) // fmp held PERMIT_FOR_ALL_TYPEHASH mstore(add(fmp, 0x20), 0) // fmp+0x20 held operator mstore(add(fmp, 0x40), 0) // fmp+0x40 held approved mstore(add(fmp, 0x60), 0) // fmp+0x60 held nonce mstore(add(fmp, 0x80), 0) // fmp+0x80 held deadline } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title HexStrings /// @notice Provides function for converting numbers to hexadecimal strings /// @dev Reference: https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/HexStrings.sol library HexStrings { bytes16 internal constant ALPHABET = "0123456789abcdef"; /// @notice Convert a number to a hex string without the '0x' prefix with a fixed length /// @param value The number to convert /// @param length The length of the output string, starting from the last character of the string /// @return The hex string function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length); for (uint256 i = buffer.length; i > 0; i--) { buffer[i - 1] = ALPHABET[value & 0xf]; value >>= 4; } return string(buffer); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {FullMath} from "@uniswap/v4-core/src/libraries/FullMath.sol"; import {FixedPoint96} from "@uniswap/v4-core/src/libraries/FixedPoint96.sol"; import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; /// @notice Provides functions for computing liquidity amounts from token amounts and prices library LiquidityAmounts { using SafeCast for uint256; /// @notice Computes the amount of liquidity received for a given amount of token0 and price range /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower)) /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary /// @param amount0 The amount0 being sent in /// @return liquidity The amount of returned liquidity function getLiquidityForAmount0(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount0) internal pure returns (uint128 liquidity) { unchecked { if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); uint256 intermediate = FullMath.mulDiv(sqrtPriceAX96, sqrtPriceBX96, FixedPoint96.Q96); return FullMath.mulDiv(amount0, intermediate, sqrtPriceBX96 - sqrtPriceAX96).toUint128(); } } /// @notice Computes the amount of liquidity received for a given amount of token1 and price range /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)). /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary /// @param amount1 The amount1 being sent in /// @return liquidity The amount of returned liquidity function getLiquidityForAmount1(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount1) internal pure returns (uint128 liquidity) { unchecked { if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); return FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtPriceBX96 - sqrtPriceAX96).toUint128(); } } /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current /// pool prices and the prices at the tick boundaries /// @param sqrtPriceX96 A sqrt price representing the current pool prices /// @param sqrtPriceAX96 A sqrt price representing the first tick boundary /// @param sqrtPriceBX96 A sqrt price representing the second tick boundary /// @param amount0 The amount of token0 being sent in /// @param amount1 The amount of token1 being sent in /// @return liquidity The maximum amount of liquidity received function getLiquidityForAmounts( uint160 sqrtPriceX96, uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, uint256 amount0, uint256 amount1 ) internal pure returns (uint128 liquidity) { if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); if (sqrtPriceX96 <= sqrtPriceAX96) { liquidity = getLiquidityForAmount0(sqrtPriceAX96, sqrtPriceBX96, amount0); } else if (sqrtPriceX96 < sqrtPriceBX96) { uint128 liquidity0 = getLiquidityForAmount0(sqrtPriceX96, sqrtPriceBX96, amount0); uint128 liquidity1 = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceX96, amount1); liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1; } else { liquidity = getLiquidityForAmount1(sqrtPriceAX96, sqrtPriceBX96, amount1); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /// @notice This is a temporary library that allows us to use transient storage (tstore/tload) /// TODO: This library can be deleted when we have the transient keyword support in solidity. library Locker { // The slot holding the locker state, transiently. bytes32(uint256(keccak256("LockedBy")) - 1) bytes32 constant LOCKED_BY_SLOT = 0x0aedd6bde10e3aa2adec092b02a3e3e805795516cda41f27aa145b8f300af87a; function set(address locker) internal { assembly { tstore(LOCKED_BY_SLOT, locker) } } function get() internal view returns (address locker) { assembly { locker := tload(LOCKED_BY_SLOT) } } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Currency} from "@uniswap/v4-core/src/types/Currency.sol"; import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; struct PathKey { Currency intermediateCurrency; uint24 fee; int24 tickSpacing; IHooks hooks; bytes hookData; } using PathKeyLibrary for PathKey global; /// @title PathKey Library /// @notice Functions for working with PathKeys library PathKeyLibrary { /// @notice Get the pool and swap direction for a given PathKey /// @param params the given PathKey /// @param currencyIn the input currency /// @return poolKey the pool key of the swap /// @return zeroForOne the direction of the swap, true if currency0 is being swapped for currency1 function getPoolAndSwapDirection(PathKey calldata params, Currency currencyIn) internal pure returns (PoolKey memory poolKey, bool zeroForOne) { Currency currencyOut = params.intermediateCurrency; (Currency currency0, Currency currency1) = currencyIn < currencyOut ? (currencyIn, currencyOut) : (currencyOut, currencyIn); zeroForOne = currencyIn == currency0; poolKey = PoolKey(currency0, currency1, params.fee, params.tickSpacing, params.hooks); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; // A PositionConfig is the input for creating and modifying a Position in core, whose truncated hash is set per tokenId struct PositionConfig { PoolKey poolKey; int24 tickLower; int24 tickUpper; } /// @notice Library to calculate the PositionConfigId from the PositionConfig struct library PositionConfigLibrary { function toId(PositionConfig calldata config) internal pure returns (bytes32 id) { // id = keccak256(abi.encodePacked(currency0, currency1, fee, tickSpacing, hooks, tickLower, tickUpper))) >> 1 assembly ("memory-safe") { let fmp := mload(0x40) mstore(add(fmp, 0x34), calldataload(add(config, 0xc0))) // tickUpper: [0x51, 0x54) mstore(add(fmp, 0x31), calldataload(add(config, 0xa0))) // tickLower: [0x4E, 0x51) mstore(add(fmp, 0x2E), calldataload(add(config, 0x80))) // hooks: [0x3A, 0x4E) mstore(add(fmp, 0x1A), calldataload(add(config, 0x60))) // tickSpacing: [0x37, 0x3A) mstore(add(fmp, 0x17), calldataload(add(config, 0x40))) // fee: [0x34, 0x37) mstore(add(fmp, 0x14), calldataload(add(config, 0x20))) // currency1: [0x20, 0x34) mstore(fmp, calldataload(config)) // currency0: [0x0c, 0x20) id := shr(1, keccak256(add(fmp, 0x0c), 0x48)) // len is 72 bytes, truncate lower bit of the hash // now clean the memory we used mstore(add(fmp, 0x40), 0) // fmp+0x40 held hooks (14 bytes), tickLower, tickUpper mstore(add(fmp, 0x20), 0) // fmp+0x20 held currency1, fee, tickSpacing, hooks (6 bytes) mstore(fmp, 0) // fmp held currency0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice A configId is set per tokenId /// The lower 255 bits are used to store the truncated hash of the corresponding PositionConfig /// The upper bit is used to signal if the tokenId has a subscriber struct PositionConfigId { bytes32 id; } library PositionConfigIdLibrary { bytes32 constant MASK_UPPER_BIT = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; bytes32 constant DIRTY_UPPER_BIT = 0x8000000000000000000000000000000000000000000000000000000000000000; /// @notice returns the truncated hash of the PositionConfig for a given tokenId function getConfigId(PositionConfigId storage _configId) internal view returns (bytes32 configId) { configId = _configId.id & MASK_UPPER_BIT; } /// @dev We only set the config on mint, guaranteeing that the most significant bit is unset, so we can just assign the entire 32 bytes to the id. function setConfigId(PositionConfigId storage _configId, bytes32 configId) internal { _configId.id = configId; } function setSubscribe(PositionConfigId storage configId) internal { configId.id |= DIRTY_UPPER_BIT; } function setUnsubscribe(PositionConfigId storage configId) internal { configId.id &= MASK_UPPER_BIT; } function hasSubscriber(PositionConfigId storage configId) internal view returns (bool subscribed) { bytes32 _id = configId.id; assembly ("memory-safe") { subscribed := shr(255, _id) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {PoolId} from "@uniswap/v4-core/src/types/PoolId.sol"; /** * @dev PositionInfo is a packed version of solidity structure. * Using the packaged version saves gas and memory by not storing the structure fields in memory slots. * * Layout: * 200 bits poolId | 24 bits tickUpper | 24 bits tickLower | 8 bits hasSubscriber * * Fields in the direction from the least significant bit: * * A flag to know if the tokenId is subscribed to an address * uint8 hasSubscriber; * * The tickUpper of the position * int24 tickUpper; * * The tickLower of the position * int24 tickLower; * * The truncated poolId. Truncates a bytes32 value so the most signifcant (highest) 200 bits are used. * bytes25 poolId; * * Note: If more bits are needed, hasSubscriber can be a single bit. * */ type PositionInfo is uint256; using PositionInfoLibrary for PositionInfo global; library PositionInfoLibrary { PositionInfo internal constant EMPTY_POSITION_INFO = PositionInfo.wrap(0); uint256 internal constant MASK_UPPER_200_BITS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000; uint256 internal constant MASK_8_BITS = 0xFF; uint24 internal constant MASK_24_BITS = 0xFFFFFF; uint256 internal constant SET_UNSUBSCRIBE = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00; uint256 internal constant SET_SUBSCRIBE = 0x01; uint8 internal constant TICK_LOWER_OFFSET = 8; uint8 internal constant TICK_UPPER_OFFSET = 32; /// @dev This poolId is NOT compatible with the poolId used in UniswapV4 core. It is truncated to 25 bytes, and just used to lookup PoolKey in the poolKeys mapping. function poolId(PositionInfo info) internal pure returns (bytes25 _poolId) { assembly ("memory-safe") { _poolId := and(MASK_UPPER_200_BITS, info) } } function tickLower(PositionInfo info) internal pure returns (int24 _tickLower) { assembly ("memory-safe") { _tickLower := signextend(2, shr(TICK_LOWER_OFFSET, info)) } } function tickUpper(PositionInfo info) internal pure returns (int24 _tickUpper) { assembly ("memory-safe") { _tickUpper := signextend(2, shr(TICK_UPPER_OFFSET, info)) } } function hasSubscriber(PositionInfo info) internal pure returns (bool _hasSubscriber) { assembly ("memory-safe") { _hasSubscriber := and(MASK_8_BITS, info) } } /// @dev this does not actually set any storage function setSubscribe(PositionInfo info) internal pure returns (PositionInfo _info) { assembly ("memory-safe") { _info := or(info, SET_SUBSCRIBE) } } /// @dev this does not actually set any storage function setUnsubscribe(PositionInfo info) internal pure returns (PositionInfo _info) { assembly ("memory-safe") { _info := and(info, SET_UNSUBSCRIBE) } } /// @notice Creates the default PositionInfo struct /// @dev Called when minting a new position /// @param _poolKey the pool key of the position /// @param _tickLower the lower tick of the position /// @param _tickUpper the upper tick of the position /// @return info packed position info, with the truncated poolId and the hasSubscriber flag set to false function initialize(PoolKey memory _poolKey, int24 _tickLower, int24 _tickUpper) internal pure returns (PositionInfo info) { bytes25 _poolId = bytes25(PoolId.unwrap(_poolKey.toId())); assembly { info := or( or(and(MASK_UPPER_200_BITS, _poolId), shl(TICK_UPPER_OFFSET, and(MASK_24_BITS, _tickUpper))), shl(TICK_LOWER_OFFSET, and(MASK_24_BITS, _tickLower)) ) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ParseBytes} from "@uniswap/v4-core/src/libraries/ParseBytes.sol"; library QuoterRevert { using QuoterRevert for bytes; using ParseBytes for bytes; /// @notice error thrown when invalid revert bytes are thrown by the quote error UnexpectedRevertBytes(bytes revertData); /// @notice error thrown containing the quote as the data, to be caught and parsed later error QuoteSwap(uint256 amount); /// @notice reverts, where the revert data is the provided bytes /// @dev called when quoting, to record the quote amount in an error /// @dev QuoteSwap is used to differentiate this error from other errors thrown when simulating the swap function revertQuote(uint256 quoteAmount) internal pure { revert QuoteSwap(quoteAmount); } /// @notice reverts using the revertData as the reason /// @dev to bubble up both the valid QuoteSwap(amount) error, or an alternative error thrown during simulation function bubbleReason(bytes memory revertData) internal pure { // mload(revertData): the length of the revert data // add(revertData, 0x20): a pointer to the start of the revert data assembly ("memory-safe") { revert(add(revertData, 0x20), mload(revertData)) } } /// @notice validates whether a revert reason is a valid swap quote or not /// if valid, it decodes the quote to return. Otherwise it reverts. function parseQuoteAmount(bytes memory reason) internal pure returns (uint256 quoteAmount) { // If the error doesnt start with QuoteSwap, we know this isnt a valid quote to parse // Instead it is another revert that was triggered somewhere in the simulation if (reason.parseSelector() != QuoteSwap.selector) { revert UnexpectedRevertBytes(reason); } // reason -> reason+0x1f is the length of the reason string // reason+0x20 -> reason+0x23 is the selector of QuoteSwap // reason+0x24 -> reason+0x43 is the quoteAmount assembly ("memory-safe") { quoteAmount := mload(add(reason, 0x24)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; import {BitMath} from "@uniswap/v4-core/src/libraries/BitMath.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; import {Base64} from "openzeppelin-contracts/contracts/utils/Base64.sol"; /// @title SVG /// @notice Provides a function for generating an SVG associated with a Uniswap NFT /// @dev Reference: https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/NFTSVG.sol library SVG { using Strings for uint256; // SVG path commands for the curve that represent the steepness of the position // defined using the Cubic Bezier Curve syntax // curve1 is the smallest (linear) curve, curve8 is the largest curve string constant curve1 = "M1 1C41 41 105 105 145 145"; string constant curve2 = "M1 1C33 49 97 113 145 145"; string constant curve3 = "M1 1C33 57 89 113 145 145"; string constant curve4 = "M1 1C25 65 81 121 145 145"; string constant curve5 = "M1 1C17 73 73 129 145 145"; string constant curve6 = "M1 1C9 81 65 137 145 145"; string constant curve7 = "M1 1C1 89 57.5 145 145 145"; string constant curve8 = "M1 1C1 97 49 145 145 145"; struct SVGParams { string quoteCurrency; string baseCurrency; address hooks; string quoteCurrencySymbol; string baseCurrencySymbol; string feeTier; int24 tickLower; int24 tickUpper; int24 tickSpacing; int8 overRange; uint256 tokenId; string color0; string color1; string color2; string color3; string x1; string y1; string x2; string y2; string x3; string y3; } /// @notice Generate the SVG associated with a Uniswap v4 NFT /// @param params The SVGParams struct containing the parameters for the SVG /// @return svg The SVG string associated with the NFT function generateSVG(SVGParams memory params) internal pure returns (string memory svg) { return string( abi.encodePacked( generateSVGDefs(params), generateSVGBorderText( params.quoteCurrency, params.baseCurrency, params.quoteCurrencySymbol, params.baseCurrencySymbol ), generateSVGCardMantle(params.quoteCurrencySymbol, params.baseCurrencySymbol, params.feeTier), generageSvgCurve(params.tickLower, params.tickUpper, params.tickSpacing, params.overRange), generateSVGPositionDataAndLocationCurve( params.tokenId.toString(), params.hooks, params.tickLower, params.tickUpper ), generateSVGRareSparkle(params.tokenId, params.hooks), "</svg>" ) ); } /// @notice Generate the SVG defs that create the color scheme for the SVG /// @param params The SVGParams struct containing the parameters to generate the SVG defs /// @return svg The SVG defs string function generateSVGDefs(SVGParams memory params) private pure returns (string memory svg) { svg = string( abi.encodePacked( '<svg width="290" height="500" viewBox="0 0 290 500" xmlns="http://www.w3.org/2000/svg"', " xmlns:xlink='http://www.w3.org/1999/xlink'>", "<defs>", '<filter id="f1"><feImage result="p0" xlink:href="data:image/svg+xml;base64,', Base64.encode( bytes( abi.encodePacked( "<svg width='290' height='500' viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><rect width='290px' height='500px' fill='#", params.color0, "'/></svg>" ) ) ), '"/><feImage result="p1" xlink:href="data:image/svg+xml;base64,', Base64.encode( bytes( abi.encodePacked( "<svg width='290' height='500' viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><circle cx='", params.x1, "' cy='", params.y1, "' r='120px' fill='#", params.color1, "'/></svg>" ) ) ), '"/><feImage result="p2" xlink:href="data:image/svg+xml;base64,', Base64.encode( bytes( abi.encodePacked( "<svg width='290' height='500' viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><circle cx='", params.x2, "' cy='", params.y2, "' r='120px' fill='#", params.color2, "'/></svg>" ) ) ), '" />', '<feImage result="p3" xlink:href="data:image/svg+xml;base64,', Base64.encode( bytes( abi.encodePacked( "<svg width='290' height='500' viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><circle cx='", params.x3, "' cy='", params.y3, "' r='100px' fill='#", params.color3, "'/></svg>" ) ) ), '" /><feBlend mode="overlay" in="p0" in2="p1" /><feBlend mode="exclusion" in2="p2" /><feBlend mode="overlay" in2="p3" result="blendOut" /><feGaussianBlur ', 'in="blendOut" stdDeviation="42" /></filter> <clipPath id="corners"><rect width="290" height="500" rx="42" ry="42" /></clipPath>', '<path id="text-path-a" d="M40 12 H250 A28 28 0 0 1 278 40 V460 A28 28 0 0 1 250 488 H40 A28 28 0 0 1 12 460 V40 A28 28 0 0 1 40 12 z" />', '<path id="minimap" d="M234 444C234 457.949 242.21 463 253 463" />', '<filter id="top-region-blur"><feGaussianBlur in="SourceGraphic" stdDeviation="24" /></filter>', '<linearGradient id="grad-up" x1="1" x2="0" y1="1" y2="0"><stop offset="0.0" stop-color="white" stop-opacity="1" />', '<stop offset=".9" stop-color="white" stop-opacity="0" /></linearGradient>', '<linearGradient id="grad-down" x1="0" x2="1" y1="0" y2="1"><stop offset="0.0" stop-color="white" stop-opacity="1" /><stop offset="0.9" stop-color="white" stop-opacity="0" /></linearGradient>', '<mask id="fade-up" maskContentUnits="objectBoundingBox"><rect width="1" height="1" fill="url(#grad-up)" /></mask>', '<mask id="fade-down" maskContentUnits="objectBoundingBox"><rect width="1" height="1" fill="url(#grad-down)" /></mask>', '<mask id="none" maskContentUnits="objectBoundingBox"><rect width="1" height="1" fill="white" /></mask>', '<linearGradient id="grad-symbol"><stop offset="0.7" stop-color="white" stop-opacity="1" /><stop offset=".95" stop-color="white" stop-opacity="0" /></linearGradient>', '<mask id="fade-symbol" maskContentUnits="userSpaceOnUse"><rect width="290px" height="200px" fill="url(#grad-symbol)" /></mask></defs>', '<g clip-path="url(#corners)">', '<rect fill="', params.color0, '" x="0px" y="0px" width="290px" height="500px" />', '<rect style="filter: url(#f1)" x="0px" y="0px" width="290px" height="500px" />', ' <g style="filter:url(#top-region-blur); transform:scale(1.5); transform-origin:center top;">', '<rect fill="none" x="0px" y="0px" width="290px" height="500px" />', '<ellipse cx="50%" cy="0px" rx="180px" ry="120px" fill="#000" opacity="0.85" /></g>', '<rect x="0" y="0" width="290" height="500" rx="42" ry="42" fill="rgba(0,0,0,0)" stroke="rgba(255,255,255,0.2)" /></g>' ) ); } /// @notice Generate the SVG for the moving border text displaying the quote and base currency addresses with their symbols /// @param quoteCurrency The quote currency /// @param baseCurrency The base currency /// @param quoteCurrencySymbol The quote currency symbol /// @param baseCurrencySymbol The base currency symbol /// @return svg The SVG for the border NFT's border text function generateSVGBorderText( string memory quoteCurrency, string memory baseCurrency, string memory quoteCurrencySymbol, string memory baseCurrencySymbol ) private pure returns (string memory svg) { svg = string( abi.encodePacked( '<text text-rendering="optimizeSpeed">', '<textPath startOffset="-100%" fill="white" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">', baseCurrency, unicode" • ", baseCurrencySymbol, ' <animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite" />', '</textPath> <textPath startOffset="0%" fill="white" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">', baseCurrency, unicode" • ", baseCurrencySymbol, ' <animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite" /> </textPath>', '<textPath startOffset="50%" fill="white" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">', quoteCurrency, unicode" • ", quoteCurrencySymbol, ' <animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s"', ' repeatCount="indefinite" /></textPath><textPath startOffset="-50%" fill="white" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">', quoteCurrency, unicode" • ", quoteCurrencySymbol, ' <animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite" /></textPath></text>' ) ); } /// @notice Generate the SVG for the card mantle displaying the quote and base currency symbols and fee tier /// @param quoteCurrencySymbol The quote currency symbol /// @param baseCurrencySymbol The base currency symbol /// @param feeTier The fee tier /// @return svg The SVG for the card mantle function generateSVGCardMantle( string memory quoteCurrencySymbol, string memory baseCurrencySymbol, string memory feeTier ) private pure returns (string memory svg) { svg = string( abi.encodePacked( '<g mask="url(#fade-symbol)"><rect fill="none" x="0px" y="0px" width="290px" height="200px" /> <text y="70px" x="32px" fill="white" font-family="\'Courier New\', monospace" font-weight="200" font-size="36px">', quoteCurrencySymbol, "/", baseCurrencySymbol, '</text><text y="115px" x="32px" fill="white" font-family="\'Courier New\', monospace" font-weight="200" font-size="36px">', feeTier, "</text></g>", '<rect x="16" y="16" width="258" height="468" rx="26" ry="26" fill="rgba(0,0,0,0)" stroke="rgba(255,255,255,0.2)" />' ) ); } /// @notice Generate the SVG for the curve that represents the position. Fade up (top is faded) if current price is above your position range, fade down (bottom is faded) if current price is below your position range /// Circles are generated at the ends of the curve if the position is in range, or at one end of the curve it is on if not in range /// @param tickLower The lower tick /// @param tickUpper The upper tick /// @param tickSpacing The tick spacing /// @param overRange Whether the current tick is in range, over range, or under range /// @return svg The SVG for the curve function generageSvgCurve(int24 tickLower, int24 tickUpper, int24 tickSpacing, int8 overRange) private pure returns (string memory svg) { string memory fade = overRange == 1 ? "#fade-up" : overRange == -1 ? "#fade-down" : "#none"; string memory curve = getCurve(tickLower, tickUpper, tickSpacing); svg = string( abi.encodePacked( '<g mask="url(', fade, ')"', ' style="transform:translate(72px,189px)">' '<rect x="-16px" y="-16px" width="180px" height="180px" fill="none" />' '<path d="', curve, '" stroke="rgba(0,0,0,0.3)" stroke-width="32px" fill="none" stroke-linecap="round" />', '</g><g mask="url(', fade, ')"', ' style="transform:translate(72px,189px)">', '<rect x="-16px" y="-16px" width="180px" height="180px" fill="none" />', '<path d="', curve, '" stroke="rgba(255,255,255,1)" fill="none" stroke-linecap="round" /></g>', generateSVGCurveCircle(overRange) ) ); } /// @notice Get the curve based on the tick range /// The smaller the tick range, the smaller/more linear the curve /// @param tickLower The lower tick /// @param tickUpper The upper tick /// @param tickSpacing The tick spacing /// @return curve The curve path function getCurve(int24 tickLower, int24 tickUpper, int24 tickSpacing) internal pure returns (string memory curve) { int24 tickRange = (tickUpper - tickLower) / tickSpacing; if (tickRange <= 4) { curve = curve1; } else if (tickRange <= 8) { curve = curve2; } else if (tickRange <= 16) { curve = curve3; } else if (tickRange <= 32) { curve = curve4; } else if (tickRange <= 64) { curve = curve5; } else if (tickRange <= 128) { curve = curve6; } else if (tickRange <= 256) { curve = curve7; } else { curve = curve8; } } /// @notice Generate the SVG for the circles on the curve /// @param overRange 0 if the current tick is in range, 1 if the current tick is over range, -1 if the current tick is under range /// @return svg The SVG for the circles function generateSVGCurveCircle(int8 overRange) internal pure returns (string memory svg) { string memory curvex1 = "73"; string memory curvey1 = "190"; string memory curvex2 = "217"; string memory curvey2 = "334"; /// If the position is over or under range, generate one circle at the end of the curve on the side of the range it is on with a larger circle around it if (overRange == 1 || overRange == -1) { svg = string( abi.encodePacked( '<circle cx="', overRange == -1 ? curvex1 : curvex2, 'px" cy="', overRange == -1 ? curvey1 : curvey2, 'px" r="4px" fill="white" /><circle cx="', overRange == -1 ? curvex1 : curvex2, 'px" cy="', overRange == -1 ? curvey1 : curvey2, 'px" r="24px" fill="none" stroke="white" />' ) ); } else { /// If the position is in range, generate two circles at the ends of the curve svg = string( abi.encodePacked( '<circle cx="', curvex1, 'px" cy="', curvey1, 'px" r="4px" fill="white" />', '<circle cx="', curvex2, 'px" cy="', curvey2, 'px" r="4px" fill="white" />' ) ); } } /// @notice Generate the SVG for the position data (token ID, hooks address, min tick, max tick) and the location curve (where your position falls on the curve) /// @param tokenId The token ID /// @param hook The hooks address /// @param tickLower The lower tick /// @param tickUpper The upper tick /// @return svg The SVG for the position data and location curve function generateSVGPositionDataAndLocationCurve( string memory tokenId, address hook, int24 tickLower, int24 tickUpper ) private pure returns (string memory svg) { string memory hookStr = (uint256(uint160(hook))).toHexString(20); string memory tickLowerStr = tickToString(tickLower); string memory tickUpperStr = tickToString(tickUpper); uint256 str1length = bytes(tokenId).length + 4; string memory hookSlice = hook == address(0) ? "No Hook" : string(abi.encodePacked(substring(hookStr, 0, 5), "...", substring(hookStr, 39, 42))); uint256 str2length = bytes(hookSlice).length + 5; uint256 str3length = bytes(tickLowerStr).length + 10; uint256 str4length = bytes(tickUpperStr).length + 10; (string memory xCoord, string memory yCoord) = rangeLocation(tickLower, tickUpper); svg = string( abi.encodePacked( ' <g style="transform:translate(29px, 354px)">', '<rect width="', uint256(7 * (str1length + 4)).toString(), 'px" height="26px" rx="8px" ry="8px" fill="rgba(0,0,0,0.6)" />', '<text x="12px" y="17px" font-family="\'Courier New\', monospace" font-size="11px" fill="white"><tspan fill="rgba(255,255,255,0.6)">ID: </tspan>', tokenId, "</text></g>", ' <g style="transform:translate(29px, 384px)">', '<rect width="', uint256(7 * (str2length + 4)).toString(), 'px" height="26px" rx="8px" ry="8px" fill="rgba(0,0,0,0.6)" />', '<text x="12px" y="17px" font-family="\'Courier New\', monospace" font-size="11px" fill="white"><tspan fill="rgba(255,255,255,0.6)">Hook: </tspan>', hookSlice, "</text></g>", ' <g style="transform:translate(29px, 414px)">', '<rect width="', uint256(7 * (str3length + 4)).toString(), 'px" height="26px" rx="8px" ry="8px" fill="rgba(0,0,0,0.6)" />', '<text x="12px" y="17px" font-family="\'Courier New\', monospace" font-size="11px" fill="white"><tspan fill="rgba(255,255,255,0.6)">Min Tick: </tspan>', tickLowerStr, "</text></g>", ' <g style="transform:translate(29px, 444px)">', '<rect width="', uint256(7 * (str4length + 4)).toString(), 'px" height="26px" rx="8px" ry="8px" fill="rgba(0,0,0,0.6)" />', '<text x="12px" y="17px" font-family="\'Courier New\', monospace" font-size="11px" fill="white"><tspan fill="rgba(255,255,255,0.6)">Max Tick: </tspan>', tickUpperStr, "</text></g>" '<g style="transform:translate(226px, 433px)">', '<rect width="36px" height="36px" rx="8px" ry="8px" fill="none" stroke="rgba(255,255,255,0.2)" />', '<path stroke-linecap="round" d="M8 9C8.00004 22.9494 16.2099 28 27 28" fill="none" stroke="white" />', '<circle style="transform:translate3d(', xCoord, "px, ", yCoord, 'px, 0px)" cx="0px" cy="0px" r="4px" fill="white"/></g>' ) ); } function substring(string memory str, uint256 startIndex, uint256 endIndex) internal pure returns (string memory) { bytes memory strBytes = bytes(str); bytes memory result = new bytes(endIndex - startIndex); for (uint256 i = startIndex; i < endIndex; i++) { result[i - startIndex] = strBytes[i]; } return string(result); } function tickToString(int24 tick) private pure returns (string memory) { string memory sign = ""; if (tick < 0) { tick = tick * -1; sign = "-"; } return string(abi.encodePacked(sign, uint256(uint24(tick)).toString())); } /// @notice Get the location of where your position falls on the curve /// @param tickLower The lower tick /// @param tickUpper The upper tick /// @return The x and y coordinates of the location of the liquidity function rangeLocation(int24 tickLower, int24 tickUpper) internal pure returns (string memory, string memory) { int24 midPoint = (tickLower + tickUpper) / 2; if (midPoint < -125_000) { return ("8", "7"); } else if (midPoint < -75_000) { return ("8", "10.5"); } else if (midPoint < -25_000) { return ("8", "14.25"); } else if (midPoint < -5_000) { return ("10", "18"); } else if (midPoint < 0) { return ("11", "21"); } else if (midPoint < 5_000) { return ("13", "23"); } else if (midPoint < 25_000) { return ("15", "25"); } else if (midPoint < 75_000) { return ("18", "26"); } else if (midPoint < 125_000) { return ("21", "27"); } else { return ("24", "27"); } } /// @notice Generates the SVG for a rare sparkle if the NFT is rare. Else, returns an empty string /// @param tokenId The token ID /// @param hooks The hooks address /// @return svg The SVG for the rare sparkle function generateSVGRareSparkle(uint256 tokenId, address hooks) private pure returns (string memory svg) { if (isRare(tokenId, hooks)) { svg = string( abi.encodePacked( '<g style="transform:translate(226px, 392px)"><rect width="36px" height="36px" rx="8px" ry="8px" fill="none" stroke="rgba(255,255,255,0.2)" />', '<g><path style="transform:translate(6px,6px)" d="M12 0L12.6522 9.56587L18 1.6077L13.7819 10.2181L22.3923 6L14.4341 ', "11.3478L24 12L14.4341 12.6522L22.3923 18L13.7819 13.7819L18 22.3923L12.6522 14.4341L12 24L11.3478 14.4341L6 22.39", '23L10.2181 13.7819L1.6077 18L9.56587 12.6522L0 12L9.56587 11.3478L1.6077 6L10.2181 10.2181L6 1.6077L11.3478 9.56587L12 0Z" fill="white" />', '<animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="10s" repeatCount="indefinite"/></g></g>' ) ); } else { svg = ""; } } /// @notice Determines if an NFT is rare based on the token ID and hooks address /// @param tokenId The token ID /// @param hooks The hooks address /// @return Whether the NFT is rare or not function isRare(uint256 tokenId, address hooks) internal pure returns (bool) { bytes32 h = keccak256(abi.encodePacked(tokenId, hooks)); return uint256(h) < type(uint256).max / (1 + BitMath.mostSignificantBit(tokenId) * 2); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {AddressStringUtil} from "./AddressStringUtil.sol"; /// @title SafeCurrencyMetadata /// @notice can produce symbols and decimals from inconsistent or absent ERC20 implementations /// @dev Reference: https://github.com/Uniswap/solidity-lib/blob/master/contracts/libraries/SafeERC20Namer.sol library SafeCurrencyMetadata { uint8 constant MAX_SYMBOL_LENGTH = 12; /// @notice attempts to extract the currency symbol. if it does not implement symbol, returns a symbol derived from the address /// @param currency The currency address /// @param nativeLabel The native label /// @return the currency symbol function currencySymbol(address currency, string memory nativeLabel) internal view returns (string memory) { if (currency == address(0)) { return nativeLabel; } string memory symbol = callAndParseStringReturn(currency, IERC20Metadata.symbol.selector); if (bytes(symbol).length == 0) { // fallback to 6 uppercase hex of address return addressToSymbol(currency); } if (bytes(symbol).length > MAX_SYMBOL_LENGTH) { return truncateSymbol(symbol); } return symbol; } /// @notice attempts to extract the token decimals, returns 0 if not implemented or not a uint8 /// @param currency The currency address /// @return the currency decimals function currencyDecimals(address currency) internal view returns (uint8) { if (currency == address(0)) { return 18; } (bool success, bytes memory data) = currency.staticcall(abi.encodeCall(IERC20Metadata.decimals, ())); if (!success) { return 0; } if (data.length == 32) { uint256 decimals = abi.decode(data, (uint256)); if (decimals <= type(uint8).max) { return uint8(decimals); } } return 0; } function bytes32ToString(bytes32 x) private pure returns (string memory) { bytes memory bytesString = new bytes(32); uint256 charCount = 0; for (uint256 j = 0; j < 32; j++) { bytes1 char = x[j]; if (char != 0) { bytesString[charCount] = char; charCount++; } } bytes memory bytesStringTrimmed = new bytes(charCount); for (uint256 j = 0; j < charCount; j++) { bytesStringTrimmed[j] = bytesString[j]; } return string(bytesStringTrimmed); } /// @notice produces a symbol from the address - the first 6 hex of the address string in upper case /// @param currencyAddress the address of the currency /// @return the symbol function addressToSymbol(address currencyAddress) private pure returns (string memory) { return AddressStringUtil.toAsciiString(currencyAddress, 6); } /// @notice calls an external view contract method that returns a symbol, and parses the output into a string /// @param currencyAddress the address of the currency /// @param selector the selector of the symbol method /// @return the symbol function callAndParseStringReturn(address currencyAddress, bytes4 selector) private view returns (string memory) { (bool success, bytes memory data) = currencyAddress.staticcall(abi.encodeWithSelector(selector)); // if not implemented, return empty string if (!success) { return ""; } // bytes32 data always has length 32 if (data.length == 32) { bytes32 decoded = abi.decode(data, (bytes32)); return bytes32ToString(decoded); } else if (data.length > 64) { return abi.decode(data, (string)); } return ""; } /// @notice truncates the symbol to the MAX_SYMBOL_LENGTH /// @dev assumes the string is already longer than MAX_SYMBOL_LENGTH (or the same) /// @param str the symbol /// @return the truncated symbol function truncateSymbol(string memory str) internal pure returns (string memory) { bytes memory strBytes = bytes(str); bytes memory truncatedBytes = new bytes(MAX_SYMBOL_LENGTH); for (uint256 i = 0; i < MAX_SYMBOL_LENGTH; i++) { truncatedBytes[i] = strBytes[i]; } return string(truncatedBytes); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {SafeCast} from "@uniswap/v4-core/src/libraries/SafeCast.sol"; /// @title Slippage Check Library /// @notice a library for checking if a delta exceeds a maximum ceiling or fails to meet a minimum floor library SlippageCheck { using SafeCast for int128; error MaximumAmountExceeded(uint128 maximumAmount, uint128 amountRequested); error MinimumAmountInsufficient(uint128 minimumAmount, uint128 amountReceived); /// @notice Revert if one or both deltas does not meet a minimum output /// @param delta The principal amount of tokens to be removed, does not include any fees accrued /// @param amount0Min The minimum amount of token0 to receive /// @param amount1Min The minimum amount of token1 to receive /// @dev This should be called when removing liquidity (burn or decrease) function validateMinOut(BalanceDelta delta, uint128 amount0Min, uint128 amount1Min) internal pure { // Called on burn or decrease, where we expect the returned delta to be positive. // However, on pools where hooks can return deltas on modify liquidity, it is possible for a returned delta to be negative. // Because we use SafeCast, this will revert in those cases when the delta is negative. // This means this contract will NOT support pools where the hook returns a negative delta on burn/decrease. if (delta.amount0().toUint128() < amount0Min) { revert MinimumAmountInsufficient(amount0Min, delta.amount0().toUint128()); } if (delta.amount1().toUint128() < amount1Min) { revert MinimumAmountInsufficient(amount1Min, delta.amount1().toUint128()); } } /// @notice Revert if one or both deltas exceeds a maximum input /// @param delta The principal amount of tokens to be added, does not include any fees accrued (which is possible on increase) /// @param amount0Max The maximum amount of token0 to spend /// @param amount1Max The maximum amount of token1 to spend /// @dev This should be called when adding liquidity (mint or increase) function validateMaxIn(BalanceDelta delta, uint128 amount0Max, uint128 amount1Max) internal pure { // Called on mint or increase, where we expect the returned delta to be negative. // However, on pools where hooks can return deltas on modify liquidity, it is possible for a returned delta to be positive (even after discounting fees accrued). // Thus, we only cast the delta if it is guaranteed to be negative. // And we do NOT revert in the positive delta case. Since a positive delta means the hook is crediting tokens to the user for minting/increasing liquidity, we do not check slippage. // This means this contract will NOT support _positive_ slippage checks (minAmountOut checks) on pools where the hook returns a positive delta on mint/increase. int256 amount0 = delta.amount0(); int256 amount1 = delta.amount1(); if (amount0 < 0 && amount0Max < uint128(uint256(-amount0))) { revert MaximumAmountExceeded(amount0Max, uint128(uint256(-amount0))); } if (amount1 < 0 && amount1Max < uint128(uint256(-amount1))) { revert MaximumAmountExceeded(amount1Max, uint128(uint256(-amount1))); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title VanityAddressLib /// @notice A library to score addresses based on their vanity library VanityAddressLib { /// @notice Compares two addresses and returns true if the first address has a better vanity score /// @param first The first address to compare /// @param second The second address to compare /// @return better True if the first address has a better vanity score function betterThan(address first, address second) internal pure returns (bool better) { return score(first) > score(second); } /// @notice Scores an address based on its vanity /// @dev Scoring rules: /// Requirement: The first nonzero nibble must be 4 /// 10 points for every leading 0 nibble /// 40 points if the first 4 is followed by 3 more 4s /// 20 points if the first nibble after the 4 4s is NOT a 4 /// 20 points if the last 4 nibbles are 4s /// 1 point for every 4 /// @param addr The address to score /// @return calculatedScore The vanity score of the address function score(address addr) internal pure returns (uint256 calculatedScore) { // convert the address to bytes for easier parsing bytes20 addrBytes = bytes20(addr); unchecked { // 10 points per leading zero nibble uint256 leadingZeroCount = getLeadingNibbleCount(addrBytes, 0, 0); calculatedScore += (leadingZeroCount * 10); // special handling for 4s immediately after leading 0s uint256 leadingFourCount = getLeadingNibbleCount(addrBytes, leadingZeroCount, 4); // If the first nonzero nibble is not 4, return 0 if (leadingFourCount == 0) { return 0; } else if (leadingFourCount == 4) { // 60 points if exactly 4 4s calculatedScore += 60; } else if (leadingFourCount > 4) { // 40 points if more than 4 4s calculatedScore += 40; } // handling for remaining nibbles for (uint256 i = 0; i < addrBytes.length * 2; i++) { uint8 currentNibble = getNibble(addrBytes, i); // 1 extra point for any 4 nibbles if (currentNibble == 4) { calculatedScore += 1; } } // If the last 4 nibbles are 4s, add 20 points if (addrBytes[18] == 0x44 && addrBytes[19] == 0x44) { calculatedScore += 20; } } } /// @notice Returns the number of leading nibbles in an address that match a given value /// @param addrBytes The address to count the leading zero nibbles in function getLeadingNibbleCount(bytes20 addrBytes, uint256 startIndex, uint8 comparison) internal pure returns (uint256 count) { if (startIndex >= addrBytes.length * 2) { return count; } for (uint256 i = startIndex; i < addrBytes.length * 2; i++) { uint8 currentNibble = getNibble(addrBytes, i); if (currentNibble != comparison) { return count; } count += 1; } } /// @notice Returns the nibble at a given index in an address /// @param input The address to get the nibble from /// @param nibbleIndex The index of the nibble to get function getNibble(bytes20 input, uint256 nibbleIndex) internal pure returns (uint8 currentNibble) { uint8 currByte = uint8(input[nibbleIndex / 2]); if (nibbleIndex % 2 == 0) { // Get the higher nibble of the byte currentNibble = currByte >> 4; } else { // Get the lower nibble of the byte currentNibble = currByte & 0x0F; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol"; import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol"; import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol"; import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol"; import {BeforeSwapDelta} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol"; import {ImmutableState} from "../base/ImmutableState.sol"; /// @title Base Hook /// @notice abstract contract for hook implementations abstract contract BaseHook is IHooks, ImmutableState { error HookNotImplemented(); constructor(IPoolManager _manager) ImmutableState(_manager) { validateHookAddress(this); } /// @notice Returns a struct of permissions to signal which hook functions are to be implemented /// @dev Used at deployment to validate the address correctly represents the expected permissions function getHookPermissions() public pure virtual returns (Hooks.Permissions memory); /// @notice Validates the deployed hook address agrees with the expected permissions of the hook /// @dev this function is virtual so that we can override it during testing, /// which allows us to deploy an implementation to any address /// and then etch the bytecode into the correct address function validateHookAddress(BaseHook _this) internal pure virtual { Hooks.validateHookPermissions(_this, getHookPermissions()); } /// @inheritdoc IHooks function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96) external onlyPoolManager returns (bytes4) { return _beforeInitialize(sender, key, sqrtPriceX96); } function _beforeInitialize(address, PoolKey calldata, uint160) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, int24 tick) external onlyPoolManager returns (bytes4) { return _afterInitialize(sender, key, sqrtPriceX96, tick); } function _afterInitialize(address, PoolKey calldata, uint160, int24) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function beforeAddLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, bytes calldata hookData ) external onlyPoolManager returns (bytes4) { return _beforeAddLiquidity(sender, key, params, hookData); } function _beforeAddLiquidity(address, PoolKey calldata, IPoolManager.ModifyLiquidityParams calldata, bytes calldata) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function beforeRemoveLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, bytes calldata hookData ) external onlyPoolManager returns (bytes4) { return _beforeRemoveLiquidity(sender, key, params, hookData); } function _beforeRemoveLiquidity( address, PoolKey calldata, IPoolManager.ModifyLiquidityParams calldata, bytes calldata ) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterAddLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external onlyPoolManager returns (bytes4, BalanceDelta) { return _afterAddLiquidity(sender, key, params, delta, feesAccrued, hookData); } function _afterAddLiquidity( address, PoolKey calldata, IPoolManager.ModifyLiquidityParams calldata, BalanceDelta, BalanceDelta, bytes calldata ) internal virtual returns (bytes4, BalanceDelta) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterRemoveLiquidity( address sender, PoolKey calldata key, IPoolManager.ModifyLiquidityParams calldata params, BalanceDelta delta, BalanceDelta feesAccrued, bytes calldata hookData ) external onlyPoolManager returns (bytes4, BalanceDelta) { return _afterRemoveLiquidity(sender, key, params, delta, feesAccrued, hookData); } function _afterRemoveLiquidity( address, PoolKey calldata, IPoolManager.ModifyLiquidityParams calldata, BalanceDelta, BalanceDelta, bytes calldata ) internal virtual returns (bytes4, BalanceDelta) { revert HookNotImplemented(); } /// @inheritdoc IHooks function beforeSwap( address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, bytes calldata hookData ) external onlyPoolManager returns (bytes4, BeforeSwapDelta, uint24) { return _beforeSwap(sender, key, params, hookData); } function _beforeSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, bytes calldata) internal virtual returns (bytes4, BeforeSwapDelta, uint24) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterSwap( address sender, PoolKey calldata key, IPoolManager.SwapParams calldata params, BalanceDelta delta, bytes calldata hookData ) external onlyPoolManager returns (bytes4, int128) { return _afterSwap(sender, key, params, delta, hookData); } function _afterSwap(address, PoolKey calldata, IPoolManager.SwapParams calldata, BalanceDelta, bytes calldata) internal virtual returns (bytes4, int128) { revert HookNotImplemented(); } /// @inheritdoc IHooks function beforeDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external onlyPoolManager returns (bytes4) { return _beforeDonate(sender, key, amount0, amount1, hookData); } function _beforeDonate(address, PoolKey calldata, uint256, uint256, bytes calldata) internal virtual returns (bytes4) { revert HookNotImplemented(); } /// @inheritdoc IHooks function afterDonate( address sender, PoolKey calldata key, uint256 amount0, uint256 amount1, bytes calldata hookData ) external onlyPoolManager returns (bytes4) { return _afterDonate(sender, key, amount0, amount1, hookData); } function _afterDonate(address, PoolKey calldata, uint256, uint256, bytes calldata) internal virtual returns (bytes4) { revert HookNotImplemented(); } }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "src/pkgs/v3-periphery:base64-sol/=lib/base64/", "src/pkgs/v3-periphery:@openzeppelin/contracts/=lib/oz-v3.4-solc-0.7/contracts/", "lib/v4-core:solmate/src/=lib/v4-core/lib/solmate/src/", "src/pkgs/v4-core:solmate/src/=src/pkgs/v4-core/lib/solmate/src/", "src/pkgs/v4-periphery:solmate/src/=src/pkgs/v4-periphery/lib/v4-core/lib/solmate/src/", "src/pkgs/v4-periphery:@uniswap/v4-core/=src/pkgs/v4-periphery/lib/v4-core/", "src/pkgs/v4-periphery/src:openzeppelin-contracts/=src/pkgs/v4-periphery/lib/v4-core/lib/openzeppelin-contracts/", "src/pkgs/v4-periphery/src:@openzeppelin/=src/pkgs/v4-periphery/lib/v4-core/lib/openzeppelin-contracts/", "src/pkgs/permit2:solmate/=src/pkgs/permit2/lib/solmate/", "src/pkgs/universal-router:@uniswap/v3-periphery/=src/pkgs/universal-router/lib/v3-periphery/", "src/pkgs/universal-router:@uniswap/v4-periphery/=src/pkgs/universal-router/lib/v4-periphery/", "src/pkgs/universal-router:solmate/=src/pkgs/universal-router/lib/solmate/", "src/pkgs/universal-router/lib/v4-periphery:@openzeppelin/=src/pkgs/universal-router/lib/v4-periphery/lib/v4-core/lib/openzeppelin-contracts/", "src/pkgs/universal-router/lib/v3-periphery:@openzeppelin/=lib/oz-v4.7.0/", "src/pkgs/uniswapx:solmate/=src/pkgs/uniswapx/lib/solmate/", "src/pkgs/uniswapx:openzeppelin-contracts/=src/pkgs/uniswapx/lib/openzeppelin-contracts/contracts/", "src/pkgs/util-contracts:v2-core/=src/pkgs/v2-core/contracts/", "src/pkgs/util-contracts:solmate/=src/pkgs/util-contracts/lib/solmate/src/", "src/pkgs/view-quoter-v3:v3-core/=src/pkgs/v3-core/", "src/pkgs/view-quoter-v3:v3-periphery/=src/pkgs/v3-periphery/", "src/pkgs/swap-router-contracts:@openzeppelin/contracts/=lib/oz-v3.4-solc-0.7/contracts/", "src/pkgs/swap-router-contracts:@uniswap/v3-periphery/=src/pkgs/v3-periphery/", "permit2/=src/pkgs/permit2/", "@uniswap/lib/=lib/solidity-lib/", "@uniswap/v2-core/=src/pkgs/v2-core/", "@uniswap/v3-core/=src/pkgs/v3-core/", "@uniswap/v4-core/=src/pkgs/v4-core/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"ERC1967InvalidAdmin","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"ProxyDeniedAdminAccess","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"}]
Contract Creation Code
60a0604052604051610d80380380610d808339810160408190526100229161036a565b828161002e828261008c565b50508160405161003d9061032e565b6001600160a01b039091168152602001604051809103905ff080158015610066573d5f803e3d5ffd5b506001600160a01b031660805261008461007f60805190565b6100ea565b505050610451565b61009582610157565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156100de576100d982826101d5565b505050565b6100e6610248565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6101295f80516020610d60833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a161015481610269565b50565b806001600160a01b03163b5f0361019157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b0316846040516101f1919061043b565b5f60405180830381855af49150503d805f8114610229576040519150601f19603f3d011682016040523d82523d5f602084013e61022e565b606091505b50909250905061023f8583836102a6565b95945050505050565b34156102675760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b03811661029257604051633173bdd160e11b81525f6004820152602401610188565b805f80516020610d608339815191526101b4565b6060826102bb576102b682610305565b6102fe565b81511580156102d257506001600160a01b0384163b155b156102fb57604051639996b31560e01b81526001600160a01b0385166004820152602401610188565b50805b9392505050565b8051156103155780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6104c68061089a83390190565b80516001600160a01b0381168114610351575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f805f6060848603121561037c575f80fd5b6103858461033b565b92506103936020850161033b565b60408501519092506001600160401b038111156103ae575f80fd5b8401601f810186136103be575f80fd5b80516001600160401b038111156103d7576103d7610356565b604051601f8201601f19908116603f011681016001600160401b038111828210171561040557610405610356565b60405281815282820160200188101561041c575f80fd5b8160208401602083015e5f602083830101528093505050509250925092565b5f82518060208501845e5f920191825250919050565b6080516104326104685f395f601001526104325ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f806100913660048184610303565b81019061009e919061033e565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61025c565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b031684604051610206919061040f565b5f60405180830381855af49150503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b509150915061025385838361027b565b95945050505050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b6060826102905761028b826102da565b6102d3565b81511580156102a757506001600160a01b0384163b155b156102d057604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b50805b9392505050565b8051156102ea5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8085851115610311575f80fd5b8386111561031d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561034f575f80fd5b82356001600160a01b0381168114610365575f80fd5b9150602083013567ffffffffffffffff811115610380575f80fd5b8301601f81018513610390575f80fd5b803567ffffffffffffffff8111156103aa576103aa61032a565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103d9576103d961032a565b6040528181528282016020018710156103f0575f80fd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f92019182525091905056fea164736f6c634300081a000a608060405234801561000f575f80fd5b506040516104c63803806104c683398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b6103d1806100f55f395ff3fe608060405260043610610049575f3560e01c8063715018a61461004d5780638da5cb5b146100635780639623609d1461008e578063ad3cb1cc146100a1578063f2fde38b146100de575b5f80fd5b348015610058575f80fd5b506100616100fd565b005b34801561006e575f80fd5b505f546040516001600160a01b0390911681526020015b60405180910390f35b61006161009c366004610260565b610110565b3480156100ac575f80fd5b506100d1604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516100859190610365565b3480156100e9575f80fd5b506100616100f836600461037e565b61017b565b6101056101bd565b61010e5f6101e9565b565b6101186101bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906101489086908690600401610399565b5f604051808303818588803b15801561015f575f80fd5b505af1158015610171573d5f803e3d5ffd5b5050505050505050565b6101836101bd565b6001600160a01b0381166101b157604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6101ba816101e9565b50565b5f546001600160a01b0316331461010e5760405163118cdaa760e01b81523360048201526024016101a8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101ba575f80fd5b634e487b7160e01b5f52604160045260245ffd5b5f805f60608486031215610272575f80fd5b833561027d81610238565b9250602084013561028d81610238565b9150604084013567ffffffffffffffff8111156102a8575f80fd5b8401601f810186136102b8575f80fd5b803567ffffffffffffffff8111156102d2576102d261024c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103015761030161024c565b604052818152828201602001881015610318575f80fd5b816020840160208301375f602083830101528093505050509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6103776020830184610337565b9392505050565b5f6020828403121561038e575f80fd5b813561037781610238565b6001600160a01b03831681526040602082018190525f906103bc90830184610337565b94935050505056fea164736f6c634300081a000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61030000000000000000000000008be6f6785b71c16ca238abbcdd3f33271969c3050000000000000000000000002bad8182c09f50c8318d769245bea52c32be46cd00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405261000c61000e565b005b7f000000000000000000000000a7f9bd1b27ad7db53e3b9db0b36b395a74b1df9e6001600160a01b0316330361007a575f356001600160e01b03191663278f794360e11b14610070576040516334ad5dbb60e21b815260040160405180910390fd5b610078610082565b565b6100786100b0565b5f806100913660048184610303565b81019061009e919061033e565b915091506100ac82826100c0565b5050565b6100786100bb61011a565b610151565b6100c98261016f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101125761010d82826101ea565b505050565b6100ac61025c565b5f61014c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e80801561016b573d5ff35b3d5ffd5b806001600160a01b03163b5f036101a957604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b031684604051610206919061040f565b5f60405180830381855af49150503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b509150915061025385838361027b565b95945050505050565b34156100785760405163b398979f60e01b815260040160405180910390fd5b6060826102905761028b826102da565b6102d3565b81511580156102a757506001600160a01b0384163b155b156102d057604051639996b31560e01b81526001600160a01b03851660048201526024016101a0565b50805b9392505050565b8051156102ea5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8085851115610311575f80fd5b8386111561031d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561034f575f80fd5b82356001600160a01b0381168114610365575f80fd5b9150602083013567ffffffffffffffff811115610380575f80fd5b8301601f81018513610390575f80fd5b803567ffffffffffffffff8111156103aa576103aa61032a565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103d9576103d961032a565b6040528181528282016020018710156103f0575f80fd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f92019182525091905056fea164736f6c634300081a000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000008be6f6785b71c16ca238abbcdd3f33271969c3050000000000000000000000002bad8182c09f50c8318d769245bea52c32be46cd00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _logic (address): 0x8Be6F6785B71c16CA238ABbCdD3F33271969C305
Arg [1] : initialOwner (address): 0x2BAD8182C09F50c8318d769245beA52C32Be46CD
Arg [2] : _data (bytes): 0x
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000008be6f6785b71c16ca238abbcdd3f33271969c305
Arg [1] : 0000000000000000000000002bad8182c09f50c8318d769245bea52c32be46cd
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.