Overview
S Balance
0 S
S Value
-More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
618964 | 2 days ago | Contract Creation | 0 S |
Loading...
Loading
Contract Name:
ManagerWithMerkleVerification
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
london EvmVersion
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: 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: 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: 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; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: 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: 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: UNLICENSED pragma solidity 0.8.21; interface IPausable { function pause() external; function unpause() external; }
// 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: 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.0.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 ERC1155 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 { /** * @dev See {IERC165-supportsInterface}. */ 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: 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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 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) (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 ERC165 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 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.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 ERC1155 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 ERC1155 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.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "remappings": [ "@solmate/=lib/solmate/src/", "@forge-std/=lib/forge-std/src/", "@ds-test/=lib/forge-std/lib/ds-test/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "@openzeppelin/=lib/openzeppelin-contracts/", "@ccip/=lib/ccip/", "@oapp-auth/=lib/OAppAuth/src/", "@devtools-oapp-evm/=lib/OAppAuth/lib/devtools/packages/oapp-evm/contracts/oapp/", "@layerzerolabs/lz-evm-messagelib-v2/=lib/OAppAuth/node_modules/@layerzerolabs/lz-evm-messagelib-v2/", "@layerzerolabs/lz-evm-protocol-v2/=lib/OAppAuth/lib/LayerZero-V2/packages/layerzero-v2/evm/protocol/", "@layerzerolabs/oapp-evm/=lib/OAppAuth/lib/devtools/packages/oapp-evm/", "@lz-oapp-evm/=lib/OAppAuth/lib/LayerZero-V2/packages/layerzero-v2/evm/oapp/contracts/oapp/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@sbu/=lib/OAppAuth/lib/solidity-bytes-utils/", "LayerZero-V2/=lib/OAppAuth/lib/", "OAppAuth/=lib/OAppAuth/", "ccip/=lib/ccip/contracts/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/OAppAuth/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solidity-bytes-utils/=lib/OAppAuth/node_modules/solidity-bytes-utils/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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":"FailedInnerCall","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
60c060405260006004553480156200001657600080fd5b5060405162002312380380620023128339810160408190526200003991620000fd565b600080546001600160a01b0385166001600160a01b031991821681178355600180549092169091556040518592919033907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908490a36040516001600160a01b0382169033907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350506001600160a01b039182166080521660a0525062000147565b80516001600160a01b0381168114620000f857600080fd5b919050565b6000806000606084860312156200011357600080fd5b6200011e84620000e0565b92506200012e60208501620000e0565b91506200013e60408501620000e0565b90509250925092565b60805160a051612167620001ab6000396000818160f4015281816107fb015281816109ff0152610c1c01526000818161022d015281816103e6015281816105200152818161062b0152818161077e01528181610ab30152610cfe01526121676000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638456cb591161008c578063bf7e214f11610066578063bf7e214f146101ef578063f04f270714610202578063f2fde38b14610215578063fbfa77cf1461022857600080fd5b80638456cb59146101b75780638da5cb5b146101bf578063b187bd26146101d257600080fd5b80633f4ba83a116100c85780633f4ba83a1461015b5780635c38449e146101635780635ca58a99146101765780637a9e5e4b146101a457600080fd5b8063158274a5146100ef57806321801a9914610133578063244b0f6a14610148575b600080fd5b6101167f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6101466101413660046112db565b61024f565b005b610146610156366004611352565b6102e9565b61014661070c565b610146610171366004611483565b610773565b61019661018436600461152f565b60026020526000908152604090205481565b60405190815260200161012a565b6101466101b236600461152f565b6108a0565b61014661098a565b600054610116906001600160a01b031681565b6005546101df9060ff1681565b604051901515815260200161012a565b600154610116906001600160a01b031681565b61014661021036600461154c565b6109f4565b61014661022336600461152f565b610ddb565b6101167f000000000000000000000000000000000000000000000000000000000000000081565b610265336000356001600160e01b031916610e58565b61028a5760405162461bcd60e51b81526004016102819061160f565b60405180910390fd5b6001600160a01b038216600081815260026020908152604091829020805490859055825181815291820185905292917f0b958dec85f1470000479dfb22c365829411f52bcde602d24ea0abf5ac7e8860910160405180910390a2505050565b6102ff336000356001600160e01b031916610e58565b61031b5760405162461bcd60e51b81526004016102819061160f565b60055460ff161561033f57604051631b7b196560e31b815260040160405180910390fd5b848981146103605760405163029c70cf60e41b815260040160405180910390fd5b8084146103805760405163581ddbfd60e01b815260040160405180910390fd5b8082146103a05760405163e9fd1adf60e01b815260040160405180910390fd5b8088146103c057604051631b4d824d60e31b815260040160405180910390fd5b3360009081526002602090815260408083205481516318160ddd60e01b815291519093927f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316926318160ddd92600480830193928290030181865afa158015610435573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104599190611635565b905060005b838110156106285761051e838f8f8481811061047c5761047c61164e565b905060200281019061048e9190611664565b8f8f868181106104a0576104a061164e565b90506020020160208101906104b5919061152f565b8e8e878181106104c7576104c761164e565b90506020020160208101906104dc919061152f565b8b8b888181106104ee576104ee61164e565b905060200201358e8e898181106105075761050761164e565b905060200281019061051991906116ad565b610f04565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f6e715d08b8b8481811061055f5761055f61164e565b9050602002016020810190610574919061152f565b8a8a858181106105865761058661164e565b905060200281019061059891906116ad565b8a8a878181106105aa576105aa61164e565b905060200201356040518563ffffffff1660e01b81526004016105d0949392919061171c565b6000604051808303816000875af11580156105ef573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106179190810190611835565b506106218161187f565b905061045e565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610687573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ab9190611635565b81146106ca57604051630ecee17560e01b815260040160405180910390fd5b6040518381527f53d426e7d80bb2c8674d3b45577e2d464d423faad6531b21f95ac11ac18b1cb69060200160405180910390a150505050505050505050505050565b610722336000356001600160e01b031916610e58565b61073e5760405162461bcd60e51b81526004016102819061160f565b6005805460ff191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107bc576040516377ed816560e01b815260040160405180910390fd5b81816040516107cc929190611898565b60405190819003812060049081556003805460ff19166001179055632e1c224f60e11b82526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691635c38449e9161083a918b918b918b918b918b918b918b91016118f1565b600060405180830381600087803b15801561085457600080fd5b505af1158015610868573d6000803e3d6000fd5b50506003805460ff1916905550506004541561089757604051633de6ce8160e21b815260040160405180910390fd5b50505050505050565b6000546001600160a01b0316331480610935575060015460405163b700961360e01b81526001600160a01b039091169063b7009613906108f490339030906001600160e01b03196000351690600401611969565b602060405180830381865afa158015610911573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109359190611996565b61093e57600080fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b6109a0336000356001600160e01b031916610e58565b6109bc5760405162461bcd60e51b81526004016102819061160f565b6005805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a3d5760405163a38bce7f60e01b815260040160405180910390fd5b60035460ff16610a60576040516326e6e2c760e01b815260040160405180910390fd5b60008282604051610a72929190611898565b604051809103902090506004548114610a9e57604051631663f61360e01b815260040160405180910390fd5b600060048190555b86811015610b3257610b227f0000000000000000000000000000000000000000000000000000000000000000898984818110610ae457610ae461164e565b905060200201358c8c85818110610afd57610afd61164e565b9050602002016020810190610b12919061152f565b6001600160a01b03169190610ff1565b610b2b8161187f565b9050610aa6565b50600080808080610b4587890189611c43565b60405163122587b560e11b815294995092975090955093509150309063244b0f6a90610b7d9088908890889088908890600401611dea565b600060405180830381600087803b158015610b9757600080fd5b505af1158015610bab573d6000803e3d6000fd5b5050505050505050506000878790506001600160401b03811115610bd157610bd1611752565b604051908082528060200260200182016040528015610c0457816020015b6060815260200190600190039081610bef5790505b50905060005b87811015610cf35763a9059cbb60e01b7f0000000000000000000000000000000000000000000000000000000000000000888884818110610c4d57610c4d61164e565b905060200201358b8b85818110610c6657610c6661164e565b90506020020135610c779190611ec7565b6040516001600160a01b0390921660248301526044820152606401604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050828281518110610cd757610cd761164e565b602002602001018190525080610cec9061187f565b9050610c0a565b506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663224d87038b8b848b6001600160401b03811115610d3e57610d3e611752565b604051908082528060200260200182016040528015610d67578160200160208202803683370190505b506040518563ffffffff1660e01b8152600401610d879493929190611eda565b6000604051808303816000875af1158015610da6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dce9190810190611f1f565b5050505050505050505050565b610df1336000356001600160e01b031916610e58565b610e0d5760405162461bcd60e51b81526004016102819061160f565b600080546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b6001546000906001600160a01b03168015801590610ee2575060405163b700961360e01b81526001600160a01b0382169063b700961390610ea190879030908890600401611969565b602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190611996565b80610efa57506000546001600160a01b038581169116145b9150505b92915050565b6000610f5083838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506001600160a01b038a1692915050611078565b806020019051810190610f639190611835565b90506000610f7184846110ee565b90506001600160a01b03811615610fa7578181604051602001610f95929190611fcf565b60405160208183030381529060405291505b610fc08a8a8a898b8a610fba8a8c612001565b896111aa565b610fe5578584848760405163c0dcd1a760e01b8152600401610281949392919061171c565b50505050505050505050565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806110725760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610281565b50505050565b6060600080846001600160a01b031684604051611095919061202f565b600060405180830381855afa9150503d80600081146110d0576040519150601f19603f3d011682016040523d82523d6000602084013e6110d5565b606091505b50915091506110e5858383611201565b95945050505050565b600081604481106111a3576000848461110860208561204b565b61111392829061205e565b61111c91612088565b60408051808201909152600f81526e111c9bdb99531a588b9d185c99d95d608a1b60209091015290507fc1b9dfe6c6d6343c26291b77edfcc5dbc62c3afa2ee72581da4e3cdbe96a0a4f81016111a157848461117960348561204b565b9061118560208661204b565b926111929392919061205e565b61119b916120a6565b60601c92505b505b5092915050565b600080600085119050600086888387876040516020016111ce9594939291906120d4565b6040516020818303038152906040528051906020012090506111f28a8a8d84611260565b9b9a5050505050505050505050565b606082611216576112118261129a565b611259565b815115801561122d57506001600160a01b0384163b155b1561125657604051639996b31560e01b81526001600160a01b0385166004820152602401610281565b50805b9392505050565b60008315611292578360051b8501855b803580851160051b948552602094851852604060002093018181106112705750505b501492915050565b8051156112aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b03811681146112c357600080fd5b600080604083850312156112ee57600080fd5b82356112f9816112c6565b946020939093013593505050565b60008083601f84011261131957600080fd5b5081356001600160401b0381111561133057600080fd5b6020830191508360208260051b850101111561134b57600080fd5b9250929050565b60008060008060008060008060008060a08b8d03121561137157600080fd5b8a356001600160401b038082111561138857600080fd5b6113948e838f01611307565b909c509a5060208d01359150808211156113ad57600080fd5b6113b98e838f01611307565b909a50985060408d01359150808211156113d257600080fd5b6113de8e838f01611307565b909850965060608d01359150808211156113f757600080fd5b6114038e838f01611307565b909650945060808d013591508082111561141c57600080fd5b506114298d828e01611307565b915080935050809150509295989b9194979a5092959850565b60008083601f84011261145457600080fd5b5081356001600160401b0381111561146b57600080fd5b60208301915083602082850101111561134b57600080fd5b60008060008060008060006080888a03121561149e57600080fd5b87356114a9816112c6565b965060208801356001600160401b03808211156114c557600080fd5b6114d18b838c01611307565b909850965060408a01359150808211156114ea57600080fd5b6114f68b838c01611307565b909650945060608a013591508082111561150f57600080fd5b5061151c8a828b01611442565b989b979a50959850939692959293505050565b60006020828403121561154157600080fd5b8135611259816112c6565b6000806000806000806000806080898b03121561156857600080fd5b88356001600160401b038082111561157f57600080fd5b61158b8c838d01611307565b909a50985060208b01359150808211156115a457600080fd5b6115b08c838d01611307565b909850965060408b01359150808211156115c957600080fd5b6115d58c838d01611307565b909650945060608b01359150808211156115ee57600080fd5b506115fb8b828c01611442565b999c989b5096995094979396929594505050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b60006020828403121561164757600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261167b57600080fd5b8301803591506001600160401b0382111561169557600080fd5b6020019150600581901b360382131561134b57600080fd5b6000808335601e198436030181126116c457600080fd5b8301803591506001600160401b038211156116de57600080fd5b60200191503681900382131561134b57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038516815260606020820181905260009061174190830185876116f3565b905082604083015295945050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561179057611790611752565b604052919050565b60006001600160401b038211156117b1576117b1611752565b50601f01601f191660200190565b60005b838110156117da5781810151838201526020016117c2565b50506000910152565b600082601f8301126117f457600080fd5b815161180761180282611798565b611768565b81815284602083860101111561181c57600080fd5b61182d8260208301602087016117bf565b949350505050565b60006020828403121561184757600080fd5b81516001600160401b0381111561185d57600080fd5b610efa848285016117e3565b634e487b7160e01b600052601160045260246000fd5b60006001820161189157611891611869565b5060010190565b8183823760009101908152919050565b8183526000602080850194508260005b858110156118e65781356118cb816112c6565b6001600160a01b0316875295820195908201906001016118b8565b509495945050505050565b6001600160a01b0388168152608060208201819052600090611916908301888a6118a8565b82810360408401528581526001600160fb1b0386111561193557600080fd5b8560051b80886020840137018281036020908101606085015261195b90820185876116f3565b9a9950505050505050505050565b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b6000602082840312156119a857600080fd5b8151801515811461125957600080fd5b60006001600160401b038211156119d1576119d1611752565b5060051b60200190565b600082601f8301126119ec57600080fd5b813560206119fc611802836119b8565b828152600592831b8501820192828201919087851115611a1b57600080fd5b8387015b85811015611aae5780356001600160401b03811115611a3e5760008081fd5b8801603f81018a13611a505760008081fd5b858101356040611a62611802836119b8565b82815291851b8301810191888101908d841115611a7f5760008081fd5b938201935b83851015611a9d57843582529389019390890190611a84565b885250505093850193508401611a1f565b5090979650505050505050565b600082601f830112611acc57600080fd5b81356020611adc611802836119b8565b82815260059290921b84018101918181019086841115611afb57600080fd5b8286015b84811015611b1f578035611b12816112c6565b8352918301918301611aff565b509695505050505050565b600082601f830112611b3b57600080fd5b81356020611b4b611802836119b8565b82815260059290921b84018101918181019086841115611b6a57600080fd5b8286015b84811015611b1f5780356001600160401b03811115611b8d5760008081fd5b8701603f81018913611b9f5760008081fd5b848101356040611bb161180283611798565b8281528b82848601011115611bc65760008081fd5b8282850189830137600092810188019290925250845250918301918301611b6e565b600082601f830112611bf957600080fd5b81356020611c09611802836119b8565b82815260059290921b84018101918181019086841115611c2857600080fd5b8286015b84811015611b1f5780358352918301918301611c2c565b600080600080600060a08688031215611c5b57600080fd5b85356001600160401b0380821115611c7257600080fd5b611c7e89838a016119db565b96506020880135915080821115611c9457600080fd5b611ca089838a01611abb565b95506040880135915080821115611cb657600080fd5b611cc289838a01611abb565b94506060880135915080821115611cd857600080fd5b611ce489838a01611b2a565b93506080880135915080821115611cfa57600080fd5b50611d0788828901611be8565b9150509295509295909350565b600081518084526020808501945080840160005b838110156118e65781516001600160a01b031687529582019590820190600101611d28565b600081518084526020808501808196508360051b8101915082860160005b85811015611dad57828403895281518051808652611d8e818888018985016117bf565b99860199601f01601f1916949094018501935090840190600101611d6b565b5091979650505050505050565b600081518084526020808501945080840160005b838110156118e657815187529582019590820190600101611dce565b600060a0820160a0835280885180835260c08501915060c08160051b86010192506020808b016000805b84811015611e685788870360bf19018652825180518089529085019085890190845b81811015611e5257835183529287019291870191600101611e36565b5090985050509483019491830191600101611e14565b50505085840381870152505050611e7f8188611d14565b90508281036040840152611e938187611d14565b90508281036060840152611ea78186611d4d565b90508281036080840152611ebb8185611dba565b98975050505050505050565b80820180821115610efe57610efe611869565b606081526000611eee6060830186886118a8565b8281036020840152611f008186611d4d565b90508281036040840152611f148185611dba565b979650505050505050565b60006020808385031215611f3257600080fd5b82516001600160401b0380821115611f4957600080fd5b818501915085601f830112611f5d57600080fd5b8151611f6b611802826119b8565b81815260059190911b83018401908481019088831115611f8a57600080fd5b8585015b83811015611fc257805185811115611fa65760008081fd5b611fb48b89838a01016117e3565b845250918601918601611f8e565b5098975050505050505050565b60008351611fe18184602088016117bf565b60609390931b6001600160601b0319169190920190815260140192915050565b6001600160e01b031981358181169160048510156111a15760049490940360031b84901b1690921692915050565b600082516120418184602087016117bf565b9190910192915050565b81810381811115610efe57610efe611869565b6000808585111561206e57600080fd5b8386111561207b57600080fd5b5050820193919092039150565b80356020831015610efe57600019602084900360031b1b1692915050565b6001600160601b031981358181169160148510156111a15760149490940360031b84901b1690921692915050565b6001600160601b0319606087811b8216835286901b16601482015283151560f81b60288201526001600160e01b031983166029820152815160009061212081602d8501602087016117bf565b91909101602d01969550505050505056fea2646970667358221220b83b773cdfcf498e8f6e203b00dd812579cee0721aa9e34f74f291765a0ebfb164736f6c634300081500330000000000000000000000005f2f11ad8656439d5c14d9b351f8b09cdac2a02d000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e50000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638456cb591161008c578063bf7e214f11610066578063bf7e214f146101ef578063f04f270714610202578063f2fde38b14610215578063fbfa77cf1461022857600080fd5b80638456cb59146101b75780638da5cb5b146101bf578063b187bd26146101d257600080fd5b80633f4ba83a116100c85780633f4ba83a1461015b5780635c38449e146101635780635ca58a99146101765780637a9e5e4b146101a457600080fd5b8063158274a5146100ef57806321801a9914610133578063244b0f6a14610148575b600080fd5b6101167f000000000000000000000000000000000000000000000000000000000000000181565b6040516001600160a01b0390911681526020015b60405180910390f35b6101466101413660046112db565b61024f565b005b610146610156366004611352565b6102e9565b61014661070c565b610146610171366004611483565b610773565b61019661018436600461152f565b60026020526000908152604090205481565b60405190815260200161012a565b6101466101b236600461152f565b6108a0565b61014661098a565b600054610116906001600160a01b031681565b6005546101df9060ff1681565b604051901515815260200161012a565b600154610116906001600160a01b031681565b61014661021036600461154c565b6109f4565b61014661022336600461152f565b610ddb565b6101167f000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e581565b610265336000356001600160e01b031916610e58565b61028a5760405162461bcd60e51b81526004016102819061160f565b60405180910390fd5b6001600160a01b038216600081815260026020908152604091829020805490859055825181815291820185905292917f0b958dec85f1470000479dfb22c365829411f52bcde602d24ea0abf5ac7e8860910160405180910390a2505050565b6102ff336000356001600160e01b031916610e58565b61031b5760405162461bcd60e51b81526004016102819061160f565b60055460ff161561033f57604051631b7b196560e31b815260040160405180910390fd5b848981146103605760405163029c70cf60e41b815260040160405180910390fd5b8084146103805760405163581ddbfd60e01b815260040160405180910390fd5b8082146103a05760405163e9fd1adf60e01b815260040160405180910390fd5b8088146103c057604051631b4d824d60e31b815260040160405180910390fd5b3360009081526002602090815260408083205481516318160ddd60e01b815291519093927f000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e56001600160a01b0316926318160ddd92600480830193928290030181865afa158015610435573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104599190611635565b905060005b838110156106285761051e838f8f8481811061047c5761047c61164e565b905060200281019061048e9190611664565b8f8f868181106104a0576104a061164e565b90506020020160208101906104b5919061152f565b8e8e878181106104c7576104c761164e565b90506020020160208101906104dc919061152f565b8b8b888181106104ee576104ee61164e565b905060200201358e8e898181106105075761050761164e565b905060200281019061051991906116ad565b610f04565b7f000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e56001600160a01b031663f6e715d08b8b8481811061055f5761055f61164e565b9050602002016020810190610574919061152f565b8a8a858181106105865761058661164e565b905060200281019061059891906116ad565b8a8a878181106105aa576105aa61164e565b905060200201356040518563ffffffff1660e01b81526004016105d0949392919061171c565b6000604051808303816000875af11580156105ef573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106179190810190611835565b506106218161187f565b905061045e565b507f000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e56001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610687573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ab9190611635565b81146106ca57604051630ecee17560e01b815260040160405180910390fd5b6040518381527f53d426e7d80bb2c8674d3b45577e2d464d423faad6531b21f95ac11ac18b1cb69060200160405180910390a150505050505050505050505050565b610722336000356001600160e01b031916610e58565b61073e5760405162461bcd60e51b81526004016102819061160f565b6005805460ff191690556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b336001600160a01b037f000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e516146107bc576040516377ed816560e01b815260040160405180910390fd5b81816040516107cc929190611898565b60405190819003812060049081556003805460ff19166001179055632e1c224f60e11b82526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000011691635c38449e9161083a918b918b918b918b918b918b918b91016118f1565b600060405180830381600087803b15801561085457600080fd5b505af1158015610868573d6000803e3d6000fd5b50506003805460ff1916905550506004541561089757604051633de6ce8160e21b815260040160405180910390fd5b50505050505050565b6000546001600160a01b0316331480610935575060015460405163b700961360e01b81526001600160a01b039091169063b7009613906108f490339030906001600160e01b03196000351690600401611969565b602060405180830381865afa158015610911573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109359190611996565b61093e57600080fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b6109a0336000356001600160e01b031916610e58565b6109bc5760405162461bcd60e51b81526004016102819061160f565b6005805460ff191660011790556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000011614610a3d5760405163a38bce7f60e01b815260040160405180910390fd5b60035460ff16610a60576040516326e6e2c760e01b815260040160405180910390fd5b60008282604051610a72929190611898565b604051809103902090506004548114610a9e57604051631663f61360e01b815260040160405180910390fd5b600060048190555b86811015610b3257610b227f000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e5898984818110610ae457610ae461164e565b905060200201358c8c85818110610afd57610afd61164e565b9050602002016020810190610b12919061152f565b6001600160a01b03169190610ff1565b610b2b8161187f565b9050610aa6565b50600080808080610b4587890189611c43565b60405163122587b560e11b815294995092975090955093509150309063244b0f6a90610b7d9088908890889088908890600401611dea565b600060405180830381600087803b158015610b9757600080fd5b505af1158015610bab573d6000803e3d6000fd5b5050505050505050506000878790506001600160401b03811115610bd157610bd1611752565b604051908082528060200260200182016040528015610c0457816020015b6060815260200190600190039081610bef5790505b50905060005b87811015610cf35763a9059cbb60e01b7f0000000000000000000000000000000000000000000000000000000000000001888884818110610c4d57610c4d61164e565b905060200201358b8b85818110610c6657610c6661164e565b90506020020135610c779190611ec7565b6040516001600160a01b0390921660248301526044820152606401604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050828281518110610cd757610cd761164e565b602002602001018190525080610cec9061187f565b9050610c0a565b506001600160a01b037f000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e51663224d87038b8b848b6001600160401b03811115610d3e57610d3e611752565b604051908082528060200260200182016040528015610d67578160200160208202803683370190505b506040518563ffffffff1660e01b8152600401610d879493929190611eda565b6000604051808303816000875af1158015610da6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dce9190810190611f1f565b5050505050505050505050565b610df1336000356001600160e01b031916610e58565b610e0d5760405162461bcd60e51b81526004016102819061160f565b600080546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b6001546000906001600160a01b03168015801590610ee2575060405163b700961360e01b81526001600160a01b0382169063b700961390610ea190879030908890600401611969565b602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190611996565b80610efa57506000546001600160a01b038581169116145b9150505b92915050565b6000610f5083838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506001600160a01b038a1692915050611078565b806020019051810190610f639190611835565b90506000610f7184846110ee565b90506001600160a01b03811615610fa7578181604051602001610f95929190611fcf565b60405160208183030381529060405291505b610fc08a8a8a898b8a610fba8a8c612001565b896111aa565b610fe5578584848760405163c0dcd1a760e01b8152600401610281949392919061171c565b50505050505050505050565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806110725760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610281565b50505050565b6060600080846001600160a01b031684604051611095919061202f565b600060405180830381855afa9150503d80600081146110d0576040519150601f19603f3d011682016040523d82523d6000602084013e6110d5565b606091505b50915091506110e5858383611201565b95945050505050565b600081604481106111a3576000848461110860208561204b565b61111392829061205e565b61111c91612088565b60408051808201909152600f81526e111c9bdb99531a588b9d185c99d95d608a1b60209091015290507fc1b9dfe6c6d6343c26291b77edfcc5dbc62c3afa2ee72581da4e3cdbe96a0a4f81016111a157848461117960348561204b565b9061118560208661204b565b926111929392919061205e565b61119b916120a6565b60601c92505b505b5092915050565b600080600085119050600086888387876040516020016111ce9594939291906120d4565b6040516020818303038152906040528051906020012090506111f28a8a8d84611260565b9b9a5050505050505050505050565b606082611216576112118261129a565b611259565b815115801561122d57506001600160a01b0384163b155b1561125657604051639996b31560e01b81526001600160a01b0385166004820152602401610281565b50805b9392505050565b60008315611292578360051b8501855b803580851160051b948552602094851852604060002093018181106112705750505b501492915050565b8051156112aa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b03811681146112c357600080fd5b600080604083850312156112ee57600080fd5b82356112f9816112c6565b946020939093013593505050565b60008083601f84011261131957600080fd5b5081356001600160401b0381111561133057600080fd5b6020830191508360208260051b850101111561134b57600080fd5b9250929050565b60008060008060008060008060008060a08b8d03121561137157600080fd5b8a356001600160401b038082111561138857600080fd5b6113948e838f01611307565b909c509a5060208d01359150808211156113ad57600080fd5b6113b98e838f01611307565b909a50985060408d01359150808211156113d257600080fd5b6113de8e838f01611307565b909850965060608d01359150808211156113f757600080fd5b6114038e838f01611307565b909650945060808d013591508082111561141c57600080fd5b506114298d828e01611307565b915080935050809150509295989b9194979a5092959850565b60008083601f84011261145457600080fd5b5081356001600160401b0381111561146b57600080fd5b60208301915083602082850101111561134b57600080fd5b60008060008060008060006080888a03121561149e57600080fd5b87356114a9816112c6565b965060208801356001600160401b03808211156114c557600080fd5b6114d18b838c01611307565b909850965060408a01359150808211156114ea57600080fd5b6114f68b838c01611307565b909650945060608a013591508082111561150f57600080fd5b5061151c8a828b01611442565b989b979a50959850939692959293505050565b60006020828403121561154157600080fd5b8135611259816112c6565b6000806000806000806000806080898b03121561156857600080fd5b88356001600160401b038082111561157f57600080fd5b61158b8c838d01611307565b909a50985060208b01359150808211156115a457600080fd5b6115b08c838d01611307565b909850965060408b01359150808211156115c957600080fd5b6115d58c838d01611307565b909650945060608b01359150808211156115ee57600080fd5b506115fb8b828c01611442565b999c989b5096995094979396929594505050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b60006020828403121561164757600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261167b57600080fd5b8301803591506001600160401b0382111561169557600080fd5b6020019150600581901b360382131561134b57600080fd5b6000808335601e198436030181126116c457600080fd5b8301803591506001600160401b038211156116de57600080fd5b60200191503681900382131561134b57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038516815260606020820181905260009061174190830185876116f3565b905082604083015295945050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561179057611790611752565b604052919050565b60006001600160401b038211156117b1576117b1611752565b50601f01601f191660200190565b60005b838110156117da5781810151838201526020016117c2565b50506000910152565b600082601f8301126117f457600080fd5b815161180761180282611798565b611768565b81815284602083860101111561181c57600080fd5b61182d8260208301602087016117bf565b949350505050565b60006020828403121561184757600080fd5b81516001600160401b0381111561185d57600080fd5b610efa848285016117e3565b634e487b7160e01b600052601160045260246000fd5b60006001820161189157611891611869565b5060010190565b8183823760009101908152919050565b8183526000602080850194508260005b858110156118e65781356118cb816112c6565b6001600160a01b0316875295820195908201906001016118b8565b509495945050505050565b6001600160a01b0388168152608060208201819052600090611916908301888a6118a8565b82810360408401528581526001600160fb1b0386111561193557600080fd5b8560051b80886020840137018281036020908101606085015261195b90820185876116f3565b9a9950505050505050505050565b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b6000602082840312156119a857600080fd5b8151801515811461125957600080fd5b60006001600160401b038211156119d1576119d1611752565b5060051b60200190565b600082601f8301126119ec57600080fd5b813560206119fc611802836119b8565b828152600592831b8501820192828201919087851115611a1b57600080fd5b8387015b85811015611aae5780356001600160401b03811115611a3e5760008081fd5b8801603f81018a13611a505760008081fd5b858101356040611a62611802836119b8565b82815291851b8301810191888101908d841115611a7f5760008081fd5b938201935b83851015611a9d57843582529389019390890190611a84565b885250505093850193508401611a1f565b5090979650505050505050565b600082601f830112611acc57600080fd5b81356020611adc611802836119b8565b82815260059290921b84018101918181019086841115611afb57600080fd5b8286015b84811015611b1f578035611b12816112c6565b8352918301918301611aff565b509695505050505050565b600082601f830112611b3b57600080fd5b81356020611b4b611802836119b8565b82815260059290921b84018101918181019086841115611b6a57600080fd5b8286015b84811015611b1f5780356001600160401b03811115611b8d5760008081fd5b8701603f81018913611b9f5760008081fd5b848101356040611bb161180283611798565b8281528b82848601011115611bc65760008081fd5b8282850189830137600092810188019290925250845250918301918301611b6e565b600082601f830112611bf957600080fd5b81356020611c09611802836119b8565b82815260059290921b84018101918181019086841115611c2857600080fd5b8286015b84811015611b1f5780358352918301918301611c2c565b600080600080600060a08688031215611c5b57600080fd5b85356001600160401b0380821115611c7257600080fd5b611c7e89838a016119db565b96506020880135915080821115611c9457600080fd5b611ca089838a01611abb565b95506040880135915080821115611cb657600080fd5b611cc289838a01611abb565b94506060880135915080821115611cd857600080fd5b611ce489838a01611b2a565b93506080880135915080821115611cfa57600080fd5b50611d0788828901611be8565b9150509295509295909350565b600081518084526020808501945080840160005b838110156118e65781516001600160a01b031687529582019590820190600101611d28565b600081518084526020808501808196508360051b8101915082860160005b85811015611dad57828403895281518051808652611d8e818888018985016117bf565b99860199601f01601f1916949094018501935090840190600101611d6b565b5091979650505050505050565b600081518084526020808501945080840160005b838110156118e657815187529582019590820190600101611dce565b600060a0820160a0835280885180835260c08501915060c08160051b86010192506020808b016000805b84811015611e685788870360bf19018652825180518089529085019085890190845b81811015611e5257835183529287019291870191600101611e36565b5090985050509483019491830191600101611e14565b50505085840381870152505050611e7f8188611d14565b90508281036040840152611e938187611d14565b90508281036060840152611ea78186611d4d565b90508281036080840152611ebb8185611dba565b98975050505050505050565b80820180821115610efe57610efe611869565b606081526000611eee6060830186886118a8565b8281036020840152611f008186611d4d565b90508281036040840152611f148185611dba565b979650505050505050565b60006020808385031215611f3257600080fd5b82516001600160401b0380821115611f4957600080fd5b818501915085601f830112611f5d57600080fd5b8151611f6b611802826119b8565b81815260059190911b83018401908481019088831115611f8a57600080fd5b8585015b83811015611fc257805185811115611fa65760008081fd5b611fb48b89838a01016117e3565b845250918601918601611f8e565b5098975050505050505050565b60008351611fe18184602088016117bf565b60609390931b6001600160601b0319169190920190815260140192915050565b6001600160e01b031981358181169160048510156111a15760049490940360031b84901b1690921692915050565b600082516120418184602087016117bf565b9190910192915050565b81810381811115610efe57610efe611869565b6000808585111561206e57600080fd5b8386111561207b57600080fd5b5050820193919092039150565b80356020831015610efe57600019602084900360031b1b1692915050565b6001600160601b031981358181169160148510156111a15760149490940360031b84901b1690921692915050565b6001600160601b0319606087811b8216835286901b16601482015283151560f81b60288201526001600160e01b031983166029820152815160009061212081602d8501602087016117bf565b91909101602d01969550505050505056fea2646970667358221220b83b773cdfcf498e8f6e203b00dd812579cee0721aa9e34f74f291765a0ebfb164736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005f2f11ad8656439d5c14d9b351f8b09cdac2a02d000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e50000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _owner (address): 0x5F2F11ad8656439d5C14d9B351f8b09cDaC2A02d
Arg [1] : _vault (address): 0xBCFF64e3EF4d4f6A4ea34Ae3F7fA7012988B69e5
Arg [2] : _balancerVault (address): 0x0000000000000000000000000000000000000001
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000005f2f11ad8656439d5c14d9b351f8b09cdac2a02d
Arg [1] : 000000000000000000000000bcff64e3ef4d4f6a4ea34ae3f7fa7012988b69e5
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.