Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
4976860 | 96 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
ManagerWithMerkleVerification
Compiler Version
v0.8.21+commit.d9974bed
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol"; import {BoringVault} from "../../../src/base/BoringVault.sol"; import {MerkleProofLib} from "@solmate/utils/MerkleProofLib.sol"; import {ERC20} from "@solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "@solmate/utils/SafeTransferLib.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {BalancerVault} from "../../../src/interfaces/BalancerVault.sol"; import {Auth, Authority} from "@solmate/auth/Auth.sol"; import {IPausable} from "../../../src/interfaces/IPausable.sol"; import {DroneLib} from "../../../src/base/Drones/DroneLib.sol"; contract ManagerWithMerkleVerification is Auth, IPausable { using FixedPointMathLib for uint256; using SafeTransferLib for ERC20; using Address for address; // ========================================= STATE ========================================= /** * @notice A merkle tree root that restricts what data can be passed to the BoringVault. * @dev Maps a strategist address to their specific merkle root. * @dev Each leaf is composed of the keccak256 hash of abi.encodePacked {decodersAndSanitizer, target, valueIsNonZero, selector, argumentAddress_0, ...., argumentAddress_N} * Where: * - decodersAndSanitizer is the addres to call to extract packed address arguments from the calldata * - target is the address to make the call to * - valueIsNonZero is a bool indicating whether or not the value is non-zero * - selector is the function selector on target * - argumentAddress is each allowed address argument in that call */ mapping(address => bytes32) public manageRoot; /** * @notice Bool indicating whether or not this contract is actively performing a flash loan. * @dev Used to block flash loans that are initiated outside a manage call. */ bool internal performingFlashLoan; /** * @notice keccak256 hash of flash loan data. */ bytes32 internal flashLoanIntentHash = bytes32(0); /** * @notice Used to pause calls to `manageVaultWithMerkleVerification`. */ bool public isPaused; //============================== ERRORS =============================== error ManagerWithMerkleVerification__InvalidManageProofLength(); error ManagerWithMerkleVerification__InvalidTargetDataLength(); error ManagerWithMerkleVerification__InvalidValuesLength(); error ManagerWithMerkleVerification__InvalidDecodersAndSanitizersLength(); error ManagerWithMerkleVerification__FlashLoanNotExecuted(); error ManagerWithMerkleVerification__FlashLoanNotInProgress(); error ManagerWithMerkleVerification__BadFlashLoanIntentHash(); error ManagerWithMerkleVerification__FailedToVerifyManageProof(address target, bytes targetData, uint256 value); error ManagerWithMerkleVerification__Paused(); error ManagerWithMerkleVerification__OnlyCallableByBoringVault(); error ManagerWithMerkleVerification__OnlyCallableByBalancerVault(); error ManagerWithMerkleVerification__TotalSupplyMustRemainConstantDuringPlatform(); //============================== EVENTS =============================== event ManageRootUpdated(address indexed strategist, bytes32 oldRoot, bytes32 newRoot); event BoringVaultManaged(uint256 callsMade); event Paused(); event Unpaused(); //============================== IMMUTABLES =============================== /** * @notice The BoringVault this contract can manage. */ BoringVault public immutable vault; /** * @notice The balancer vault this contract can use for flash loans. */ BalancerVault public immutable balancerVault; constructor(address _owner, address _vault, address _balancerVault) Auth(_owner, Authority(address(0))) { vault = BoringVault(payable(_vault)); balancerVault = BalancerVault(_balancerVault); } // ========================================= ADMIN FUNCTIONS ========================================= /** * @notice Sets the manageRoot. * @dev Callable by OWNER_ROLE. */ function setManageRoot(address strategist, bytes32 _manageRoot) external requiresAuth { bytes32 oldRoot = manageRoot[strategist]; manageRoot[strategist] = _manageRoot; emit ManageRootUpdated(strategist, oldRoot, _manageRoot); } /** * @notice Pause this contract, which prevents future calls to `manageVaultWithMerkleVerification`. * @dev Callable by MULTISIG_ROLE. */ function pause() external requiresAuth { isPaused = true; emit Paused(); } /** * @notice Unpause this contract, which allows future calls to `manageVaultWithMerkleVerification`. * @dev Callable by MULTISIG_ROLE. */ function unpause() external requiresAuth { isPaused = false; emit Unpaused(); } // ========================================= STRATEGIST FUNCTIONS ========================================= /** * @notice Allows strategist to manage the BoringVault. * @dev The strategist must provide a merkle proof for every call that verifiees they are allowed to make that call. * @dev Callable by MANAGER_INTERNAL_ROLE. * @dev Callable by STRATEGIST_ROLE. * @dev Callable by MICRO_MANAGER_ROLE. */ function manageVaultWithMerkleVerification( bytes32[][] calldata manageProofs, address[] calldata decodersAndSanitizers, address[] calldata targets, bytes[] calldata targetData, uint256[] calldata values ) external requiresAuth { if (isPaused) revert ManagerWithMerkleVerification__Paused(); uint256 targetsLength = targets.length; if (targetsLength != manageProofs.length) revert ManagerWithMerkleVerification__InvalidManageProofLength(); if (targetsLength != targetData.length) revert ManagerWithMerkleVerification__InvalidTargetDataLength(); if (targetsLength != values.length) revert ManagerWithMerkleVerification__InvalidValuesLength(); if (targetsLength != decodersAndSanitizers.length) { revert ManagerWithMerkleVerification__InvalidDecodersAndSanitizersLength(); } bytes32 strategistManageRoot = manageRoot[msg.sender]; uint256 totalSupply = vault.totalSupply(); for (uint256 i; i < targetsLength; ++i) { _verifyCallData( strategistManageRoot, manageProofs[i], decodersAndSanitizers[i], targets[i], values[i], targetData[i] ); vault.manage(targets[i], targetData[i], values[i]); } if (totalSupply != vault.totalSupply()) { revert ManagerWithMerkleVerification__TotalSupplyMustRemainConstantDuringPlatform(); } emit BoringVaultManaged(targetsLength); } // ========================================= FLASH LOAN FUNCTIONS ========================================= /** * @notice In order to perform a flash loan, * 1) Merkle root must contain the leaf(address(this), this.flashLoan.selector, ARGUMENT_ADDRESSES ...) * 2) Strategist must initiate the flash loan using `manageVaultWithMerkleVerification` * 3) balancerVault MUST callback to this contract with the same userData */ function flashLoan( address recipient, address[] calldata tokens, uint256[] calldata amounts, bytes calldata userData ) external { if (msg.sender != address(vault)) revert ManagerWithMerkleVerification__OnlyCallableByBoringVault(); flashLoanIntentHash = keccak256(userData); performingFlashLoan = true; balancerVault.flashLoan(recipient, tokens, amounts, userData); performingFlashLoan = false; if (flashLoanIntentHash != bytes32(0)) revert ManagerWithMerkleVerification__FlashLoanNotExecuted(); } /** * @notice Add support for balancer flash loans. * @dev userData can optionally have salt encoded at the end of it, in order to change the intentHash, * if a flash loan is exact userData is being repeated, and their is fear of 3rd parties * front-running the rebalance. */ function receiveFlashLoan( address[] calldata tokens, uint256[] calldata amounts, uint256[] calldata feeAmounts, bytes calldata userData ) external { if (msg.sender != address(balancerVault)) revert ManagerWithMerkleVerification__OnlyCallableByBalancerVault(); if (!performingFlashLoan) revert ManagerWithMerkleVerification__FlashLoanNotInProgress(); // Validate userData using intentHash. bytes32 intentHash = keccak256(userData); if (intentHash != flashLoanIntentHash) revert ManagerWithMerkleVerification__BadFlashLoanIntentHash(); // reset intent hash to prevent replays. flashLoanIntentHash = bytes32(0); // Transfer tokens to vault. for (uint256 i = 0; i < amounts.length; ++i) { ERC20(tokens[i]).safeTransfer(address(vault), amounts[i]); } { ( bytes32[][] memory manageProofs, address[] memory decodersAndSanitizers, address[] memory targets, bytes[] memory data, uint256[] memory values ) = abi.decode(userData, (bytes32[][], address[], address[], bytes[], uint256[])); ManagerWithMerkleVerification(address(this)).manageVaultWithMerkleVerification( manageProofs, decodersAndSanitizers, targets, data, values ); } // Transfer tokens back to balancer. // Have vault transfer amount + fees back to balancer bytes[] memory transferData = new bytes[](amounts.length); for (uint256 i; i < amounts.length; ++i) { transferData[i] = abi.encodeWithSelector(ERC20.transfer.selector, address(balancerVault), (amounts[i] + feeAmounts[i])); } // Values is always zero, just pass in an array of zeroes. vault.manage(tokens, transferData, new uint256[](amounts.length)); } // ========================================= INTERNAL HELPER FUNCTIONS ========================================= /** * @notice Helper function to decode, sanitize, and verify call data. */ function _verifyCallData( bytes32 currentManageRoot, bytes32[] calldata manageProof, address decoderAndSanitizer, address target, uint256 value, bytes calldata targetData ) internal view { // Use address decoder to get addresses in call data. bytes memory packedArgumentAddresses = abi.decode(decoderAndSanitizer.functionStaticCall(targetData), (bytes)); address droneTarget = DroneLib.extractTargetFromInput(targetData); if (droneTarget != address(0)) { packedArgumentAddresses = abi.encodePacked(packedArgumentAddresses, droneTarget); } if ( !_verifyManageProof( currentManageRoot, manageProof, target, decoderAndSanitizer, value, bytes4(targetData), packedArgumentAddresses ) ) { revert ManagerWithMerkleVerification__FailedToVerifyManageProof(target, targetData, value); } } /** * @notice Helper function to verify a manageProof is valid. */ function _verifyManageProof( bytes32 root, bytes32[] calldata proof, address target, address decoderAndSanitizer, uint256 value, bytes4 selector, bytes memory packedArgumentAddresses ) internal pure returns (bool) { bool valueNonZero = value > 0; bytes32 leaf = keccak256(abi.encodePacked(decoderAndSanitizer, target, valueNonZero, selector, packedArgumentAddresses)); return MerkleProofLib.verify(proof, root, leaf); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Interface that must be implemented by smart contracts in order to receive * ERC-1155 token transfers. */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC-1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC-1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.20; import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol"; import {IERC1155Receiver} from "../IERC1155Receiver.sol"; /** * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. */ abstract contract ERC1155Holder is ERC165, IERC1155Receiver { /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC-721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC-721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be * reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol) pragma solidity ^0.8.20; import {IERC721Receiver} from "../IERC721Receiver.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. * * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or * {IERC721-setApprovalForAll}. */ abstract contract ERC721Holder is IERC721Receiver { /** * @dev See {IERC721Receiver-onERC721Received}. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) { return this.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @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 Errors.InsufficientBalance(address(this).balance, amount); } (bool success, bytes memory returndata) = recipient.call{value: amount}(""); if (!success) { _revert(returndata); } } /** * @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 * {Errors.FailedCall} 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 Errors.InsufficientBalance(address(this).balance, value); } (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 {Errors.FailedCall}) 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 {Errors.FailedCall} 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 {Errors.FailedCall}. */ 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 assembly ("memory-safe") { revert(add(returndata, 0x20), mload(returndata)) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * 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[ERC 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: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol) /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) abstract contract Auth { event OwnershipTransferred(address indexed user, address indexed newOwner); event AuthorityUpdated(address indexed user, Authority indexed newAuthority); address public owner; Authority public authority; constructor(address _owner, Authority _authority) { owner = _owner; authority = _authority; emit OwnershipTransferred(msg.sender, _owner); emit AuthorityUpdated(msg.sender, _authority); } modifier requiresAuth() virtual { require(isAuthorized(msg.sender, msg.sig), "UNAUTHORIZED"); _; } function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) { Authority auth = authority; // Memoizing authority saves us a warm SLOAD, around 100 gas. // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be // aware that this makes protected functions uncallable even to the owner if the authority is out of order. return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) || user == owner; } function setAuthority(Authority newAuthority) public virtual { // We check if the caller is the owner first because we want to ensure they can // always swap out the authority even if it's reverting or using up a lot of gas. require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig)); authority = newAuthority; emit AuthorityUpdated(msg.sender, newAuthority); } function transferOwnership(address newOwner) public virtual requiresAuth { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } } /// @notice A generic interface for a contract which provides authorization data to an Auth instance. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol) /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) interface Authority { function canCall( address user, address target, bytes4 functionSig ) external view returns (bool); }
// 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; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant MAX_UINT256 = 2**256 - 1; uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // Divide x * y by the denominator. z := div(mul(x, y), denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // If x * y modulo the denominator is strictly greater than 0, // 1 is added to round up the division of x * y by the denominator. z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let y := x // We start y at x, which will help us make our initial estimate. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // We check y >= 2^(k + 8) but shift right by k bits // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } // Goal was to get z*z*y within a small factor of x. More iterations could // get y in a tighter range. Currently, we will have y in [256, 256*2^16). // We ensured y >= 256 so that the relative difference between y and y+1 is small. // That's not possible if x < 256 but we can just verify those cases exhaustively. // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Mod x by y. Note this will return // 0 instead of reverting if y is zero. z := mod(x, y) } } function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Divide x by y. Note this will return // 0 instead of reverting if y is zero. r := div(x, y) } } function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Add 1 to x * y if x % y > 0. Note this will // return 0 instead of reverting if y is zero. z := add(gt(mod(x, y), 0), div(x, y)) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Gas optimized merkle proof verification library. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/MerkleProofLib.sol) library MerkleProofLib { function verify( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if proof.length { // Left shifting by 5 is like multiplying by 32. let end := add(proof.offset, shl(5, proof.length)) // Initialize offset to the offset of the proof in calldata. let offset := proof.offset // Iterate over proof elements to compute root hash. // prettier-ignore for {} 1 {} { // Slot where the leaf should be put in scratch space. If // leaf > calldataload(offset): slot 32, otherwise: slot 0. let leafSlot := shl(5, gt(leaf, calldataload(offset))) // Store elements to hash contiguously in scratch space. // The xor puts calldataload(offset) in whichever slot leaf // is not occupying, so 0 if leafSlot is 32, and 32 otherwise. mstore(leafSlot, leaf) mstore(xor(leafSlot, 32), calldataload(offset)) // Reuse leaf to store the hash to reduce stack operations. leaf := keccak256(0, 64) // Hash both slots of scratch space. offset := add(offset, 32) // Shift 1 word per cycle. // prettier-ignore if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) // The proof is valid if the roots match. } } }
// 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. 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. // 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. success := call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) // 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 and token has code. if and(iszero(and(eq(mload(0), 1), gt(returndatasize(), 31))), success) { success := iszero(or(iszero(extcodesize(token)), returndatasize())) } } 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. // 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. success := call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) // 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 and token has code. if and(iszero(and(eq(mload(0), 1), gt(returndatasize(), 31))), success) { success := iszero(or(iszero(extcodesize(token)), returndatasize())) } } 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. // 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. success := call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) // 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 and token has code. if and(iszero(and(eq(mload(0), 1), gt(returndatasize(), 31))), success) { success := iszero(or(iszero(extcodesize(token)), returndatasize())) } } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol"; import {SafeTransferLib} from "@solmate/utils/SafeTransferLib.sol"; import {ERC20} from "@solmate/tokens/ERC20.sol"; import {BeforeTransferHook} from "../../src/interfaces/BeforeTransferHook.sol"; import {Auth, Authority} from "@solmate/auth/Auth.sol"; contract BoringVault is ERC20, Auth, ERC721Holder, ERC1155Holder { using Address for address; using SafeTransferLib for ERC20; using FixedPointMathLib for uint256; // ========================================= STATE ========================================= /** * @notice Contract responsbile for implementing `beforeTransfer`. */ BeforeTransferHook public hook; //============================== EVENTS =============================== event Enter(address indexed from, address indexed asset, uint256 amount, address indexed to, uint256 shares); event Exit(address indexed to, address indexed asset, uint256 amount, address indexed from, uint256 shares); //============================== CONSTRUCTOR =============================== constructor(address _owner, string memory _name, string memory _symbol, uint8 _decimals) ERC20(_name, _symbol, _decimals) Auth(_owner, Authority(address(0))) {} //============================== MANAGE =============================== /** * @notice Allows manager to make an arbitrary function call from this contract. * @dev Callable by MANAGER_ROLE. */ function manage(address target, bytes calldata data, uint256 value) external requiresAuth returns (bytes memory result) { result = target.functionCallWithValue(data, value); } /** * @notice Allows manager to make arbitrary function calls from this contract. * @dev Callable by MANAGER_ROLE. */ function manage(address[] calldata targets, bytes[] calldata data, uint256[] calldata values) external requiresAuth returns (bytes[] memory results) { uint256 targetsLength = targets.length; results = new bytes[](targetsLength); for (uint256 i; i < targetsLength; ++i) { results[i] = targets[i].functionCallWithValue(data[i], values[i]); } } //============================== ENTER =============================== /** * @notice Allows minter to mint shares, in exchange for assets. * @dev If assetAmount is zero, no assets are transferred in. * @dev Callable by MINTER_ROLE. */ function enter(address from, ERC20 asset, uint256 assetAmount, address to, uint256 shareAmount) external requiresAuth { // Transfer assets in if (assetAmount > 0) asset.safeTransferFrom(from, address(this), assetAmount); // Mint shares. _mint(to, shareAmount); emit Enter(from, address(asset), assetAmount, to, shareAmount); } //============================== EXIT =============================== /** * @notice Allows burner to burn shares, in exchange for assets. * @dev If assetAmount is zero, no assets are transferred out. * @dev Callable by BURNER_ROLE. */ function exit(address to, ERC20 asset, uint256 assetAmount, address from, uint256 shareAmount) external requiresAuth { // Burn shares. _burn(from, shareAmount); // Transfer assets out. if (assetAmount > 0) asset.safeTransfer(to, assetAmount); emit Exit(to, address(asset), assetAmount, from, shareAmount); } //============================== BEFORE TRANSFER HOOK =============================== /** * @notice Sets the share locker. * @notice If set to zero address, the share locker logic is disabled. * @dev Callable by OWNER_ROLE. */ function setBeforeTransferHook(address _hook) external requiresAuth { hook = BeforeTransferHook(_hook); } /** * @notice Call `beforeTransferHook` passing in `from` `to`, and `msg.sender`. */ function _callBeforeTransfer(address from, address to) internal view { if (address(hook) != address(0)) hook.beforeTransfer(from, to, msg.sender); } function transfer(address to, uint256 amount) public override returns (bool) { _callBeforeTransfer(msg.sender, to); return super.transfer(to, amount); } function transferFrom(address from, address to, uint256 amount) public override returns (bool) { _callBeforeTransfer(from, to); return super.transferFrom(from, to, amount); } //============================== RECEIVE =============================== receive() external payable {} }
// SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.0; library DroneLib { bytes32 internal constant TARGET_FLAG = keccak256(bytes("DroneLib.target")); function extractTargetFromCalldata() internal pure returns (address target) { target = extractTargetFromInput(msg.data); } function extractTargetFromInput(bytes calldata data) internal pure returns (address target) { // Look at the last 32 bytes of calldata and see if the TARGET_FLAG is there. uint256 length = data.length; if (length >= 68) { bytes32 flag = bytes32(data[length - 32:]); if (flag == TARGET_FLAG) { // If the flag is there, extract the target from the calldata. target = address(bytes20(data[length - 52:length - 32])); } } // else no target present, so target is address(0). } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; import {DecoderCustomTypes} from "../../src/interfaces/DecoderCustomTypes.sol"; interface BalancerVault { function flashLoan(address, address[] memory tokens, uint256[] memory amounts, bytes calldata userData) external; function swap( DecoderCustomTypes.SingleSwap memory singleSwap, DecoderCustomTypes.FundManagement memory funds, uint256 limit, uint256 deadline ) external returns (uint256 amountCalculated); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; interface BeforeTransferHook { function beforeTransfer(address from, address to, address operator) external view; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; contract DecoderCustomTypes { // ========================================= BALANCER ========================================= struct JoinPoolRequest { address[] assets; uint256[] maxAmountsIn; bytes userData; bool fromInternalBalance; } struct ExitPoolRequest { address[] assets; uint256[] minAmountsOut; bytes userData; bool toInternalBalance; } enum SwapKind { GIVEN_IN, GIVEN_OUT } struct SingleSwap { bytes32 poolId; SwapKind kind; address assetIn; address assetOut; uint256 amount; bytes userData; } struct FundManagement { address sender; bool fromInternalBalance; address recipient; bool toInternalBalance; } // ========================================= UNISWAP V3 ========================================= struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; } struct IncreaseLiquidityParams { uint256 tokenId; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } struct DecreaseLiquidityParams { uint256 tokenId; uint128 liquidity; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } struct CollectParams { uint256 tokenId; address recipient; uint128 amount0Max; uint128 amount1Max; } struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } struct PancakeSwapExactInputParams { bytes path; address recipient; uint256 amountIn; uint256 amountOutMinimum; } // ========================================= MORPHO BLUE ========================================= struct MarketParams { address loanToken; address collateralToken; address oracle; address irm; uint256 lltv; } // ========================================= 1INCH ========================================= struct SwapDescription { address srcToken; address dstToken; address payable srcReceiver; address payable dstReceiver; uint256 amount; uint256 minReturnAmount; uint256 flags; } // ========================================= PENDLE ========================================= struct TokenInput { // TOKEN DATA address tokenIn; uint256 netTokenIn; address tokenMintSy; // AGGREGATOR DATA address pendleSwap; SwapData swapData; } struct TokenOutput { // TOKEN DATA address tokenOut; uint256 minTokenOut; address tokenRedeemSy; // AGGREGATOR DATA address pendleSwap; SwapData swapData; } struct ApproxParams { uint256 guessMin; uint256 guessMax; uint256 guessOffchain; // pass 0 in to skip this variable uint256 maxIteration; // every iteration, the diff between guessMin and guessMax will be divided by 2 uint256 eps; // the max eps between the returned result & the correct result, base 1e18. Normally this number will be set // to 1e15 (1e18/1000 = 0.1%) } struct SwapData { SwapType swapType; address extRouter; bytes extCalldata; bool needScale; } enum SwapType { NONE, KYBERSWAP, ONE_INCH, // ETH_WETH not used in Aggregator ETH_WETH } struct LimitOrderData { address limitRouter; uint256 epsSkipMarket; // only used for swap operations, will be ignored otherwise FillOrderParams[] normalFills; FillOrderParams[] flashFills; bytes optData; } struct FillOrderParams { Order order; bytes signature; uint256 makingAmount; } struct Order { uint256 salt; uint256 expiry; uint256 nonce; OrderType orderType; address token; address YT; address maker; address receiver; uint256 makingAmount; uint256 lnImpliedRate; uint256 failSafeRate; bytes permit; } enum OrderType { SY_FOR_PT, PT_FOR_SY, SY_FOR_YT, YT_FOR_SY } // ========================================= EIGEN LAYER ========================================= struct QueuedWithdrawalParams { // Array of strategies that the QueuedWithdrawal contains address[] strategies; // Array containing the amount of shares in each Strategy in the `strategies` array uint256[] shares; // The address of the withdrawer address withdrawer; } struct Withdrawal { // The address that originated the Withdrawal address staker; // The address that the staker was delegated to at the time that the Withdrawal was created address delegatedTo; // The address that can complete the Withdrawal + will receive funds when completing the withdrawal address withdrawer; // Nonce used to guarantee that otherwise identical withdrawals have unique hashes uint256 nonce; // Block number when the Withdrawal was created uint32 startBlock; // Array of strategies that the Withdrawal contains address[] strategies; // Array containing the amount of shares in each Strategy in the `strategies` array uint256[] shares; } struct SignatureWithExpiry { // the signature itself, formatted as a single bytes object bytes signature; // the expiration timestamp (UTC) of the signature uint256 expiry; } struct EarnerTreeMerkleLeaf { address earner; bytes32 earnerTokenRoot; } struct TokenTreeMerkleLeaf { address token; uint256 cumulativeEarnings; } struct RewardsMerkleClaim { uint32 rootIndex; uint32 earnerIndex; bytes earnerTreeProof; EarnerTreeMerkleLeaf earnerLeaf; uint32[] tokenIndices; bytes[] tokenTreeProofs; TokenTreeMerkleLeaf[] tokenLeaves; } // ========================================= CCIP ========================================= // If extraArgs is empty bytes, the default is 200k gas limit. struct EVM2AnyMessage { bytes receiver; // abi.encode(receiver address) for dest EVM chains bytes data; // Data payload EVMTokenAmount[] tokenAmounts; // Token transfers address feeToken; // Address of feeToken. address(0) means you will send msg.value. bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV2) } /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct EVMTokenAmount { address token; // token address on the local chain. uint256 amount; // Amount of tokens. } struct EVMExtraArgsV1 { uint256 gasLimit; } // ========================================= OFT ========================================= struct SendParam { uint32 dstEid; // Destination endpoint ID. bytes32 to; // Recipient address. uint256 amountLD; // Amount to send in local decimals. uint256 minAmountLD; // Minimum amount to send in local decimals. bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message. bytes composeMsg; // The composed message for the send() operation. bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations. } struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; } // ========================================= L1StandardBridge ========================================= struct WithdrawalTransaction { uint256 nonce; address sender; address target; uint256 value; uint256 gasLimit; bytes data; } struct OutputRootProof { bytes32 version; bytes32 stateRoot; bytes32 messagePasserStorageRoot; bytes32 latestBlockhash; } // ========================================= Mantle L1StandardBridge ========================================= struct MantleWithdrawalTransaction { uint256 nonce; address sender; address target; uint256 mntValue; uint256 value; uint256 gasLimit; bytes data; } // ========================================= Linea Bridge ========================================= struct ClaimMessageWithProofParams { bytes32[] proof; uint256 messageNumber; uint32 leafIndex; address from; address to; uint256 fee; uint256 value; address payable feeRecipient; bytes32 merkleRoot; bytes data; } // ========================================= Scroll Bridge ========================================= struct L2MessageProof { uint256 batchIndex; bytes merkleProof; } // ========================================= Camelot V3 ========================================= struct CamelotMintParams { address token0; address token1; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; } // ========================================= Velodrome V3 ========================================= struct VelodromeMintParams { address token0; address token1; int24 tickSpacing; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; uint160 sqrtPriceX96; } // ========================================= Karak ========================================= struct QueuedWithdrawal { address staker; address delegatedTo; uint256 nonce; uint256 start; WithdrawRequest request; } struct WithdrawRequest { address[] vaults; uint256[] shares; address withdrawer; } // ========================================= Term Finance ================================== /// @dev TermAuctionOfferSubmission represents an offer submission to offeror an amount of money for a specific interest rate struct TermAuctionOfferSubmission { /// @dev For an existing offer this is the unique onchain identifier for this offer. For a new offer this is a randomized input that will be used to generate the unique onchain identifier. bytes32 id; /// @dev The address of the offeror address offeror; /// @dev Hash of the offered price as a percentage of the initial loaned amount vs amount returned at maturity. This stores 9 decimal places bytes32 offerPriceHash; /// @dev The maximum amount of purchase tokens that can be lent uint256 amount; /// @dev The address of the ERC20 purchase token address purchaseToken; } // ========================================= Aera ========================================= struct AssetValue { address asset; uint256 amount; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; interface IPausable { function pause() external; function unpause() external; }
{ "evmVersion": "shanghai", "metadata": { "appendCBOR": true, "bytecodeHash": "ipfs", "useLiteralContent": false }, "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "remappings": [ "@ccip/=lib/boring-vault/lib/ccip/", "@devtools-oapp-evm/=lib/boring-vault/lib/OAppAuth/lib/devtools/packages/oapp-evm/contracts/oapp/", "@ds-test/=lib/boring-vault/lib/forge-std/lib/ds-test/src/", "@forge-std/=lib/boring-vault/lib/forge-std/src/", "@layerzerolabs/lz-evm-messagelib-v2/=lib/boring-vault/lib/OAppAuth/node_modules/@layerzerolabs/lz-evm-messagelib-v2/", "@layerzerolabs/lz-evm-protocol-v2/=lib/boring-vault/lib/OAppAuth/lib/LayerZero-V2/packages/layerzero-v2/evm/protocol/", "@layerzerolabs/oapp-evm/=lib/boring-vault/lib/OAppAuth/lib/devtools/packages/oapp-evm/", "@lz-oapp-evm/=lib/boring-vault/lib/OAppAuth/lib/LayerZero-V2/packages/layerzero-v2/evm/oapp/contracts/oapp/", "@oapp-auth/=lib/boring-vault/lib/OAppAuth/src/", "@openzeppelin/=lib/boring-vault/lib/openzeppelin-contracts/", "@solmate/=lib/boring-vault/lib/solmate/src/", "LayerZero-V2/=lib/boring-vault/lib/OAppAuth/lib/", "OAppAuth/=lib/boring-vault/lib/OAppAuth/", "boring-vault/=lib/boring-vault/", "ccip/=lib/boring-vault/lib/ccip/contracts/", "ds-test/=lib/solmate/lib/ds-test/src/", "erc4626-tests/=lib/boring-vault/lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/boring-vault/lib/OAppAuth/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", "openzeppelin-contracts/=lib/boring-vault/lib/openzeppelin-contracts/", "solady/=lib/solady/src/", "solidity-bytes-utils/=lib/boring-vault/lib/OAppAuth/node_modules/solidity-bytes-utils/", "solmate/=lib/solmate/src/", "yearn-vaults/=lib/yearn-vaults/contracts/", "@sbu/=lib/boring-vault/lib/OAppAuth/lib/solidity-bytes-utils/", "morpho-blue/=lib/boring-vault/lib/morpho-blue/" ], "viaIR": false }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_balancerVault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__BadFlashLoanIntentHash","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"targetData","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"ManagerWithMerkleVerification__FailedToVerifyManageProof","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__FlashLoanNotExecuted","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__FlashLoanNotInProgress","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__InvalidDecodersAndSanitizersLength","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__InvalidManageProofLength","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__InvalidTargetDataLength","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__InvalidValuesLength","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__OnlyCallableByBalancerVault","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__OnlyCallableByBoringVault","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__Paused","type":"error"},{"inputs":[],"name":"ManagerWithMerkleVerification__TotalSupplyMustRemainConstantDuringPlatform","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"callsMade","type":"uint256"}],"name":"BoringVaultManaged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategist","type":"address"},{"indexed":false,"internalType":"bytes32","name":"oldRoot","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"newRoot","type":"bytes32"}],"name":"ManageRootUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balancerVault","outputs":[{"internalType":"contract BalancerVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"flashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"manageRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[][]","name":"manageProofs","type":"bytes32[][]"},{"internalType":"address[]","name":"decodersAndSanitizers","type":"address[]"},{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"bytes[]","name":"targetData","type":"bytes[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"manageVaultWithMerkleVerification","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"feeAmounts","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"receiveFlashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"strategist","type":"address"},{"internalType":"bytes32","name":"_manageRoot","type":"bytes32"}],"name":"setManageRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract BoringVault","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040525f60045534801562000014575f80fd5b5060405162002245380380620022458339810160408190526200003791620000f8565b5f80546001600160a01b0385166001600160a01b031991821681178355600180549092169091556040518592919033907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908490a36040516001600160a01b0382169033907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198905f90a350506001600160a01b039182166080521660a052506200013f565b80516001600160a01b0381168114620000f3575f80fd5b919050565b5f805f606084860312156200010b575f80fd5b6200011684620000dc565b92506200012660208501620000dc565b91506200013660408501620000dc565b90509250925092565b60805160a0516120a66200019f5f395f818160ee015281816107e3015281816109da0152610bed01525f8181610225015281816103da01528181610511015281816106170152818161076601528181610a8c0152610ccf01526120a65ff3fe608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80638456cb5911610088578063bf7e214f11610063578063bf7e214f146101e7578063f04f2707146101fa578063f2fde38b1461020d578063fbfa77cf14610220575f80fd5b80638456cb59146101b05780638da5cb5b146101b8578063b187bd26146101ca575f80fd5b80633f4ba83a116100c35780633f4ba83a146101555780635c38449e1461015d5780635ca58a99146101705780637a9e5e4b1461019d575f80fd5b8063158274a5146100e957806321801a991461012d578063244b0f6a14610142575b5f80fd5b6101107f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61014061013b366004611299565b610247565b005b61014061015036600461130a565b6102df565b6101406106f6565b61014061016b36600461142c565b61075b565b61018f61017e3660046114d0565b60026020525f908152604090205481565b604051908152602001610124565b6101406101ab3660046114d0565b610883565b610140610967565b5f54610110906001600160a01b031681565b6005546101d79060ff1681565b6040519015158152602001610124565b600154610110906001600160a01b031681565b6101406102083660046114eb565b6109cf565b61014061021b3660046114d0565b610da7565b6101107f000000000000000000000000000000000000000000000000000000000000000081565b61025c335f356001600160e01b031916610e22565b6102815760405162461bcd60e51b8152600401610278906115a5565b60405180910390fd5b6001600160a01b0382165f81815260026020908152604091829020805490859055825181815291820185905292917f0b958dec85f1470000479dfb22c365829411f52bcde602d24ea0abf5ac7e8860910160405180910390a2505050565b6102f4335f356001600160e01b031916610e22565b6103105760405162461bcd60e51b8152600401610278906115a5565b60055460ff161561033457604051631b7b196560e31b815260040160405180910390fd5b848981146103555760405163029c70cf60e41b815260040160405180910390fd5b8084146103755760405163581ddbfd60e01b815260040160405180910390fd5b8082146103955760405163e9fd1adf60e01b815260040160405180910390fd5b8088146103b557604051631b4d824d60e31b815260040160405180910390fd5b335f9081526002602090815260408083205481516318160ddd60e01b815291519093927f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316926318160ddd92600480830193928290030181865afa158015610427573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061044b91906115cb565b90505f5b838110156106145761050f838f8f8481811061046d5761046d6115e2565b905060200281019061047f91906115f6565b8f8f86818110610491576104916115e2565b90506020020160208101906104a691906114d0565b8e8e878181106104b8576104b86115e2565b90506020020160208101906104cd91906114d0565b8b8b888181106104df576104df6115e2565b905060200201358e8e898181106104f8576104f86115e2565b905060200281019061050a919061163b565b610eca565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f6e715d08b8b84818110610550576105506115e2565b905060200201602081019061056591906114d0565b8a8a85818110610577576105776115e2565b9050602002810190610589919061163b565b8a8a8781811061059b5761059b6115e2565b905060200201356040518563ffffffff1660e01b81526004016105c194939291906116a5565b5f604051808303815f875af11580156105dc573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261060391908101906117b5565b5061060d816117fa565b905061044f565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610671573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061069591906115cb565b81146106b457604051630ecee17560e01b815260040160405180910390fd5b6040518381527f53d426e7d80bb2c8674d3b45577e2d464d423faad6531b21f95ac11ac18b1cb69060200160405180910390a150505050505050505050505050565b61070b335f356001600160e01b031916610e22565b6107275760405162461bcd60e51b8152600401610278906115a5565b6005805460ff191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107a4576040516377ed816560e01b815260040160405180910390fd5b81816040516107b4929190611812565b60405190819003812060049081556003805460ff19166001179055632e1c224f60e11b82526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691635c38449e91610822918b918b918b918b918b918b918b9101611868565b5f604051808303815f87803b158015610839575f80fd5b505af115801561084b573d5f803e3d5ffd5b50506003805460ff1916905550506004541561087a57604051633de6ce8160e21b815260040160405180910390fd5b50505050505050565b5f546001600160a01b0316331480610914575060015460405163b700961360e01b81526001600160a01b039091169063b7009613906108d590339030906001600160e01b03195f3516906004016118de565b602060405180830381865afa1580156108f0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610914919061190b565b61091c575f80fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198905f90a350565b61097c335f356001600160e01b031916610e22565b6109985760405162461bcd60e51b8152600401610278906115a5565b6005805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a185760405163a38bce7f60e01b815260040160405180910390fd5b60035460ff16610a3b576040516326e6e2c760e01b815260040160405180910390fd5b5f8282604051610a4c929190611812565b604051809103902090506004548114610a7857604051631663f61360e01b815260040160405180910390fd5b5f60048190555b86811015610b0b57610afb7f0000000000000000000000000000000000000000000000000000000000000000898984818110610abd57610abd6115e2565b905060200201358c8c85818110610ad657610ad66115e2565b9050602002016020810190610aeb91906114d0565b6001600160a01b03169190610fb4565b610b04816117fa565b9050610a7f565b505f80808080610b1d87890189611ba1565b60405163122587b560e11b815294995092975090955093509150309063244b0f6a90610b559088908890889088908890600401611d39565b5f604051808303815f87803b158015610b6c575f80fd5b505af1158015610b7e573d5f803e3d5ffd5b5050505050505050505f878790506001600160401b03811115610ba357610ba36116da565b604051908082528060200260200182016040528015610bd657816020015b6060815260200190600190039081610bc15790505b5090505f5b87811015610cc45763a9059cbb60e01b7f0000000000000000000000000000000000000000000000000000000000000000888884818110610c1e57610c1e6115e2565b905060200201358b8b85818110610c3757610c376115e2565b90506020020135610c489190611e14565b6040516001600160a01b0390921660248301526044820152606401604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050828281518110610ca857610ca86115e2565b602002602001018190525080610cbd906117fa565b9050610bdb565b506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663224d87038b8b848b6001600160401b03811115610d0f57610d0f6116da565b604051908082528060200260200182016040528015610d38578160200160208202803683370190505b506040518563ffffffff1660e01b8152600401610d589493929190611e27565b5f604051808303815f875af1158015610d73573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d9a9190810190611e6b565b5050505050505050505050565b610dbc335f356001600160e01b031916610e22565b610dd85760405162461bcd60e51b8152600401610278906115a5565b5f80546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b6001545f906001600160a01b03168015801590610ea9575060405163b700961360e01b81526001600160a01b0382169063b700961390610e6a908790309088906004016118de565b602060405180830381865afa158015610e85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ea9919061190b565b80610ec057505f546001600160a01b038581169116145b9150505b92915050565b5f610f1483838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250506001600160a01b038a1692915050611043565b806020019051810190610f2791906117b5565b90505f610f3484846110b5565b90506001600160a01b03811615610f6a578181604051602001610f58929190611f15565b60405160208183030381529060405291505b610f838a8a8a898b8a610f7d8a8c611f46565b8961116f565b610fa8578584848760405163c0dcd1a760e01b815260040161027894939291906116a5565b50505050505050505050565b5f60405163a9059cbb60e01b81526001600160a01b038416600482015282602482015260205f6044835f895af191505080601f3d1160015f511416151615610ffe5750823b153d17155b8061103d5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610278565b50505050565b60605f80846001600160a01b03168460405161105f9190611f74565b5f60405180830381855afa9150503d805f8114611097576040519150601f19603f3d011682016040523d82523d5f602084013e61109c565b606091505b50915091506110ac8583836111c3565b95945050505050565b5f8160448110611168575f84846110cd602085611f8f565b6110d8928290611fa2565b6110e191611fc9565b60408051808201909152600f81526e111c9bdb99531a588b9d185c99d95d608a1b60209091015290507fc1b9dfe6c6d6343c26291b77edfcc5dbc62c3afa2ee72581da4e3cdbe96a0a4f810161116657848461113e603485611f8f565b9061114a602086611f8f565b9261115793929190611fa2565b61116091611fe6565b60601c92505b505b5092915050565b5f805f851190505f8688838787604051602001611190959493929190612014565b6040516020818303038152906040528051906020012090506111b48a8a8d84611222565b9b9a5050505050505050505050565b6060826111d8576111d38261125a565b61121b565b81511580156111ef57506001600160a01b0384163b155b1561121857604051639996b31560e01b81526001600160a01b0385166004820152602401610278565b50805b9392505050565b5f8315611252578360051b8501855b803580851160051b94855260209485185260405f2093018181106112315750505b501492915050565b80511561126957805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b50565b6001600160a01b0381168114611282575f80fd5b5f80604083850312156112aa575f80fd5b82356112b581611285565b946020939093013593505050565b5f8083601f8401126112d3575f80fd5b5081356001600160401b038111156112e9575f80fd5b6020830191508360208260051b8501011115611303575f80fd5b9250929050565b5f805f805f805f805f8060a08b8d031215611323575f80fd5b8a356001600160401b0380821115611339575f80fd5b6113458e838f016112c3565b909c509a5060208d013591508082111561135d575f80fd5b6113698e838f016112c3565b909a50985060408d0135915080821115611381575f80fd5b61138d8e838f016112c3565b909850965060608d01359150808211156113a5575f80fd5b6113b18e838f016112c3565b909650945060808d01359150808211156113c9575f80fd5b506113d68d828e016112c3565b915080935050809150509295989b9194979a5092959850565b5f8083601f8401126113ff575f80fd5b5081356001600160401b03811115611415575f80fd5b602083019150836020828501011115611303575f80fd5b5f805f805f805f6080888a031215611442575f80fd5b873561144d81611285565b965060208801356001600160401b0380821115611468575f80fd5b6114748b838c016112c3565b909850965060408a013591508082111561148c575f80fd5b6114988b838c016112c3565b909650945060608a01359150808211156114b0575f80fd5b506114bd8a828b016113ef565b989b979a50959850939692959293505050565b5f602082840312156114e0575f80fd5b813561121b81611285565b5f805f805f805f806080898b031215611502575f80fd5b88356001600160401b0380821115611518575f80fd5b6115248c838d016112c3565b909a50985060208b013591508082111561153c575f80fd5b6115488c838d016112c3565b909850965060408b0135915080821115611560575f80fd5b61156c8c838d016112c3565b909650945060608b0135915080821115611584575f80fd5b506115918b828c016113ef565b999c989b5096995094979396929594505050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b5f602082840312156115db575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e1984360301811261160b575f80fd5b8301803591506001600160401b03821115611624575f80fd5b6020019150600581901b3603821315611303575f80fd5b5f808335601e19843603018112611650575f80fd5b8301803591506001600160401b03821115611669575f80fd5b602001915036819003821315611303575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160a01b03851681526060602082018190525f906116c9908301858761167d565b905082604083015295945050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715611716576117166116da565b604052919050565b5f6001600160401b03821115611736576117366116da565b50601f01601f191660200190565b5f5b8381101561175e578181015183820152602001611746565b50505f910152565b5f82601f830112611775575f80fd5b81516117886117838261171e565b6116ee565b81815284602083860101111561179c575f80fd5b6117ad826020830160208701611744565b949350505050565b5f602082840312156117c5575f80fd5b81516001600160401b038111156117da575f80fd5b610ec084828501611766565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161180b5761180b6117e6565b5060010190565b818382375f9101908152919050565b8183525f60208085019450825f5b8581101561185d57813561184281611285565b6001600160a01b03168752958201959082019060010161182f565b509495945050505050565b6001600160a01b03881681526080602082018190525f9061188c908301888a611821565b82810360408401528581526001600160fb1b038611156118aa575f80fd5b8560051b8088602084013701828103602090810160608501526118d0908201858761167d565b9a9950505050505050505050565b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b5f6020828403121561191b575f80fd5b8151801515811461121b575f80fd5b5f6001600160401b03821115611942576119426116da565b5060051b60200190565b5f82601f83011261195b575f80fd5b8135602061196b6117838361192a565b828152600592831b8501820192828201919087851115611989575f80fd5b8387015b85811015611a195780356001600160401b038111156119ab575f8081fd5b8801603f81018a136119bc575f8081fd5b8581013560406119ce6117838361192a565b82815291851b8301810191888101908d8411156119ea575f8081fd5b938201935b83851015611a08578435825293890193908901906119ef565b88525050509385019350840161198d565b5090979650505050505050565b5f82601f830112611a35575f80fd5b81356020611a456117838361192a565b82815260059290921b84018101918181019086841115611a63575f80fd5b8286015b84811015611a87578035611a7a81611285565b8352918301918301611a67565b509695505050505050565b5f82601f830112611aa1575f80fd5b81356020611ab16117838361192a565b82815260059290921b84018101918181019086841115611acf575f80fd5b8286015b84811015611a875780356001600160401b03811115611af1575f8081fd5b8701603f81018913611b02575f8081fd5b848101356040611b146117838361171e565b8281528b82848601011115611b28575f8081fd5b82828501898301375f92810188019290925250845250918301918301611ad3565b5f82601f830112611b58575f80fd5b81356020611b686117838361192a565b82815260059290921b84018101918181019086841115611b86575f80fd5b8286015b84811015611a875780358352918301918301611b8a565b5f805f805f60a08688031215611bb5575f80fd5b85356001600160401b0380821115611bcb575f80fd5b611bd789838a0161194c565b96506020880135915080821115611bec575f80fd5b611bf889838a01611a26565b95506040880135915080821115611c0d575f80fd5b611c1989838a01611a26565b94506060880135915080821115611c2e575f80fd5b611c3a89838a01611a92565b93506080880135915080821115611c4f575f80fd5b50611c5c88828901611b49565b9150509295509295909350565b5f8151808452602080850194508084015f5b8381101561185d5781516001600160a01b031687529582019590820190600101611c7b565b5f81518084526020808501808196508360051b810191508286015f5b85811015611cfe57828403895281518051808652611cdf81888801898501611744565b99860199601f01601f1916949094018501935090840190600101611cbc565b5091979650505050505050565b5f8151808452602080850194508084015f5b8381101561185d57815187529582019590820190600101611d1d565b5f60a0820160a0835280885180835260c08501915060c08160051b86010192506020808b015f805b84811015611db55788870360bf19018652825180518089529085019085890190845b81811015611d9f57835183529287019291870191600101611d83565b5090985050509483019491830191600101611d61565b50505085840381870152505050611dcc8188611c69565b90508281036040840152611de08187611c69565b90508281036060840152611df48186611ca0565b90508281036080840152611e088185611d0b565b98975050505050505050565b80820180821115610ec457610ec46117e6565b606081525f611e3a606083018688611821565b8281036020840152611e4c8186611ca0565b90508281036040840152611e608185611d0b565b979650505050505050565b5f6020808385031215611e7c575f80fd5b82516001600160401b0380821115611e92575f80fd5b818501915085601f830112611ea5575f80fd5b8151611eb36117838261192a565b81815260059190911b83018401908481019088831115611ed1575f80fd5b8585015b83811015611f0857805185811115611eec575f8081fd5b611efa8b89838a0101611766565b845250918601918601611ed5565b5098975050505050505050565b5f8351611f26818460208801611744565b60609390931b6001600160601b0319169190920190815260140192915050565b6001600160e01b031981358181169160048510156111665760049490940360031b84901b1690921692915050565b5f8251611f85818460208701611744565b9190910192915050565b81810381811115610ec457610ec46117e6565b5f8085851115611fb0575f80fd5b83861115611fbc575f80fd5b5050820193919092039150565b80356020831015610ec4575f19602084900360031b1b1692915050565b6001600160601b031981358181169160148510156111665760149490940360031b84901b1690921692915050565b6001600160601b0319606087811b8216835286901b16601482015283151560f81b60288201526001600160e01b03198316602982015281515f9061205f81602d850160208701611744565b91909101602d01969550505050505056fea26469706673582212208a54c2671d4e4f5079bf5876eb683638ceb02c1ca2acb018c33520f248d6a85164736f6c63430008150033000000000000000000000000771263e3bc6acda5ae388a3f8a0c2dd7a17275fc000000000000000000000000279cad277447965af3d24a78197aad1b02a2c5890000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80638456cb5911610088578063bf7e214f11610063578063bf7e214f146101e7578063f04f2707146101fa578063f2fde38b1461020d578063fbfa77cf14610220575f80fd5b80638456cb59146101b05780638da5cb5b146101b8578063b187bd26146101ca575f80fd5b80633f4ba83a116100c35780633f4ba83a146101555780635c38449e1461015d5780635ca58a99146101705780637a9e5e4b1461019d575f80fd5b8063158274a5146100e957806321801a991461012d578063244b0f6a14610142575b5f80fd5b6101107f000000000000000000000000000000000000000000000000000000000000000181565b6040516001600160a01b0390911681526020015b60405180910390f35b61014061013b366004611299565b610247565b005b61014061015036600461130a565b6102df565b6101406106f6565b61014061016b36600461142c565b61075b565b61018f61017e3660046114d0565b60026020525f908152604090205481565b604051908152602001610124565b6101406101ab3660046114d0565b610883565b610140610967565b5f54610110906001600160a01b031681565b6005546101d79060ff1681565b6040519015158152602001610124565b600154610110906001600160a01b031681565b6101406102083660046114eb565b6109cf565b61014061021b3660046114d0565b610da7565b6101107f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c58981565b61025c335f356001600160e01b031916610e22565b6102815760405162461bcd60e51b8152600401610278906115a5565b60405180910390fd5b6001600160a01b0382165f81815260026020908152604091829020805490859055825181815291820185905292917f0b958dec85f1470000479dfb22c365829411f52bcde602d24ea0abf5ac7e8860910160405180910390a2505050565b6102f4335f356001600160e01b031916610e22565b6103105760405162461bcd60e51b8152600401610278906115a5565b60055460ff161561033457604051631b7b196560e31b815260040160405180910390fd5b848981146103555760405163029c70cf60e41b815260040160405180910390fd5b8084146103755760405163581ddbfd60e01b815260040160405180910390fd5b8082146103955760405163e9fd1adf60e01b815260040160405180910390fd5b8088146103b557604051631b4d824d60e31b815260040160405180910390fd5b335f9081526002602090815260408083205481516318160ddd60e01b815291519093927f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c5896001600160a01b0316926318160ddd92600480830193928290030181865afa158015610427573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061044b91906115cb565b90505f5b838110156106145761050f838f8f8481811061046d5761046d6115e2565b905060200281019061047f91906115f6565b8f8f86818110610491576104916115e2565b90506020020160208101906104a691906114d0565b8e8e878181106104b8576104b86115e2565b90506020020160208101906104cd91906114d0565b8b8b888181106104df576104df6115e2565b905060200201358e8e898181106104f8576104f86115e2565b905060200281019061050a919061163b565b610eca565b7f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c5896001600160a01b031663f6e715d08b8b84818110610550576105506115e2565b905060200201602081019061056591906114d0565b8a8a85818110610577576105776115e2565b9050602002810190610589919061163b565b8a8a8781811061059b5761059b6115e2565b905060200201356040518563ffffffff1660e01b81526004016105c194939291906116a5565b5f604051808303815f875af11580156105dc573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261060391908101906117b5565b5061060d816117fa565b905061044f565b507f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c5896001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610671573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061069591906115cb565b81146106b457604051630ecee17560e01b815260040160405180910390fd5b6040518381527f53d426e7d80bb2c8674d3b45577e2d464d423faad6531b21f95ac11ac18b1cb69060200160405180910390a150505050505050505050505050565b61070b335f356001600160e01b031916610e22565b6107275760405162461bcd60e51b8152600401610278906115a5565b6005805460ff191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a1565b336001600160a01b037f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c58916146107a4576040516377ed816560e01b815260040160405180910390fd5b81816040516107b4929190611812565b60405190819003812060049081556003805460ff19166001179055632e1c224f60e11b82526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000011691635c38449e91610822918b918b918b918b918b918b918b9101611868565b5f604051808303815f87803b158015610839575f80fd5b505af115801561084b573d5f803e3d5ffd5b50506003805460ff1916905550506004541561087a57604051633de6ce8160e21b815260040160405180910390fd5b50505050505050565b5f546001600160a01b0316331480610914575060015460405163b700961360e01b81526001600160a01b039091169063b7009613906108d590339030906001600160e01b03195f3516906004016118de565b602060405180830381865afa1580156108f0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610914919061190b565b61091c575f80fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b76389980198905f90a350565b61097c335f356001600160e01b031916610e22565b6109985760405162461bcd60e51b8152600401610278906115a5565b6005805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a1565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000011614610a185760405163a38bce7f60e01b815260040160405180910390fd5b60035460ff16610a3b576040516326e6e2c760e01b815260040160405180910390fd5b5f8282604051610a4c929190611812565b604051809103902090506004548114610a7857604051631663f61360e01b815260040160405180910390fd5b5f60048190555b86811015610b0b57610afb7f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c589898984818110610abd57610abd6115e2565b905060200201358c8c85818110610ad657610ad66115e2565b9050602002016020810190610aeb91906114d0565b6001600160a01b03169190610fb4565b610b04816117fa565b9050610a7f565b505f80808080610b1d87890189611ba1565b60405163122587b560e11b815294995092975090955093509150309063244b0f6a90610b559088908890889088908890600401611d39565b5f604051808303815f87803b158015610b6c575f80fd5b505af1158015610b7e573d5f803e3d5ffd5b5050505050505050505f878790506001600160401b03811115610ba357610ba36116da565b604051908082528060200260200182016040528015610bd657816020015b6060815260200190600190039081610bc15790505b5090505f5b87811015610cc45763a9059cbb60e01b7f0000000000000000000000000000000000000000000000000000000000000001888884818110610c1e57610c1e6115e2565b905060200201358b8b85818110610c3757610c376115e2565b90506020020135610c489190611e14565b6040516001600160a01b0390921660248301526044820152606401604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050828281518110610ca857610ca86115e2565b602002602001018190525080610cbd906117fa565b9050610bdb565b506001600160a01b037f000000000000000000000000279cad277447965af3d24a78197aad1b02a2c5891663224d87038b8b848b6001600160401b03811115610d0f57610d0f6116da565b604051908082528060200260200182016040528015610d38578160200160208202803683370190505b506040518563ffffffff1660e01b8152600401610d589493929190611e27565b5f604051808303815f875af1158015610d73573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d9a9190810190611e6b565b5050505050505050505050565b610dbc335f356001600160e01b031916610e22565b610dd85760405162461bcd60e51b8152600401610278906115a5565b5f80546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b6001545f906001600160a01b03168015801590610ea9575060405163b700961360e01b81526001600160a01b0382169063b700961390610e6a908790309088906004016118de565b602060405180830381865afa158015610e85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ea9919061190b565b80610ec057505f546001600160a01b038581169116145b9150505b92915050565b5f610f1483838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250506001600160a01b038a1692915050611043565b806020019051810190610f2791906117b5565b90505f610f3484846110b5565b90506001600160a01b03811615610f6a578181604051602001610f58929190611f15565b60405160208183030381529060405291505b610f838a8a8a898b8a610f7d8a8c611f46565b8961116f565b610fa8578584848760405163c0dcd1a760e01b815260040161027894939291906116a5565b50505050505050505050565b5f60405163a9059cbb60e01b81526001600160a01b038416600482015282602482015260205f6044835f895af191505080601f3d1160015f511416151615610ffe5750823b153d17155b8061103d5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610278565b50505050565b60605f80846001600160a01b03168460405161105f9190611f74565b5f60405180830381855afa9150503d805f8114611097576040519150601f19603f3d011682016040523d82523d5f602084013e61109c565b606091505b50915091506110ac8583836111c3565b95945050505050565b5f8160448110611168575f84846110cd602085611f8f565b6110d8928290611fa2565b6110e191611fc9565b60408051808201909152600f81526e111c9bdb99531a588b9d185c99d95d608a1b60209091015290507fc1b9dfe6c6d6343c26291b77edfcc5dbc62c3afa2ee72581da4e3cdbe96a0a4f810161116657848461113e603485611f8f565b9061114a602086611f8f565b9261115793929190611fa2565b61116091611fe6565b60601c92505b505b5092915050565b5f805f851190505f8688838787604051602001611190959493929190612014565b6040516020818303038152906040528051906020012090506111b48a8a8d84611222565b9b9a5050505050505050505050565b6060826111d8576111d38261125a565b61121b565b81511580156111ef57506001600160a01b0384163b155b1561121857604051639996b31560e01b81526001600160a01b0385166004820152602401610278565b50805b9392505050565b5f8315611252578360051b8501855b803580851160051b94855260209485185260405f2093018181106112315750505b501492915050565b80511561126957805160208201fd5b60405163d6bda27560e01b815260040160405180910390fd5b50565b6001600160a01b0381168114611282575f80fd5b5f80604083850312156112aa575f80fd5b82356112b581611285565b946020939093013593505050565b5f8083601f8401126112d3575f80fd5b5081356001600160401b038111156112e9575f80fd5b6020830191508360208260051b8501011115611303575f80fd5b9250929050565b5f805f805f805f805f8060a08b8d031215611323575f80fd5b8a356001600160401b0380821115611339575f80fd5b6113458e838f016112c3565b909c509a5060208d013591508082111561135d575f80fd5b6113698e838f016112c3565b909a50985060408d0135915080821115611381575f80fd5b61138d8e838f016112c3565b909850965060608d01359150808211156113a5575f80fd5b6113b18e838f016112c3565b909650945060808d01359150808211156113c9575f80fd5b506113d68d828e016112c3565b915080935050809150509295989b9194979a5092959850565b5f8083601f8401126113ff575f80fd5b5081356001600160401b03811115611415575f80fd5b602083019150836020828501011115611303575f80fd5b5f805f805f805f6080888a031215611442575f80fd5b873561144d81611285565b965060208801356001600160401b0380821115611468575f80fd5b6114748b838c016112c3565b909850965060408a013591508082111561148c575f80fd5b6114988b838c016112c3565b909650945060608a01359150808211156114b0575f80fd5b506114bd8a828b016113ef565b989b979a50959850939692959293505050565b5f602082840312156114e0575f80fd5b813561121b81611285565b5f805f805f805f806080898b031215611502575f80fd5b88356001600160401b0380821115611518575f80fd5b6115248c838d016112c3565b909a50985060208b013591508082111561153c575f80fd5b6115488c838d016112c3565b909850965060408b0135915080821115611560575f80fd5b61156c8c838d016112c3565b909650945060608b0135915080821115611584575f80fd5b506115918b828c016113ef565b999c989b5096995094979396929594505050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b5f602082840312156115db575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e1984360301811261160b575f80fd5b8301803591506001600160401b03821115611624575f80fd5b6020019150600581901b3603821315611303575f80fd5b5f808335601e19843603018112611650575f80fd5b8301803591506001600160401b03821115611669575f80fd5b602001915036819003821315611303575f80fd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160a01b03851681526060602082018190525f906116c9908301858761167d565b905082604083015295945050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715611716576117166116da565b604052919050565b5f6001600160401b03821115611736576117366116da565b50601f01601f191660200190565b5f5b8381101561175e578181015183820152602001611746565b50505f910152565b5f82601f830112611775575f80fd5b81516117886117838261171e565b6116ee565b81815284602083860101111561179c575f80fd5b6117ad826020830160208701611744565b949350505050565b5f602082840312156117c5575f80fd5b81516001600160401b038111156117da575f80fd5b610ec084828501611766565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161180b5761180b6117e6565b5060010190565b818382375f9101908152919050565b8183525f60208085019450825f5b8581101561185d57813561184281611285565b6001600160a01b03168752958201959082019060010161182f565b509495945050505050565b6001600160a01b03881681526080602082018190525f9061188c908301888a611821565b82810360408401528581526001600160fb1b038611156118aa575f80fd5b8560051b8088602084013701828103602090810160608501526118d0908201858761167d565b9a9950505050505050505050565b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b5f6020828403121561191b575f80fd5b8151801515811461121b575f80fd5b5f6001600160401b03821115611942576119426116da565b5060051b60200190565b5f82601f83011261195b575f80fd5b8135602061196b6117838361192a565b828152600592831b8501820192828201919087851115611989575f80fd5b8387015b85811015611a195780356001600160401b038111156119ab575f8081fd5b8801603f81018a136119bc575f8081fd5b8581013560406119ce6117838361192a565b82815291851b8301810191888101908d8411156119ea575f8081fd5b938201935b83851015611a08578435825293890193908901906119ef565b88525050509385019350840161198d565b5090979650505050505050565b5f82601f830112611a35575f80fd5b81356020611a456117838361192a565b82815260059290921b84018101918181019086841115611a63575f80fd5b8286015b84811015611a87578035611a7a81611285565b8352918301918301611a67565b509695505050505050565b5f82601f830112611aa1575f80fd5b81356020611ab16117838361192a565b82815260059290921b84018101918181019086841115611acf575f80fd5b8286015b84811015611a875780356001600160401b03811115611af1575f8081fd5b8701603f81018913611b02575f8081fd5b848101356040611b146117838361171e565b8281528b82848601011115611b28575f8081fd5b82828501898301375f92810188019290925250845250918301918301611ad3565b5f82601f830112611b58575f80fd5b81356020611b686117838361192a565b82815260059290921b84018101918181019086841115611b86575f80fd5b8286015b84811015611a875780358352918301918301611b8a565b5f805f805f60a08688031215611bb5575f80fd5b85356001600160401b0380821115611bcb575f80fd5b611bd789838a0161194c565b96506020880135915080821115611bec575f80fd5b611bf889838a01611a26565b95506040880135915080821115611c0d575f80fd5b611c1989838a01611a26565b94506060880135915080821115611c2e575f80fd5b611c3a89838a01611a92565b93506080880135915080821115611c4f575f80fd5b50611c5c88828901611b49565b9150509295509295909350565b5f8151808452602080850194508084015f5b8381101561185d5781516001600160a01b031687529582019590820190600101611c7b565b5f81518084526020808501808196508360051b810191508286015f5b85811015611cfe57828403895281518051808652611cdf81888801898501611744565b99860199601f01601f1916949094018501935090840190600101611cbc565b5091979650505050505050565b5f8151808452602080850194508084015f5b8381101561185d57815187529582019590820190600101611d1d565b5f60a0820160a0835280885180835260c08501915060c08160051b86010192506020808b015f805b84811015611db55788870360bf19018652825180518089529085019085890190845b81811015611d9f57835183529287019291870191600101611d83565b5090985050509483019491830191600101611d61565b50505085840381870152505050611dcc8188611c69565b90508281036040840152611de08187611c69565b90508281036060840152611df48186611ca0565b90508281036080840152611e088185611d0b565b98975050505050505050565b80820180821115610ec457610ec46117e6565b606081525f611e3a606083018688611821565b8281036020840152611e4c8186611ca0565b90508281036040840152611e608185611d0b565b979650505050505050565b5f6020808385031215611e7c575f80fd5b82516001600160401b0380821115611e92575f80fd5b818501915085601f830112611ea5575f80fd5b8151611eb36117838261192a565b81815260059190911b83018401908481019088831115611ed1575f80fd5b8585015b83811015611f0857805185811115611eec575f8081fd5b611efa8b89838a0101611766565b845250918601918601611ed5565b5098975050505050505050565b5f8351611f26818460208801611744565b60609390931b6001600160601b0319169190920190815260140192915050565b6001600160e01b031981358181169160048510156111665760049490940360031b84901b1690921692915050565b5f8251611f85818460208701611744565b9190910192915050565b81810381811115610ec457610ec46117e6565b5f8085851115611fb0575f80fd5b83861115611fbc575f80fd5b5050820193919092039150565b80356020831015610ec4575f19602084900360031b1b1692915050565b6001600160601b031981358181169160148510156111665760149490940360031b84901b1690921692915050565b6001600160601b0319606087811b8216835286901b16601482015283151560f81b60288201526001600160e01b03198316602982015281515f9061205f81602d850160208701611744565b91909101602d01969550505050505056fea26469706673582212208a54c2671d4e4f5079bf5876eb683638ceb02c1ca2acb018c33520f248d6a85164736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000771263e3bc6acda5ae388a3f8a0c2dd7a17275fc000000000000000000000000279cad277447965af3d24a78197aad1b02a2c5890000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _owner (address): 0x771263e3Bc6aCDa5aE388A3F8A0c2dd7A17275FC
Arg [1] : _vault (address): 0x279CAD277447965AF3d24a78197aad1B02a2c589
Arg [2] : _balancerVault (address): 0x0000000000000000000000000000000000000001
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000771263e3bc6acda5ae388a3f8a0c2dd7a17275fc
Arg [1] : 000000000000000000000000279cad277447965af3d24a78197aad1b02a2c589
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode Sourcemap
708:11500:15:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3801:44;;;;;;;;-1:-1:-1;;;;;200:32:20;;;182:51;;170:2;155:18;3801:44:15;;;;;;;;4266:255;;;;;;:::i;:::-;;:::i;:::-;;5492:1497;;;;;;:::i;:::-;;:::i;4945:99::-;;;:::i;7475:586::-;;;;;;:::i;:::-;;:::i;1777:45::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;4938:25:20;;;4926:2;4911:18;1777:45:15;4792:177:20;1523:434:8;;;;;;:::i;:::-;;:::i;4686:94:15:-;;;:::i;562:20:8:-;;;;;-1:-1:-1;;;;;562:20:8;;;2275::15;;;;;;;;;;;;5616:14:20;;5609:22;5591:41;;5579:2;5564:18;2275:20:15;5451:187:20;589:26:8;;;;;-1:-1:-1;;;;;589:26:8;;;8382:1945:15;;;;;;:::i;:::-;;:::i;1963:164:8:-;;;;;;:::i;:::-;;:::i;3671:34:15:-;;;;;4266:255;902:33:8;915:10;927:7;;-1:-1:-1;;;;;;927:7:8;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:8;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;;;4380:22:15;::::1;4362:15;4380:22:::0;;;:10:::1;:22;::::0;;;;;;;;;;4412:36;;;;4463:51;;8057:25:20;;;8098:18;;;8091:34;;;4380:22:15;;4463:51:::1;::::0;8030:18:20;4463:51:15::1;;;;;;;4352:169;4266:255:::0;;:::o;5492:1497::-;902:33:8;915:10;927:7;;-1:-1:-1;;;;;;927:7:8;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:8;;;;;;;:::i;:::-;5778:8:15::1;::::0;::::1;;5774:60;;;5795:39;;-1:-1:-1::0;;;5795:39:15::1;;;;;;;;;;;5774:60;5868:7:::0;5896:36;;::::1;5892:106;;5941:57;;-1:-1:-1::0;;;5941:57:15::1;;;;;;;;;;;5892:106;6012:34:::0;;::::1;6008:103;;6055:56;;-1:-1:-1::0;;;6055:56:15::1;;;;;;;;;;;6008:103;6125:30:::0;;::::1;6121:95;;6164:52;;-1:-1:-1::0;;;6164:52:15::1;;;;;;;;;;;6121:95;6230:45:::0;;::::1;6226:150;;6298:67;;-1:-1:-1::0;;;6298:67:15::1;;;;;;;;;;;6226:150;6428:10;6386:28;6417:22:::0;;;:10:::1;:22;::::0;;;;;;;;6471:19;;-1:-1:-1;;;6471:19:15;;;;6417:22;;6386:28;6471:5:::1;-1:-1:-1::0;;;;;6471:17:15::1;::::0;::::1;::::0;:19:::1;::::0;;::::1;::::0;6417:22;6471:19;;;;;:17;:19:::1;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6449:41;;6506:9;6501:277;6521:13;6517:1;:17;6501:277;;;6555:148;6588:20;6610:12;;6623:1;6610:15;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;6627:21;;6649:1;6627:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;6653:7;;6661:1;6653:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;6665:6;;6672:1;6665:9;;;;;;;:::i;:::-;;;;;;;6676:10;;6687:1;6676:13;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;6555:15;:148::i;:::-;6717:5;-1:-1:-1::0;;;;;6717:12:15::1;;6730:7;;6738:1;6730:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;6742;;6753:1;6742:13;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;6757:6;;6764:1;6757:9;;;;;;;:::i;:::-;;;;;;;6717:50;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;6717:50:15::1;::::0;::::1;;::::0;::::1;::::0;;;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;6536:3:15::1;::::0;::::1;:::i;:::-;;;6501:277;;;;6806:5;-1:-1:-1::0;;;;;6806:17:15::1;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6791:11;:34;6787:148;;6848:76;;-1:-1:-1::0;;;6848:76:15::1;;;;;;;;;;;6787:148;6949:33;::::0;4938:25:20;;;6949:33:15::1;::::0;4926:2:20;4911:18;6949:33:15::1;;;;;;;5764:1225;;;5492:1497:::0;;;;;;;;;;:::o;4945:99::-;902:33:8;915:10;927:7;;-1:-1:-1;;;;;;927:7:8;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:8;;;;;;;:::i;:::-;4996:8:15::1;:16:::0;;-1:-1:-1;;4996:16:15::1;::::0;;5027:10:::1;::::0;::::1;::::0;5007:5:::1;::::0;5027:10:::1;4945:99::o:0;7475:586::-;7654:10;-1:-1:-1;;;;;7676:5:15;7654:28;;7650:99;;7691:58;;-1:-1:-1;;;7691:58:15;;;;;;;;;;;7650:99;7792:8;;7782:19;;;;;;;:::i;:::-;;;;;;;;;7760;:41;;;7811:19;:26;;-1:-1:-1;;7811:26:15;7833:4;7811:26;;;-1:-1:-1;;;7847:61:15;;-1:-1:-1;;;;;7847:13:15;:23;;;;:61;;7871:9;;7882:6;;;;7890:7;;;;7899:8;;;;7847:61;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7918:19:15;:27;;-1:-1:-1;;7918:27:15;;;-1:-1:-1;;7959:19:15;;:33;7955:99;;8001:53;;-1:-1:-1;;;8001:53:15;;;;;;;;;;;7955:99;7475:586;;;;;;;:::o;1523:434:8:-;1794:5;;-1:-1:-1;;;;;1794:5:8;1780:10;:19;;:76;;-1:-1:-1;1803:9:8;;:53;;-1:-1:-1;;;1803:53:8;;-1:-1:-1;;;;;1803:9:8;;;;:17;;:53;;1821:10;;1841:4;;-1:-1:-1;;;;;;1803:9:8;1848:7;;;1803:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1772:85;;;;;;1868:9;:24;;-1:-1:-1;;;;;;1868:24:8;-1:-1:-1;;;;;1868:24:8;;;;;;;;1908:42;;1925:10;;1908:42;;-1:-1:-1;;1908:42:8;1523:434;:::o;4686:94:15:-;902:33:8;915:10;927:7;;-1:-1:-1;;;;;;927:7:8;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:8;;;;;;;:::i;:::-;4735:8:15::1;:15:::0;;-1:-1:-1;;4735:15:15::1;4746:4;4735:15;::::0;;4765:8:::1;::::0;::::1;::::0;4735::::1;::::0;4765::::1;4686:94::o:0;8382:1945::-;8580:10;-1:-1:-1;;;;;8602:13:15;8580:36;;8576:109;;8625:60;;-1:-1:-1;;;8625:60:15;;;;;;;;;;;8576:109;8700:19;;;;8695:88;;8728:55;;-1:-1:-1;;;8728:55:15;;;;;;;;;;;8695:88;8841:18;8872:8;;8862:19;;;;;;;:::i;:::-;;;;;;;;8841:40;;8909:19;;8895:10;:33;8891:101;;8937:55;;-1:-1:-1;;;8937:55:15;;;;;;;;;;;8891:101;9081:1;9051:19;:32;;;9131:127;9151:18;;;9131:127;;;9190:57;9228:5;9236:7;;9244:1;9236:10;;;;;;;:::i;:::-;;;;;;;9196:6;;9203:1;9196:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;9190:29:15;;:57;:29;:57::i;:::-;9171:3;;;:::i;:::-;;;9131:127;;;-1:-1:-1;9299:31:15;;;;;9523:77;;;;9534:8;9523:77;:::i;:::-;9615:168;;-1:-1:-1;;;9615:168:15;;9281:319;;-1:-1:-1;9281:319:15;;-1:-1:-1;9281:319:15;;-1:-1:-1;9281:319:15;-1:-1:-1;9281:319:15;-1:-1:-1;9653:4:15;;9615:78;;:168;;9281:319;;;;;;;;;;9615:168;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9267:527;;;;;9911:27;9953:7;;:14;;-1:-1:-1;;;;;9941:27:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9911:57;;9983:9;9978:201;9994:18;;;9978:201;;;-1:-1:-1;;;10123:13:15;10153:10;;10164:1;10153:13;;;;;;;:::i;:::-;;;;;;;10140:7;;10148:1;10140:10;;;;;;;:::i;:::-;;;;;;;:26;;;;:::i;:::-;10067:101;;-1:-1:-1;;;;;25060:32:20;;;10067:101:15;;;25042:51:20;25109:18;;;25102:34;25015:18;;10067:101:15;;;;;;;;;;;;;-1:-1:-1;;;;;10067:101:15;;;;;;;-1:-1:-1;;;;;10067:101:15;;;;;;;;;;;10033:12;10046:1;10033:15;;;;;;;;:::i;:::-;;;;;;:135;;;;10014:3;;;;:::i;:::-;;;9978:201;;;-1:-1:-1;;;;;;10255:5:15;:12;;10268:6;;10276:12;10304:7;-1:-1:-1;;;;;10290:29:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10290:29:15;;10255:65;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;10255:65:15;;;;;;;;;;;;:::i;:::-;;8566:1761;;8382:1945;;;;;;;;:::o;1963:164:8:-;902:33;915:10;927:7;;-1:-1:-1;;;;;;927:7:8;902:12;:33::i;:::-;894:58;;;;-1:-1:-1;;;894:58:8;;;;;;;:::i;:::-;2046:5:::1;:16:::0;;-1:-1:-1;;;;;;2046:16:8::1;-1:-1:-1::0;;;;;2046:16:8;::::1;::::0;;::::1;::::0;;2078:42:::1;::::0;2046:16;;2099:10:::1;::::0;2078:42:::1;::::0;2046:5;2078:42:::1;1963:164:::0;:::o;977:540::-;1097:9;;1064:4;;-1:-1:-1;;;;;1097:9:8;1415:27;;;;;:77;;-1:-1:-1;1446:46:8;;-1:-1:-1;;;1446:46:8;;-1:-1:-1;;;;;1446:12:8;;;;;:46;;1459:4;;1473;;1480:11;;1446:46;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1414:96;;;-1:-1:-1;1505:5:8;;-1:-1:-1;;;;;1497:13:8;;;1505:5;;1497:13;1414:96;1407:103;;;977:540;;;;;:::o;10541:1059:15:-;10852:36;10902:50;10941:10;;10902:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;10902:38:15;;;:50;-1:-1:-1;;10902:38:15;:50::i;:::-;10891:71;;;;;;;;;;;;:::i;:::-;10852:110;;10972:19;10994:43;11026:10;;10994:31;:43::i;:::-;10972:65;-1:-1:-1;;;;;;11051:25:15;;;11047:136;;11135:23;11160:11;11118:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;11092:80;;11047:136;11211:257;11247:17;11282:11;;11311:6;11335:19;11372:5;11395:18;11402:10;;11395:18;:::i;:::-;11431:23;11211:18;:257::i;:::-;11193:401;;11557:6;11565:10;;11577:5;11500:83;;-1:-1:-1;;;11500:83:15;;;;;;;;;;;:::i;11193:401::-;10780:820;;10541:1059;;;;;;;;:::o;2832:1464:12:-;2944:12;3114:4;3108:11;-1:-1:-1;;;3237:17:12;3230:93;-1:-1:-1;;;;;3374:2:12;3370:51;3366:1;3347:17;3343:25;3336:86;3508:6;3503:2;3484:17;3480:26;3473:42;3855:2;3852:1;3848:2;3829:17;3826:1;3819:5;3812;3807:51;3796:62;;;4125:7;4118:2;4100:16;4097:24;4093:1;4089;4083:8;4080:15;4076:46;4069:54;4065:68;4062:172;;;-1:-1:-1;4180:18:12;;4173:26;4201:16;4170:48;4163:56;4062:172;4262:7;4254:35;;;;-1:-1:-1;;;4254:35:12;;27974:2:20;4254:35:12;;;27956:21:20;28013:2;27993:18;;;27986:30;-1:-1:-1;;;28032:18:20;;;28025:45;28087:18;;4254:35:12;27772:339:20;4254:35:12;2934:1362;2832:1464;;;:::o;3521:254:4:-;3607:12;3632;3646:23;3673:6;-1:-1:-1;;;;;3673:17:4;3691:4;3673:23;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3631:65;;;;3713:55;3740:6;3748:7;3757:10;3713:26;:55::i;:::-;3706:62;3521:254;-1:-1:-1;;;;;3521:254:4:o;310:585:14:-;386:14;515:4;550:2;540:12;;536:292;;568:12;591:4;;596:11;605:2;596:6;:11;:::i;:::-;591:18;;;;;:::i;:::-;583:27;;;:::i;:::-;138:24;;;;;;;;;;;;-1:-1:-1;;;138:24:14;;;;;568:42;-1:-1:-1;629:19:14;;;625:193;;772:4;;777:11;786:2;777:6;:11;:::i;:::-;772:29;789:11;798:2;789:6;:11;:::i;:::-;772:29;;;;;;;:::i;:::-;764:38;;;:::i;:::-;756:47;;747:56;;625:193;554:274;536:292;402:493;310:585;;;;:::o;11687:519:15:-;11955:4;11971:17;11999:1;11991:5;:9;11971:29;;12010:12;12064:19;12085:6;12093:12;12107:8;12117:23;12047:94;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;12037:105;;;;;;12010:132;;12159:40;12181:5;;12188:4;12194;12159:21;:40::i;:::-;12152:47;11687:519;-1:-1:-1;;;;;;;;;;;11687:519:15:o;4437:582:4:-;4581:12;4610:7;4605:408;;4633:19;4641:10;4633:7;:19::i;:::-;4605:408;;;4857:17;;:22;:49;;;;-1:-1:-1;;;;;;4883:18:4;;;:23;4857:49;4853:119;;;4933:24;;-1:-1:-1;;;4933:24:4;;-1:-1:-1;;;;;200:32:20;;4933:24:4;;;182:51:20;155:18;;4933:24:4;14:225:20;4853:119:4;-1:-1:-1;4992:10:4;4605:408;4437:582;;;;;:::o;363:1666:11:-;486:12;579;576:1356;;;711:12;708:1;704:20;690:12;686:39;834:12;968:950;1192:20;;1183:30;;;1180:1;1176:38;1476:22;;;1540:2;1526:17;;;1519:47;1689:2;1686:1;1676:16;;1761:15;1874;;;968:950;1864:36;972:2;;576:1356;-1:-1:-1;1957:14:11;;363:1666;-1:-1:-1;;363:1666:11:o;5559:434:4:-;5690:17;;:21;5686:301;;5894:10;5888:17;5881:4;5869:10;5865:21;5858:48;5686:301;5957:19;;-1:-1:-1;;;5957:19:4;;;;;;;;;;;5686:301;5559:434;:::o;244:131:20:-;-1:-1:-1;;;;;319:31:20;;309:42;;299:70;;365:1;362;355:12;380:315;448:6;456;509:2;497:9;488:7;484:23;480:32;477:52;;;525:1;522;515:12;477:52;564:9;551:23;583:31;608:5;583:31;:::i;:::-;633:5;685:2;670:18;;;;657:32;;-1:-1:-1;;;380:315:20:o;700:386::-;782:8;792:6;846:3;839:4;831:6;827:17;823:27;813:55;;864:1;861;854:12;813:55;-1:-1:-1;887:20:20;;-1:-1:-1;;;;;919:30:20;;916:50;;;962:1;959;952:12;916:50;999:4;991:6;987:17;975:29;;1059:3;1052:4;1042:6;1039:1;1035:14;1027:6;1023:27;1019:38;1016:47;1013:67;;;1076:1;1073;1066:12;1013:67;700:386;;;;;:::o;1091:1853::-;1359:6;1367;1375;1383;1391;1399;1407;1415;1423;1431;1484:3;1472:9;1463:7;1459:23;1455:33;1452:53;;;1501:1;1498;1491:12;1452:53;1541:9;1528:23;-1:-1:-1;;;;;1611:2:20;1603:6;1600:14;1597:34;;;1627:1;1624;1617:12;1597:34;1666:89;1747:7;1738:6;1727:9;1723:22;1666:89;:::i;:::-;1774:8;;-1:-1:-1;1640:115:20;-1:-1:-1;1862:2:20;1847:18;;1834:32;;-1:-1:-1;1878:16:20;;;1875:36;;;1907:1;1904;1897:12;1875:36;1946:91;2029:7;2018:8;2007:9;2003:24;1946:91;:::i;:::-;2056:8;;-1:-1:-1;1920:117:20;-1:-1:-1;2144:2:20;2129:18;;2116:32;;-1:-1:-1;2160:16:20;;;2157:36;;;2189:1;2186;2179:12;2157:36;2228:91;2311:7;2300:8;2289:9;2285:24;2228:91;:::i;:::-;2338:8;;-1:-1:-1;2202:117:20;-1:-1:-1;2426:2:20;2411:18;;2398:32;;-1:-1:-1;2442:16:20;;;2439:36;;;2471:1;2468;2461:12;2439:36;2510:91;2593:7;2582:8;2571:9;2567:24;2510:91;:::i;:::-;2620:8;;-1:-1:-1;2484:117:20;-1:-1:-1;2708:3:20;2693:19;;2680:33;;-1:-1:-1;2725:16:20;;;2722:36;;;2754:1;2751;2744:12;2722:36;;2793:91;2876:7;2865:8;2854:9;2850:24;2793:91;:::i;:::-;2767:117;;2903:8;2893:18;;;2930:8;2920:18;;;1091:1853;;;;;;;;;;;;;:::o;2949:347::-;3000:8;3010:6;3064:3;3057:4;3049:6;3045:17;3041:27;3031:55;;3082:1;3079;3072:12;3031:55;-1:-1:-1;3105:20:20;;-1:-1:-1;;;;;3137:30:20;;3134:50;;;3180:1;3177;3170:12;3134:50;3217:4;3209:6;3205:17;3193:29;;3269:3;3262:4;3253:6;3245;3241:19;3237:30;3234:39;3231:59;;;3286:1;3283;3276:12;3301:1234;3452:6;3460;3468;3476;3484;3492;3500;3553:3;3541:9;3532:7;3528:23;3524:33;3521:53;;;3570:1;3567;3560:12;3521:53;3609:9;3596:23;3628:31;3653:5;3628:31;:::i;:::-;3678:5;-1:-1:-1;3734:2:20;3719:18;;3706:32;-1:-1:-1;;;;;3787:14:20;;;3784:34;;;3814:1;3811;3804:12;3784:34;3853:89;3934:7;3925:6;3914:9;3910:22;3853:89;:::i;:::-;3961:8;;-1:-1:-1;3827:115:20;-1:-1:-1;4049:2:20;4034:18;;4021:32;;-1:-1:-1;4065:16:20;;;4062:36;;;4094:1;4091;4084:12;4062:36;4133:91;4216:7;4205:8;4194:9;4190:24;4133:91;:::i;:::-;4243:8;;-1:-1:-1;4107:117:20;-1:-1:-1;4331:2:20;4316:18;;4303:32;;-1:-1:-1;4347:16:20;;;4344:36;;;4376:1;4373;4366:12;4344:36;;4415:60;4467:7;4456:8;4445:9;4441:24;4415:60;:::i;:::-;3301:1234;;;;-1:-1:-1;3301:1234:20;;-1:-1:-1;3301:1234:20;;;;4389:86;;-1:-1:-1;;;3301:1234:20:o;4540:247::-;4599:6;4652:2;4640:9;4631:7;4627:23;4623:32;4620:52;;;4668:1;4665;4658:12;4620:52;4707:9;4694:23;4726:31;4751:5;4726:31;:::i;5868:1433::-;6046:6;6054;6062;6070;6078;6086;6094;6102;6155:3;6143:9;6134:7;6130:23;6126:33;6123:53;;;6172:1;6169;6162:12;6123:53;6212:9;6199:23;-1:-1:-1;;;;;6282:2:20;6274:6;6271:14;6268:34;;;6298:1;6295;6288:12;6268:34;6337:89;6418:7;6409:6;6398:9;6394:22;6337:89;:::i;:::-;6445:8;;-1:-1:-1;6311:115:20;-1:-1:-1;6533:2:20;6518:18;;6505:32;;-1:-1:-1;6549:16:20;;;6546:36;;;6578:1;6575;6568:12;6546:36;6617:91;6700:7;6689:8;6678:9;6674:24;6617:91;:::i;:::-;6727:8;;-1:-1:-1;6591:117:20;-1:-1:-1;6815:2:20;6800:18;;6787:32;;-1:-1:-1;6831:16:20;;;6828:36;;;6860:1;6857;6850:12;6828:36;6899:91;6982:7;6971:8;6960:9;6956:24;6899:91;:::i;:::-;7009:8;;-1:-1:-1;6873:117:20;-1:-1:-1;7097:2:20;7082:18;;7069:32;;-1:-1:-1;7113:16:20;;;7110:36;;;7142:1;7139;7132:12;7110:36;;7181:60;7233:7;7222:8;7211:9;7207:24;7181:60;:::i;:::-;5868:1433;;;;-1:-1:-1;5868:1433:20;;-1:-1:-1;5868:1433:20;;;;;;7260:8;-1:-1:-1;;;5868:1433:20:o;7542:336::-;7744:2;7726:21;;;7783:2;7763:18;;;7756:30;-1:-1:-1;;;7817:2:20;7802:18;;7795:42;7869:2;7854:18;;7542:336::o;8136:184::-;8206:6;8259:2;8247:9;8238:7;8234:23;8230:32;8227:52;;;8275:1;8272;8265:12;8227:52;-1:-1:-1;8298:16:20;;8136:184;-1:-1:-1;8136:184:20:o;8325:127::-;8386:10;8381:3;8377:20;8374:1;8367:31;8417:4;8414:1;8407:15;8441:4;8438:1;8431:15;8457:545;8550:4;8556:6;8616:11;8603:25;8710:2;8706:7;8695:8;8679:14;8675:29;8671:43;8651:18;8647:68;8637:96;;8729:1;8726;8719:12;8637:96;8756:33;;8808:20;;;-1:-1:-1;;;;;;8840:30:20;;8837:50;;;8883:1;8880;8873:12;8837:50;8916:4;8904:17;;-1:-1:-1;8967:1:20;8963:14;;;8947;8943:35;8933:46;;8930:66;;;8992:1;8989;8982:12;9007:521;9084:4;9090:6;9150:11;9137:25;9244:2;9240:7;9229:8;9213:14;9209:29;9205:43;9185:18;9181:68;9171:96;;9263:1;9260;9253:12;9171:96;9290:33;;9342:20;;;-1:-1:-1;;;;;;9374:30:20;;9371:50;;;9417:1;9414;9407:12;9371:50;9450:4;9438:17;;-1:-1:-1;9481:14:20;9477:27;;;9467:38;;9464:58;;;9518:1;9515;9508:12;9533:266;9621:6;9616:3;9609:19;9673:6;9666:5;9659:4;9654:3;9650:14;9637:43;-1:-1:-1;9725:1:20;9700:16;;;9718:4;9696:27;;;9689:38;;;;9781:2;9760:15;;;-1:-1:-1;;9756:29:20;9747:39;;;9743:50;;9533:266::o;9804:412::-;-1:-1:-1;;;;;10017:32:20;;9999:51;;10086:2;10081;10066:18;;10059:30;;;-1:-1:-1;;10106:61:20;;10148:18;;10140:6;10132;10106:61;:::i;:::-;10098:69;;10203:6;10198:2;10187:9;10183:18;10176:34;9804:412;;;;;;;:::o;10221:127::-;10282:10;10277:3;10273:20;10270:1;10263:31;10313:4;10310:1;10303:15;10337:4;10334:1;10327:15;10353:275;10424:2;10418:9;10489:2;10470:13;;-1:-1:-1;;10466:27:20;10454:40;;-1:-1:-1;;;;;10509:34:20;;10545:22;;;10506:62;10503:88;;;10571:18;;:::i;:::-;10607:2;10600:22;10353:275;;-1:-1:-1;10353:275:20:o;10633:186::-;10681:4;-1:-1:-1;;;;;10706:6:20;10703:30;10700:56;;;10736:18;;:::i;:::-;-1:-1:-1;10802:2:20;10781:15;-1:-1:-1;;10777:29:20;10808:4;10773:40;;10633:186::o;10824:250::-;10909:1;10919:113;10933:6;10930:1;10927:13;10919:113;;;11009:11;;;11003:18;10990:11;;;10983:39;10955:2;10948:10;10919:113;;;-1:-1:-1;;11066:1:20;11048:16;;11041:27;10824:250::o;11079:441::-;11132:5;11185:3;11178:4;11170:6;11166:17;11162:27;11152:55;;11203:1;11200;11193:12;11152:55;11232:6;11226:13;11263:48;11279:31;11307:2;11279:31;:::i;:::-;11263:48;:::i;:::-;11336:2;11327:7;11320:19;11382:3;11375:4;11370:2;11362:6;11358:15;11354:26;11351:35;11348:55;;;11399:1;11396;11389:12;11348:55;11412:77;11486:2;11479:4;11470:7;11466:18;11459:4;11451:6;11447:17;11412:77;:::i;:::-;11507:7;11079:441;-1:-1:-1;;;;11079:441:20:o;11525:335::-;11604:6;11657:2;11645:9;11636:7;11632:23;11628:32;11625:52;;;11673:1;11670;11663:12;11625:52;11706:9;11700:16;-1:-1:-1;;;;;11731:6:20;11728:30;11725:50;;;11771:1;11768;11761:12;11725:50;11794:60;11846:7;11837:6;11826:9;11822:22;11794:60;:::i;11865:127::-;11926:10;11921:3;11917:20;11914:1;11907:31;11957:4;11954:1;11947:15;11981:4;11978:1;11971:15;11997:135;12036:3;12057:17;;;12054:43;;12077:18;;:::i;:::-;-1:-1:-1;12124:1:20;12113:13;;11997:135::o;12319:271::-;12502:6;12494;12489:3;12476:33;12458:3;12528:16;;12553:13;;;12528:16;12319:271;-1:-1:-1;12319:271:20:o;12595:522::-;12695:6;12690:3;12683:19;12665:3;12721:4;12750:2;12745:3;12741:12;12734:19;;12776:5;12799:1;12809:283;12823:6;12820:1;12817:13;12809:283;;;12900:6;12887:20;12920:33;12945:7;12920:33;:::i;:::-;-1:-1:-1;;;;;12978:33:20;12966:46;;13032:12;;;;13067:15;;;;13008:1;12838:9;12809:283;;;-1:-1:-1;13108:3:20;;12595:522;-1:-1:-1;;;;;12595:522:20:o;13122:951::-;-1:-1:-1;;;;;13483:32:20;;13465:51;;13552:3;13547:2;13532:18;;13525:31;;;-1:-1:-1;;13579:74:20;;13633:19;;13625:6;13617;13579:74;:::i;:::-;13689:22;;;13684:2;13669:18;;13662:50;13721:22;;;-1:-1:-1;;;;;13755:31:20;;13752:51;;;13799:1;13796;13789:12;13752:51;13833:6;13830:1;13826:14;13887:6;13879;13874:2;13866:6;13862:15;13849:45;13913:19;13972:18;;;13992:2;13968:27;;;13963:2;13948:18;;13941:55;14013:54;;14055:11;;14047:6;14039;14013:54;:::i;:::-;14005:62;13122:951;-1:-1:-1;;;;;;;;;;13122:951:20:o;14078:400::-;-1:-1:-1;;;;;14334:15:20;;;14316:34;;14386:15;;;;14381:2;14366:18;;14359:43;-1:-1:-1;;;;;;14438:33:20;;;14433:2;14418:18;;14411:61;14266:2;14251:18;;14078:400::o;14483:277::-;14550:6;14603:2;14591:9;14582:7;14578:23;14574:32;14571:52;;;14619:1;14616;14609:12;14571:52;14651:9;14645:16;14704:5;14697:13;14690:21;14683:5;14680:32;14670:60;;14726:1;14723;14716:12;14765:193;14835:4;-1:-1:-1;;;;;14860:6:20;14857:30;14854:56;;;14890:18;;:::i;:::-;-1:-1:-1;14935:1:20;14931:14;14947:4;14927:25;;14765:193::o;14963:1725::-;15027:5;15080:3;15073:4;15065:6;15061:17;15057:27;15047:55;;15098:1;15095;15088:12;15047:55;15134:6;15121:20;15160:4;15184:70;15200:53;15250:2;15200:53;:::i;15184:70::-;15288:15;;;15350:1;15390:11;;;15378:24;;15374:33;;;15319:12;;;;15276:3;15419:15;;;15416:35;;;15447:1;15444;15437:12;15416:35;15483:2;15475:6;15471:15;15495:1164;15511:6;15506:3;15503:15;15495:1164;;;15597:3;15584:17;-1:-1:-1;;;;;15620:11:20;15617:35;15614:125;;;15693:1;15722:2;15718;15711:14;15614:125;15762:24;;15821:2;15813:11;;15809:21;-1:-1:-1;15799:119:20;;15872:1;15901:2;15897;15890:14;15799:119;15962:2;15958;15954:11;15941:25;15989:2;16017:70;16033:53;16083:2;16033:53;:::i;16017:70::-;16131:17;;;16225:11;;;16217:20;;16213:29;;;16170:14;;;;16258:17;;;16255:107;;;16316:1;16345:2;16341;16334:14;16255:107;16388:11;;;;16412:174;16430:8;16423:5;16420:19;16412:174;;;16512:19;;16498:34;;16451:14;;;;16558;;;;16412:174;;;16599:18;;-1:-1:-1;;;16637:12:20;;;;-1:-1:-1;15528:12:20;;15495:1164;;;-1:-1:-1;16677:5:20;;14963:1725;-1:-1:-1;;;;;;;14963:1725:20:o;16693:747::-;16747:5;16800:3;16793:4;16785:6;16781:17;16777:27;16767:55;;16818:1;16815;16808:12;16767:55;16854:6;16841:20;16880:4;16904:70;16920:53;16970:2;16920:53;:::i;16904:70::-;17008:15;;;17094:1;17090:10;;;;17078:23;;17074:32;;;17039:12;;;;17118:15;;;17115:35;;;17146:1;17143;17136:12;17115:35;17182:2;17174:6;17170:15;17194:217;17210:6;17205:3;17202:15;17194:217;;;17290:3;17277:17;17307:31;17332:5;17307:31;:::i;:::-;17351:18;;17389:12;;;;17227;;17194:217;;;-1:-1:-1;17429:5:20;16693:747;-1:-1:-1;;;;;;16693:747:20:o;17445:1448::-;17497:5;17550:3;17543:4;17535:6;17531:17;17527:27;17517:55;;17568:1;17565;17558:12;17517:55;17604:6;17591:20;17630:4;17654:70;17670:53;17720:2;17670:53;:::i;17654:70::-;17758:15;;;17844:1;17840:10;;;;17828:23;;17824:32;;;17789:12;;;;17868:15;;;17865:35;;;17896:1;17893;17886:12;17865:35;17932:2;17924:6;17920:15;17944:920;17960:6;17955:3;17952:15;17944:920;;;18046:3;18033:17;-1:-1:-1;;;;;18069:11:20;18066:35;18063:125;;;18142:1;18171:2;18167;18160:14;18063:125;18211:24;;18270:2;18262:11;;18258:21;-1:-1:-1;18248:119:20;;18321:1;18350:2;18346;18339:14;18248:119;18411:2;18407;18403:11;18390:25;18438:2;18468:48;18484:31;18512:2;18484:31;:::i;18468:48::-;18545:2;18536:7;18529:19;18589:3;18584:2;18579;18575;18571:11;18567:20;18564:29;18561:119;;;18634:1;18663:2;18659;18652:14;18561:119;18737:2;18732;18728;18724:11;18719:2;18710:7;18706:16;18693:47;18787:1;18764:16;;;18760:25;;18753:36;;;;-1:-1:-1;18802:20:20;;-1:-1:-1;18842:12:20;;;;17977;;17944:920;;18898:672;18952:5;19005:3;18998:4;18990:6;18986:17;18982:27;18972:55;;19023:1;19020;19013:12;18972:55;19059:6;19046:20;19085:4;19109:70;19125:53;19175:2;19125:53;:::i;19109:70::-;19213:15;;;19299:1;19295:10;;;;19283:23;;19279:32;;;19244:12;;;;19323:15;;;19320:35;;;19351:1;19348;19341:12;19320:35;19387:2;19379:6;19375:15;19399:142;19415:6;19410:3;19407:15;19399:142;;;19481:17;;19469:30;;19519:12;;;;19432;;19399:142;;19575:1317;19829:6;19837;19845;19853;19861;19914:3;19902:9;19893:7;19889:23;19885:33;19882:53;;;19931:1;19928;19921:12;19882:53;19971:9;19958:23;-1:-1:-1;;;;;20041:2:20;20033:6;20030:14;20027:34;;;20057:1;20054;20047:12;20027:34;20080:71;20143:7;20134:6;20123:9;20119:22;20080:71;:::i;:::-;20070:81;;20204:2;20193:9;20189:18;20176:32;20160:48;;20233:2;20223:8;20220:16;20217:36;;;20249:1;20246;20239:12;20217:36;20272:63;20327:7;20316:8;20305:9;20301:24;20272:63;:::i;:::-;20262:73;;20388:2;20377:9;20373:18;20360:32;20344:48;;20417:2;20407:8;20404:16;20401:36;;;20433:1;20430;20423:12;20401:36;20456:63;20511:7;20500:8;20489:9;20485:24;20456:63;:::i;:::-;20446:73;;20572:2;20561:9;20557:18;20544:32;20528:48;;20601:2;20591:8;20588:16;20585:36;;;20617:1;20614;20607:12;20585:36;20640:61;20693:7;20682:8;20671:9;20667:24;20640:61;:::i;:::-;20630:71;;20754:3;20743:9;20739:19;20726:33;20710:49;;20784:2;20774:8;20771:16;20768:36;;;20800:1;20797;20790:12;20768:36;;20823:63;20878:7;20867:8;20856:9;20852:24;20823:63;:::i;:::-;20813:73;;;19575:1317;;;;;;;;:::o;20897:461::-;20950:3;20988:5;20982:12;21015:6;21010:3;21003:19;21041:4;21070:2;21065:3;21061:12;21054:19;;21107:2;21100:5;21096:14;21128:1;21138:195;21152:6;21149:1;21146:13;21138:195;;;21217:13;;-1:-1:-1;;;;;21213:39:20;21201:52;;21273:12;;;;21308:15;;;;21249:1;21167:9;21138:195;;21363:822;21414:3;21452:5;21446:12;21479:6;21474:3;21467:19;21505:4;21546:2;21541:3;21537:12;21571:11;21598;21591:18;;21648:6;21645:1;21641:14;21634:5;21630:26;21618:38;;21690:2;21683:5;21679:14;21711:1;21721:438;21735:6;21732:1;21729:13;21721:438;;;21806:5;21800:4;21796:16;21791:3;21784:29;21842:6;21836:13;21884:2;21878:9;21913:8;21907:4;21900:22;21935:72;21998:8;21993:2;21987:4;21983:13;21978:2;21974;21970:11;21935:72;:::i;:::-;22137:12;;;;22069:2;22046:17;-1:-1:-1;;22042:31:20;22032:42;;;;22028:51;;;-1:-1:-1;22102:15:20;;;;21757:1;21750:9;21721:438;;;-1:-1:-1;22175:4:20;;21363:822;-1:-1:-1;;;;;;;21363:822:20:o;22190:435::-;22243:3;22281:5;22275:12;22308:6;22303:3;22296:19;22334:4;22363:2;22358:3;22354:12;22347:19;;22400:2;22393:5;22389:14;22421:1;22431:169;22445:6;22442:1;22439:13;22431:169;;;22506:13;;22494:26;;22540:12;;;;22575:15;;;;22467:1;22460:9;22431:169;;22630:2103;23152:4;23200:3;23189:9;23185:19;23231:3;23220:9;23213:22;23255:6;23290;23284:13;23321:6;23313;23306:22;23359:3;23348:9;23344:19;23337:26;;23422:3;23412:6;23409:1;23405:14;23394:9;23390:30;23386:40;23372:54;;23445:4;23484:2;23476:6;23472:15;23505:1;23526;23536:694;23552:6;23547:3;23544:15;23536:694;;;23621:22;;;-1:-1:-1;;23617:37:20;23605:50;;23678:13;;23752:9;;23774:24;;;23864:11;;;;23820:15;;;;23899:1;23913:209;23929:8;23924:3;23921:17;23913:209;;;24006:15;;23992:30;;24091:17;;;;24048:14;;;;23957:1;23948:11;23913:209;;;-1:-1:-1;24145:5:20;;-1:-1:-1;;;24208:12:20;;;;24173:15;;;;23578:1;23569:11;23536:694;;;23540:3;;;24278:9;24270:6;24266:22;24261:2;24250:9;24246:18;24239:50;;;;24312:44;24349:6;24341;24312:44;:::i;:::-;24298:58;;24404:9;24396:6;24392:22;24387:2;24376:9;24372:18;24365:50;24438:44;24475:6;24467;24438:44;:::i;:::-;24424:58;;24530:9;24522:6;24518:22;24513:2;24502:9;24498:18;24491:50;24564:42;24599:6;24591;24564:42;:::i;:::-;24550:56;;24655:9;24647:6;24643:22;24637:3;24626:9;24622:19;24615:51;24683:44;24720:6;24712;24683:44;:::i;:::-;24675:52;22630:2103;-1:-1:-1;;;;;;;;22630:2103:20:o;24738:125::-;24803:9;;;24824:10;;;24821:36;;;24837:18;;:::i;25147:712::-;25510:2;25499:9;25492:21;25473:4;25536:73;25605:2;25594:9;25590:18;25582:6;25574;25536:73;:::i;:::-;25657:9;25649:6;25645:22;25640:2;25629:9;25625:18;25618:50;25691:42;25726:6;25718;25691:42;:::i;:::-;25677:56;;25781:9;25773:6;25769:22;25764:2;25753:9;25749:18;25742:50;25809:44;25846:6;25838;25809:44;:::i;:::-;25801:52;25147:712;-1:-1:-1;;;;;;;25147:712:20:o;25864:1142::-;25968:6;25999:2;26042;26030:9;26021:7;26017:23;26013:32;26010:52;;;26058:1;26055;26048:12;26010:52;26091:9;26085:16;-1:-1:-1;;;;;26161:2:20;26153:6;26150:14;26147:34;;;26177:1;26174;26167:12;26147:34;26215:6;26204:9;26200:22;26190:32;;26260:7;26253:4;26249:2;26245:13;26241:27;26231:55;;26282:1;26279;26272:12;26231:55;26311:2;26305:9;26334:70;26350:53;26400:2;26350:53;:::i;26334:70::-;26438:15;;;26520:1;26516:10;;;;26508:19;;26504:28;;;26469:12;;;;26544:19;;;26541:39;;;26576:1;26573;26566:12;26541:39;26608:2;26604;26600:11;26620:356;26636:6;26631:3;26628:15;26620:356;;;26715:3;26709:10;26751:2;26738:11;26735:19;26732:109;;;26795:1;26824:2;26820;26813:14;26732:109;26866:67;26925:7;26920:2;26906:11;26902:2;26898:20;26894:29;26866:67;:::i;:::-;26854:80;;-1:-1:-1;26954:12:20;;;;26653;;26620:356;;;-1:-1:-1;26995:5:20;25864:1142;-1:-1:-1;;;;;;;;25864:1142:20:o;27011:428::-;27168:3;27206:6;27200:13;27222:66;27281:6;27276:3;27269:4;27261:6;27257:17;27222:66;:::i;:::-;27357:2;27353:15;;;;-1:-1:-1;;;;;;27349:53:20;27310:16;;;;27335:68;;;27430:2;27419:14;;27011:428;-1:-1:-1;;27011:428:20:o;27444:323::-;-1:-1:-1;;;;;;27564:19:20;;27640:11;;;;27671:1;27663:10;;27660:101;;;27732:1;27728:11;;;;27725:1;27721:19;27717:28;;;27709:37;27705:46;;;;27444:323;-1:-1:-1;;27444:323:20:o;28116:287::-;28245:3;28283:6;28277:13;28299:66;28358:6;28353:3;28346:4;28338:6;28334:17;28299:66;:::i;:::-;28381:16;;;;;28116:287;-1:-1:-1;;28116:287:20:o;28408:128::-;28475:9;;;28496:11;;;28493:37;;;28510:18;;:::i;28541:331::-;28646:9;28657;28699:8;28687:10;28684:24;28681:44;;;28721:1;28718;28711:12;28681:44;28750:6;28740:8;28737:20;28734:40;;;28770:1;28767;28760:12;28734:40;-1:-1:-1;;28796:23:20;;;28841:25;;;;;-1:-1:-1;28541:331:20:o;28877:255::-;28997:19;;29036:2;29028:11;;29025:101;;;-1:-1:-1;;29097:2:20;29093:12;;;29090:1;29086:20;29082:33;29071:45;28877:255;;;;:::o;29137:337::-;-1:-1:-1;;;;;;29258:19:20;;29345:11;;;;29376:2;29368:11;;29365:103;;;29438:2;29434:12;;;;29431:1;29427:20;29423:29;;;29415:38;29411:47;;;;29137:337;-1:-1:-1;;29137:337:20:o;29479:687::-;-1:-1:-1;;;;;;29800:2:20;29796:15;;;29792:24;;29780:37;;29851:15;;;29847:24;29842:2;29833:12;;29826:46;29918:14;;29911:22;29906:3;29902:32;29897:2;29888:12;;29881:54;-1:-1:-1;;;;;;29965:33:20;;29960:2;29951:12;;29944:55;30022:13;;-1:-1:-1;;30044:75:20;30022:13;30107:2;30098:12;;30091:4;30079:17;;30044:75;:::i;:::-;30139:16;;;;30157:2;30135:25;;29479:687;-1:-1:-1;;;;;;29479:687:20:o
Swarm Source
ipfs://8a54c2671d4e4f5079bf5876eb683638ceb02c1ca2acb018c33520f248d6a851
Loading...
Loading
Loading...
Loading

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.