Source Code
Overview
HYPE Balance
HYPE Value
$0.00Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
3094891 | 70 days ago | Contract Creation | 0 HYPE |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
JamBalanceManager
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 1239 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "./base/JamTransfer.sol"; import "./interfaces/IJamBalanceManager.sol"; import "./interfaces/IPermit2.sol"; /// @title JamBalanceManager /// @notice The reason a balance manager exists is to prevent interaction to the settlement contract draining user funds /// By having another contract that allowances are made to, we can enforce that it is only used to draw in user balances to settlement and not sent out contract JamBalanceManager is IJamBalanceManager { using SafeTransferLib for IERC20; using JamOrderLib for JamOrder; using BlendSingleOrderLib for BlendSingleOrder; using BlendMultiOrderLib for BlendMultiOrder; using BlendAggregateOrderLib for BlendAggregateOrder; address private immutable operator; IPermit2 private immutable PERMIT2; constructor(address _operator, address _permit2) { // Operator can be defined at creation time with `msg.sender` // Pass in the settlement - and that can be the only caller. operator = _operator; PERMIT2 = IPermit2(_permit2); } modifier onlyOperator(address account) { require(account == operator, InvalidCaller()); _; } /// @inheritdoc IJamBalanceManager function transferTokensWithPermit2( JamOrder calldata order, bytes calldata signature, bytes32 hooksHash, address receiver ) onlyOperator(msg.sender) external { PERMIT2.permitWitnessTransferFrom( order.toBatchPermit2(), order.toSignatureTransferDetails(receiver), order.taker, order.hash(hooksHash), JamOrderLib.PERMIT2_ORDER_TYPE, signature ); } /// @inheritdoc IJamBalanceManager function transferTokens( address[] calldata tokens, uint256[] calldata amounts, address sender, address receiver ) onlyOperator(msg.sender) external { for (uint i; i < tokens.length; ++i){ if (tokens[i] != JamOrderLib.NATIVE_TOKEN){ IERC20(tokens[i]).safeTransferFrom(sender, receiver, amounts[i]); } else if (receiver != operator){ JamTransfer(operator).transferNativeFromContract(receiver, amounts[i]); } } } /// @inheritdoc IJamBalanceManager function transferTokenForBlendSingleOrder( BlendSingleOrder memory order, IBebopBlend.OldSingleQuote memory oldSingleQuote, bytes memory takerSignature, address takerAddress, bytes32 hooksHash ) onlyOperator(msg.sender) external { PERMIT2.permitWitnessTransferFrom( IPermit2.PermitTransferFrom( IPermit2.TokenPermissions(order.taker_token, order.taker_amount), order.flags >> 128, order.expiry ), IPermit2.SignatureTransferDetails(operator, order.taker_amount), takerAddress, order.hash(oldSingleQuote.makerAmount, oldSingleQuote.makerNonce, hooksHash), BlendSingleOrderLib.PERMIT2_ORDER_TYPE, takerSignature ); } /// @inheritdoc IJamBalanceManager function transferTokensForMultiBebopOrder( BlendMultiOrder memory order, IBebopBlend.OldMultiQuote memory oldMultiQuote, bytes memory takerSignature, address takerAddress, bytes32 hooksHash ) onlyOperator(msg.sender) external { PERMIT2.permitWitnessTransferFrom( order.toBatchPermit2(), order.toSignatureTransferDetails(operator), takerAddress, order.hash(oldMultiQuote.makerAmounts, oldMultiQuote.makerNonce, hooksHash), BlendMultiOrderLib.PERMIT2_ORDER_TYPE, takerSignature ); } /// @inheritdoc IJamBalanceManager function transferTokensForAggregateBebopOrder( BlendAggregateOrder memory order, IBebopBlend.OldAggregateQuote memory oldAggregateQuote, bytes memory takerSignature, address takerAddress, bytes32 hooksHash ) onlyOperator(msg.sender) external { (address[] memory tokens, uint256[] memory amounts) = order.unpackTokensAndAmounts(true, oldAggregateQuote); PERMIT2.permitWitnessTransferFrom( order.toBatchPermit2(tokens, amounts), BlendAggregateOrderLib.toSignatureTransferDetails(amounts, operator), takerAddress, order.hash(oldAggregateQuote.makerAmounts, oldAggregateQuote.makerNonces, hooksHash), BlendAggregateOrderLib.PERMIT2_ORDER_TYPE, takerSignature ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; /// @notice Thrown when solver sends less than expected to settlement contract error InvalidOutputBalance(address token, uint256 expected, uint256 actual); /// @notice Thrown when sending ETH via call fails error FailedToSendEth(); /// @notice Thrown when the passed in signature is not a valid length error InvalidSignatureLength(); /// @notice Thrown when the recovered signer is equal to the zero address error InvalidSignature(); /// @notice Thrown when the recovered signer does not equal the claimedSigner error InvalidSigner(); /// @notice Thrown when the recovered contract signature is incorrect error InvalidContractSignature(); /// @notice Thrown when msg.sender is not allowed to call a function error InvalidExecutor(); /// @notice Thrown when length of sell tokens and sell amounts are not equal error SellTokensInvalidLength(); /// @notice Thrown when length of buy tokens and buy amounts are not equal error BuyTokensInvalidLength(); /// @notice Thrown when order is expired error OrderExpired(); /// @notice Thrown when nonce is already invalidated error InvalidNonce(); /// @notice Thrown when nonce is zero error ZeroNonce(); /// @notice Thrown when length of filled amounts is not equal to tokens length error InvalidFilledAmountsLength(); /// @notice Thrown when filled amounts is less than previous amount error InvalidFilledAmounts(uint256 expected, uint256 actual); /// @notice Thrown when length of signatures array is not equal to batch length error InvalidBatchSignaturesLength(); /// @notice Thrown when length of hooks array is not equal to batch length error InvalidBatchHooksLength(); /// @notice Thrown when one of the orders in batch has settlement contract as receiver error InvalidReceiverInBatch(); /// @notice Thrown when different fees are passed in batch error DifferentFeesInBatch(); /// @notice Thrown when invalid partner address is passed error InvalidPartnerAddress(); /// @notice Thrown when caller is not settlement contract error InvalidCaller(); /// @notice Thrown when interactions failed error InteractionsFailed(); /// @notice Thrown when beforeSettle hooks failed error BeforeSettleHooksFailed(); /// @notice Thrown when beforeSettle hooks failed error AfterSettleHooksFailed(); /// @notice Thrown for unknown blend order type error InvalidBlendOrderType(); /// @notice Thrown when invalid fee percentage is passed error InvalidFeePercentage(); /// @notice Thrown when interactions contain call to balance manager error CallToBalanceManagerNotAllowed(); /// @notice Thrown when there are duplicate buy tokens in the order error DuplicateTokens(); /// @notice Thrown when new partner-id is different from the current one error InvalidBlendPartnerId();
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "../base/Errors.sol"; import "../libraries/JamOrder.sol"; import "../external-libs/SafeTransferLib.sol"; /// @title JamPartner abstract contract JamPartner { uint16 internal constant HUNDRED_PERCENT = 10000; // 100% in bps address internal immutable protocolFeeAddress; event NativeTransfer(address indexed receiver, uint256 amount); using SafeTransferLib for IERC20; constructor(address _protocolFeeAddress){ protocolFeeAddress = _protocolFeeAddress; } /// @notice Distribute fees to the partner and protocol, fees are optional /// @param partnerInfo The partner info, packed with the partner address, partner fee and protocol fee /// @param token The token to distribute fees in /// @param amount Token amount in order to distribute fees from /// @return totalFeesSent The total amount of tokens sent as fees function distributeFees(uint256 partnerInfo, address token, uint256 amount) internal returns (uint256 totalFeesSent){ (address partnerAddress, uint16 partnerFee, uint16 protocolFee) = unpackPartnerInfo(partnerInfo); if (partnerFee > 0) { totalFeesSent += sendPartnerFee(token, amount, partnerFee, partnerAddress); } if (protocolFee > 0) { totalFeesSent += sendPartnerFee(token, amount, protocolFee, protocolFeeAddress); } return totalFeesSent; } /// @notice Unpack the partner info /// @param partnerInfo Packed info: [ .... | address | uint16 | uint16 ] function unpackPartnerInfo(uint256 partnerInfo) private pure returns (address, uint16, uint16) { uint16 protocolFeeBps = uint16(partnerInfo & 0xFFFF); uint16 partnerFeeBps = uint16((partnerInfo >> 16) & 0xFFFF); address partnerAddress = address(uint160(partnerInfo >> 32)); require(partnerFeeBps + protocolFeeBps < HUNDRED_PERCENT, InvalidFeePercentage()); require(partnerFeeBps > 0 || (partnerFeeBps == 0 && partnerAddress == address(0)), InvalidPartnerAddress()); return (partnerAddress, partnerFeeBps, protocolFeeBps); } /// @notice Send the partner fee /// @param token The token to send /// @param amount The amount to send /// @param fee The fee percentage /// @param receiver The receiver of the fee /// @return feeAmount The amount of fee sent function sendPartnerFee(address token, uint256 amount, uint16 fee, address receiver) private returns (uint256){ uint256 feeAmount = amount * fee / HUNDRED_PERCENT; if (token == JamOrderLib.NATIVE_TOKEN) { (bool sent, ) = payable(receiver).call{value: feeAmount}(""); require(sent, FailedToSendEth()); emit NativeTransfer(receiver, feeAmount); } else { IERC20(token).safeTransfer(receiver, feeAmount); } return feeAmount; } /// @notice Get total fees in bps /// @param partnerInfo The partner info /// @return totalFeesBps The total fees in bps function getTotalFeesBps(uint256 partnerInfo) internal pure returns (uint16){ uint16 protocolFeeBps = uint16(partnerInfo & 0xFFFF); uint16 partnerFeeBps = uint16((partnerInfo >> 16) & 0xFFFF); return protocolFeeBps + partnerFeeBps; } /// @notice Get arrays with fees amounts for each token /// @param amounts The amounts to calculate fees for /// @param minAmounts Minimum amounts that user signed for /// @param partnerInfo The partner info /// @return newAmounts The new amounts after fees /// @return protocolFees The protocol fees, if empty then no protocol fees /// @return partnerFees The partner fees, if empty then no partner fees /// @return partnerAddress The partner address, or zero address if no partner fees function getUpdatedAmountsAndFees( uint256[] calldata amounts, uint256[] calldata minAmounts, uint256 partnerInfo ) internal pure returns (uint256[] memory newAmounts, uint256[] memory protocolFees, uint256[] memory partnerFees, address) { (address partnerAddress, uint16 partnerFee, uint16 protocolFee) = unpackPartnerInfo(partnerInfo); uint tokensLength = amounts.length; require(minAmounts.length == tokensLength, InvalidFilledAmountsLength()); newAmounts = new uint256[](tokensLength); if (protocolFee > 0) { protocolFees = new uint256[](tokensLength); for (uint256 i; i < tokensLength; ++i) { protocolFees[i] = amounts[i] * protocolFee / HUNDRED_PERCENT; newAmounts[i] = amounts[i] - protocolFees[i]; } } if (partnerFee > 0) { partnerFees = new uint256[](tokensLength); for (uint256 i; i < tokensLength; ++i) { partnerFees[i] = amounts[i] * partnerFee / HUNDRED_PERCENT; newAmounts[i] = newAmounts[i] == 0 ? amounts[i] - partnerFees[i] : newAmounts[i] - partnerFees[i]; } } for (uint256 i; i < tokensLength; ++i) { require(newAmounts[i] >= minAmounts[i], InvalidFilledAmounts(minAmounts[i], newAmounts[i])); } return (newAmounts, protocolFees, partnerFees, partnerAddress); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "./JamPartner.sol"; /// @title JamTransfer /// @notice Functions for transferring tokens from SettlementContract abstract contract JamTransfer is JamPartner { using SafeTransferLib for IERC20; /// @dev Check if token is approved for spender, max approve if not /// max approval is fine for settlement contract, because we use BalanceManager for users approvals /// @param token token's address /// @param amount transfer amount /// @param spender spender's address, in our case it will BebopBlend contract function approveToken(IERC20 token, uint256 amount, address spender) internal { uint256 allowance = token.allowance(address(this), spender); if (allowance < amount) { token.safeApproveWithRetry(spender, type(uint256).max); } } /// @dev After solver settlement, transfer tokens from this contract to receiver /// @param tokens tokens' addresses /// @param minAmounts minimum amounts from order /// @param amounts tokens' filled amounts /// @param receiver address /// @param transferExactAmounts if true, transfer exact amounts, otherwise transfer full tokens balance function transferTokensFromContract( address[] calldata tokens, uint256[] calldata minAmounts, uint256[] memory amounts, address receiver, uint256 partnerInfo, bool transferExactAmounts ) internal { for (uint i; i < tokens.length; ++i) { if (!transferExactAmounts) { amounts[i] = tokens[i] == JamOrderLib.NATIVE_TOKEN ? address(this).balance : IERC20(tokens[i]).balanceOf(address(this)); } if (partnerInfo != 0){ amounts[i] -= distributeFees(partnerInfo, tokens[i], amounts[i]); } require(amounts[i] >= minAmounts[i], InvalidOutputBalance(tokens[i], minAmounts[i], amounts[i])); if (tokens[i] == JamOrderLib.NATIVE_TOKEN) { (bool sent, ) = payable(receiver).call{value: amounts[i]}(""); require(sent, FailedToSendEth()); emit NativeTransfer(receiver, amounts[i]); } else { IERC20(tokens[i]).safeTransfer(receiver, amounts[i]); } } } /// @dev Transfer native tokens to receiver from this contract /// @param receiver address /// @param amount amount of native tokens function transferNativeFromContract(address receiver, uint256 amount) public { (bool sent, ) = payable(receiver).call{value: amount}(""); require(sent, FailedToSendEth()); } /// @dev Calculate new amounts of tokens if solver transferred excess to contract during settleBatch /// @param curInd index of current order /// @param orders array of orders /// @return array of new amounts function calculateNewAmounts(uint256 curInd, JamOrder[] calldata orders) internal view returns (uint256[] memory) { JamOrder calldata curOrder = orders[curInd]; uint256[] memory newAmounts = new uint256[](curOrder.buyTokens.length); for (uint i; i < curOrder.buyTokens.length; ++i) { uint256 fullAmount; for (uint j = curInd; j < orders.length; ++j) { for (uint k; k < orders[j].buyTokens.length; ++k) { if (orders[j].buyTokens[k] == curOrder.buyTokens[i]) { fullAmount += orders[j].buyAmounts[k]; require( getTotalFeesBps(curOrder.partnerInfo) == getTotalFeesBps(orders[j].partnerInfo), DifferentFeesInBatch() ); } } } uint256 tokenBalance = curOrder.buyTokens[i] == JamOrderLib.NATIVE_TOKEN ? address(this).balance : IERC20(curOrder.buyTokens[i]).balanceOf(address(this)); // if at least two takers buy same token, we need to divide the whole tokenBalance among them. // for edge case with newAmounts[i] overflow, solver shouldn't submit txs in a batch newAmounts[i] = tokenBalance * curOrder.buyAmounts[i] / fullAmount; if (newAmounts[i] < curOrder.buyAmounts[i]) { newAmounts[i] = curOrder.buyAmounts[i]; } } return newAmounts; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "../interfaces/IPermit2.sol"; // from PermitHash.sol in Permit2 // https://github.com/Uniswap/permit2/blob/main/src/libraries/PermitHash.sol library PermitHash { bytes32 private constant _TOKEN_PERMISSIONS_TYPEHASH = keccak256("TokenPermissions(address token,uint256 amount)"); string private constant _PERMIT_BATCH_WITNESS_TRANSFER_FROM_TYPEHASH_STUB = "PermitBatchWitnessTransferFrom(TokenPermissions[] permitted,address spender,uint256 nonce,uint256 deadline,"; function hashWithWitness( IPermit2.PermitBatchTransferFrom memory permit, bytes32 witness, string memory witnessTypeString, address spender ) internal pure returns (bytes32) { bytes32 typeHash = keccak256(abi.encodePacked(_PERMIT_BATCH_WITNESS_TRANSFER_FROM_TYPEHASH_STUB, witnessTypeString)); uint256 numPermitted = permit.permitted.length; bytes32[] memory tokenPermissionHashes = new bytes32[](numPermitted); for (uint256 i = 0; i < numPermitted; ++i) { tokenPermissionHashes[i] = _hashTokenPermissions(permit.permitted[i]); } return keccak256( abi.encode( typeHash, keccak256(abi.encodePacked(tokenPermissionHashes)), spender, permit.nonce, permit.deadline, witness ) ); } function _hashTokenPermissions(IPermit2.TokenPermissions memory permitted) private pure returns (bytes32){ return keccak256(abi.encode(_TOKEN_PERMISSIONS_TYPEHASH, permitted)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.27; import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; /// @notice Safe ERC20 transfer library that gracefully handles missing return values. /// From: Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// https://github.com/Vectorized/solady/blob/main/src/utils/SafeTransferLib.sol library SafeTransferLib { /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( IERC20 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( IERC20 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"); } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// If the initial attempt to approve fails, attempts to reset the approved amount to zero, /// then retries the approval again (some tokens, e.g. USDT, requires this). /// Reverts upon failure. function safeApproveWithRetry(IERC20 token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, retrying upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x34, 0) // Store 0 for the `amount`. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval. mstore(0x34, amount) // Store back the original `amount`. // Retry the approval, reverting upon failure. if iszero( and( or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../libraries/BlendSingleOrder.sol"; import "../libraries/BlendMultiOrder.sol"; import "../libraries/BlendAggregateOrder.sol"; /// @title IBebopBlend is interface for interacting with BebopBlend contract, which aggregates PMM liquidity. /// Swaps through that contract have zero slippage. /// Deployed on 0xbbbbbBB520d69a9775E85b458C58c648259FAD5F interface IBebopBlend { enum BlendOrderType { Single, // 0 Multi, // 1 Aggregate // 2 } struct OldSingleQuote { bool useOldAmount; uint256 makerAmount; uint256 makerNonce; } struct OldMultiQuote { bool useOldAmount; uint256[] makerAmounts; uint256 makerNonce; } struct OldAggregateQuote { bool useOldAmount; uint256[][] makerAmounts; uint256[] makerNonces; } struct MakerSignature { bytes signatureBytes; uint256 flags; } /// @notice Maker execution of one-to-one trade with one maker /// @param order Single order struct /// @param makerSignature Maker's signature for SingleOrder /// @param filledTakerAmount Partially filled taker amount, 0 for full fill /// @param takerQuoteInfo If maker_amount has improved then it contains old quote values that taker signed, /// otherwise it contains same values as in order /// @param takerSignature Taker's signature to approve executing order by maker, /// if taker executes order himself then signature can be '0x' (recommended to use swapSingle for this case) function settleSingle( BlendSingleOrder calldata order, MakerSignature calldata makerSignature, uint256 filledTakerAmount, OldSingleQuote calldata takerQuoteInfo, bytes calldata takerSignature ) external payable; /// @notice Maker execution of one-to-many or many-to-one trade with one maker /// @param order Multi order struct /// @param makerSignature Maker's signature for MultiOrder /// @param filledTakerAmount Partially filled taker amount, 0 for full fill. Many-to-one doesnt support partial fill /// @param takerQuoteInfo If maker_amounts have improved then it contains old quote values that taker signed, /// otherwise it contains same values as in order /// @param takerSignature Taker's signature to approve executing order by maker, /// if taker executes order himself then signature can be '0x' (recommended to use swapMulti for this case) function settleMulti( BlendMultiOrder calldata order, MakerSignature calldata makerSignature, uint256 filledTakerAmount, OldMultiQuote calldata takerQuoteInfo, bytes calldata takerSignature ) external payable; /// @notice Maker execution of any trade with multiple makers /// @param order Aggregate order struct /// @param makersSignatures Makers signatures for MultiOrder (can be contructed as part of current AggregateOrder) /// @param filledTakerAmount Partially filled taker amount, 0 for full fill. Many-to-one doesnt support partial fill /// @param takerQuoteInfo If maker_amounts have improved then it contains old quote values that taker signed, /// otherwise it contains same values as in order /// @param takerSignature Taker's signature to approve executing order by maker, /// if taker executes order himself then signature can be '0x' (recommended to use swapAggregate for this case) function settleAggregate( BlendAggregateOrder calldata order, MakerSignature[] calldata makersSignatures, uint256 filledTakerAmount, OldAggregateQuote calldata takerQuoteInfo, bytes calldata takerSignature ) external payable; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "../libraries/JamOrder.sol"; import "../libraries/BlendSingleOrder.sol"; import "../libraries/BlendMultiOrder.sol"; import "../libraries/BlendAggregateOrder.sol"; import "./IBebopBlend.sol"; /// @title IJamBalanceManager /// @notice User approvals are made here. This handles the complexity of multiple allowance types. interface IJamBalanceManager { /// @dev Transfer user's tokens to receiver address for JamOrder /// @param order user signed order /// @param signature permit2 signature with order as witness /// @param hooksHash hash of hooks data /// @param receiver address to receive tokens, it can be operator address or solver address function transferTokensWithPermit2( JamOrder calldata order, bytes calldata signature, bytes32 hooksHash, address receiver ) external; /// @dev Transfer tokens to receiver address /// this function can be used not only for user's tokens, but also for maker's tokens in settleInternal /// @param tokens list of tokens to transfer /// @param amounts list of amounts to transfer /// @param sender address to transfer tokens from /// @param receiver address to transfer tokens to function transferTokens( address[] calldata tokens, uint256[] calldata amounts, address sender, address receiver ) external; /// @dev Transfer user's tokens to operator address for BlendSingleOrder /// @param order user signed order /// @param oldSingleQuote in case of amounts improvement, old quote is used to get old amounts signed by user /// @param takerSignature permit2 signature with order as witness /// @param takerAddress user address /// @param hooksHash hash of hooks data function transferTokenForBlendSingleOrder( BlendSingleOrder memory order, IBebopBlend.OldSingleQuote memory oldSingleQuote, bytes memory takerSignature, address takerAddress, bytes32 hooksHash ) external; /// @dev Transfer user's tokens to operator address for BlendMultiOrder /// @param order user signed order /// @param oldMultiQuote in case of amounts improvement, old quote is used to get old amounts signed by user /// @param takerSignature permit2 signature with order as witness /// @param takerAddress user address /// @param hooksHash hash of hooks data function transferTokensForMultiBebopOrder( BlendMultiOrder memory order, IBebopBlend.OldMultiQuote memory oldMultiQuote, bytes memory takerSignature, address takerAddress, bytes32 hooksHash ) external; /// @dev Transfer user's tokens to operator address for BlendAggregateOrder /// @param order user signed order /// @param oldAggregateQuote in case of amounts improvement, old quote is used to get old amounts signed by user /// @param takerSignature permit2 signature with order as witness /// @param takerAddress user address /// @param hooksHash hash of hooks data function transferTokensForAggregateBebopOrder( BlendAggregateOrder memory order, IBebopBlend.OldAggregateQuote memory oldAggregateQuote, bytes memory takerSignature, address takerAddress, bytes32 hooksHash ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; // Part of ISignatureTransfer(https://github.com/Uniswap/permit2/blob/main/src/interfaces/ISignatureTransfer.sol) interface IPermit2 { /// @notice The token and amount details for a transfer signed in the permit transfer signature struct TokenPermissions { // ERC20 token address address token; // the maximum amount that can be spent uint256 amount; } /// @notice The signed permit message for a single token transfer struct PermitTransferFrom { TokenPermissions permitted; // a unique value for every token owner's signature to prevent signature replays uint256 nonce; // deadline on the permit signature uint256 deadline; } /// @notice Used to reconstruct the signed permit message for multiple token transfers /// @dev Do not need to pass in spender address as it is required that it is msg.sender /// @dev Note that a user still signs over a spender address struct PermitBatchTransferFrom { // the tokens and corresponding amounts permitted for a transfer TokenPermissions[] permitted; // a unique value for every token owner's signature to prevent signature replays uint256 nonce; // deadline on the permit signature uint256 deadline; } /// @notice Specifies the recipient address and amount for batched transfers. /// @dev Recipients and amounts correspond to the index of the signed token permissions array. /// @dev Reverts if the requested amount is greater than the permitted signed amount. struct SignatureTransferDetails { // recipient address address to; // spender requested amount uint256 requestedAmount; } /// @notice Transfers a token using a signed permit message /// @notice Includes extra data provided by the caller to verify signature over /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition /// @dev Reverts if the requested amount is greater than the permitted signed amount /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails The spender's requested transfer details for the permitted token /// @param witness Extra data to include when checking the user signature /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash /// @param signature The signature to verify function permitWitnessTransferFrom( PermitTransferFrom memory permit, SignatureTransferDetails calldata transferDetails, address owner, bytes32 witness, string calldata witnessTypeString, bytes calldata signature ) external; /// @notice Transfers multiple tokens using a signed permit message /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition /// @notice Includes extra data provided by the caller to verify signature over /// @param permit The permit data signed over by the owner /// @param owner The owner of the tokens to transfer /// @param transferDetails Specifies the recipient and requested amount for the token transfer /// @param witness Extra data to include when checking the user signature /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash /// @param signature The signature to verify function permitWitnessTransferFrom( PermitBatchTransferFrom memory permit, SignatureTransferDetails[] calldata transferDetails, address owner, bytes32 witness, string calldata witnessTypeString, bytes calldata signature ) external; function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "../interfaces/IPermit2.sol"; import "../interfaces/IBebopBlend.sol"; /// @notice Struct for any trade with multiple makers struct BlendAggregateOrder { uint256 expiry; address taker_address; address[] maker_addresses; uint256[] maker_nonces; address[][] taker_tokens; address[][] maker_tokens; uint256[][] taker_amounts; uint256[][] maker_amounts; address receiver; bytes commands; uint256 flags; } library BlendAggregateOrderLib { bytes internal constant ORDER_TYPE = abi.encodePacked( "AggregateOrder(uint64 partner_id,uint256 expiry,address taker_address,address[] maker_addresses,uint256[] maker_nonces,address[][] taker_tokens,address[][] maker_tokens,uint256[][] taker_amounts,uint256[][] maker_amounts,address receiver,bytes commands,bytes32 hooksHash)" ); bytes32 internal constant ORDER_TYPE_HASH = keccak256(ORDER_TYPE); string internal constant PERMIT2_ORDER_TYPE = string( abi.encodePacked("AggregateOrder witness)", ORDER_TYPE, "TokenPermissions(address token,uint256 amount)") ); address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /// @notice hash the given order using same schema as in BebopBlend contract /// @param order the order to hash /// @param updatedMakerAmounts amounts that taker signed /// @param updatedMakerNonces nonce that taker signed /// @return the eip-712 order hash function hash( BlendAggregateOrder memory order, uint256[][] memory updatedMakerAmounts, uint256[] memory updatedMakerNonces, bytes32 hooksHash ) internal pure returns (bytes32) { uint64 partnerId = uint64(order.flags >> 64); return keccak256( abi.encode( ORDER_TYPE_HASH, partnerId, order.expiry, order.taker_address, keccak256(abi.encodePacked(order.maker_addresses)), keccak256(abi.encodePacked(updatedMakerNonces)), keccak256(_encodeTightlyPackedNested(order.taker_tokens)), keccak256(_encodeTightlyPackedNested(order.maker_tokens)), keccak256(_encodeTightlyPackedNestedInt(order.taker_amounts)), keccak256(_encodeTightlyPackedNestedInt(updatedMakerAmounts)), order.receiver, keccak256(order.commands), hooksHash ) ); } function toBatchPermit2( BlendAggregateOrder memory order, address[] memory tokens, uint256[] memory amounts ) internal pure returns (IPermit2.PermitBatchTransferFrom memory) { IPermit2.TokenPermissions[] memory permitted = new IPermit2.TokenPermissions[](tokens.length); for (uint i; i < tokens.length; ++i) { permitted[i] = IPermit2.TokenPermissions(tokens[i], amounts[i]); } return IPermit2.PermitBatchTransferFrom(permitted, order.flags >> 128, order.expiry); } function toSignatureTransferDetails( uint256[] memory amounts, address receiver ) internal pure returns (IPermit2.SignatureTransferDetails[] memory) { IPermit2.SignatureTransferDetails[] memory details = new IPermit2.SignatureTransferDetails[](amounts.length); for (uint i; i < amounts.length; ++i) { details[i] = IPermit2.SignatureTransferDetails(receiver, amounts[i]); } return details; } /// @notice Unpack 2d arrays of tokens and amounts into 1d array without duplicates /// @param order the order to unpack /// @param unpackTakerAmounts if true, unpack taker amounts, otherwise unpack maker amounts function unpackTokensAndAmounts( BlendAggregateOrder memory order, bool unpackTakerAmounts, IBebopBlend.OldAggregateQuote memory oldAggregateQuote ) internal pure returns (address[] memory tokens, uint256[] memory amounts){ uint maxLen; for (uint i; i < order.maker_addresses.length; ++i) { maxLen += unpackTakerAmounts ? order.taker_tokens[i].length : order.maker_tokens[i].length; } tokens = new address[](maxLen); amounts = new uint256[](maxLen); uint uniqueTokensCnt; uint commandsInd; for (uint256 i; i < order.maker_addresses.length; ++i) { if (unpackTakerAmounts) { commandsInd += order.maker_tokens[i].length; } uint curTokensLen = unpackTakerAmounts ? order.taker_tokens[i].length : order.maker_tokens[i].length; for (uint256 j; j < curTokensLen; ++j) { /// @dev AggregateOrder contains multiple maker orders, 'commands' field indicates how to transfer tokens /// All commands packed into one variable with bytes type, for each token - command is 1 byte: /// '0x[maker1-order_maker-token1][maker1-order_taker-token1][maker2-order_maker-token1][maker2-order_taker-token1]...' /// ignoring TRANSFER_FROM_CONTRACT and TRANSFER_TO_CONTRACT commands, since they are transfers between makers if ( (unpackTakerAmounts && order.commands[commandsInd + j] != 0x08) || // Commands.TRANSFER_FROM_CONTRACT=0x08 (!unpackTakerAmounts && order.commands[commandsInd + j] != 0x07) //Commands.TRANSFER_TO_CONTRACT=0x07 ) { bool isNew = true; address token = unpackTakerAmounts ? order.taker_tokens[i][j] : order.maker_tokens[i][j]; if (order.commands[commandsInd + j] == 0x04) { // Commands.NATIVE_TRANSFER=0x04 token = NATIVE_TOKEN; } uint256 amount = unpackTakerAmounts ? order.taker_amounts[i][j] : ( oldAggregateQuote.useOldAmount ? oldAggregateQuote.makerAmounts[i][j] : order.maker_amounts[i][j] ); for (uint256 k; k < uniqueTokensCnt; ++k) { if (tokens[k] == token) { amounts[k] += amount; isNew = false; break; } } if (isNew) { tokens[uniqueTokensCnt] = token; amounts[uniqueTokensCnt++] = amount; } } } if (unpackTakerAmounts) { commandsInd += order.taker_tokens[i].length; } else { commandsInd += order.maker_tokens[i].length + order.taker_tokens[i].length; } } assembly { mstore(tokens, uniqueTokensCnt) mstore(amounts, uniqueTokensCnt) } } /// @notice Pack 2D array of integers into tightly packed bytes for hashing function _encodeTightlyPackedNestedInt(uint256[][] memory nestedArray) private pure returns (bytes memory encoded) { uint nestedArrayLen = nestedArray.length; for (uint i; i < nestedArrayLen; ++i) { encoded = abi.encodePacked(encoded, keccak256(abi.encodePacked(nestedArray[i]))); } return encoded; } /// @notice Pack 2D array of addresses into tightly packed bytes for hashing function _encodeTightlyPackedNested(address[][] memory nestedArray) private pure returns (bytes memory encoded) { uint nestedArrayLen = nestedArray.length; for (uint i; i < nestedArrayLen; ++i) { encoded = abi.encodePacked(encoded, keccak256(abi.encodePacked(nestedArray[i]))); } return encoded; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "../interfaces/IPermit2.sol"; /// @notice Struct for many-to-one or one-to-many trade with one maker struct BlendMultiOrder { uint256 expiry; address taker_address; address maker_address; uint256 maker_nonce; address[] taker_tokens; address[] maker_tokens; uint256[] taker_amounts; uint256[] maker_amounts; address receiver; bytes commands; uint256 flags; } library BlendMultiOrderLib { bytes internal constant ORDER_TYPE = abi.encodePacked( "MultiOrder(uint64 partner_id,uint256 expiry,address taker_address,address maker_address,uint256 maker_nonce,address[] taker_tokens,address[] maker_tokens,uint256[] taker_amounts,uint256[] maker_amounts,address receiver,bytes commands,bytes32 hooksHash)" ); bytes32 internal constant ORDER_TYPE_HASH = keccak256(ORDER_TYPE); string internal constant PERMIT2_ORDER_TYPE = string( abi.encodePacked("MultiOrder witness)", ORDER_TYPE, "TokenPermissions(address token,uint256 amount)") ); address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /// @notice hash the given order using same schema as in BebopBlend contract /// @param order the order to hash /// @param updatedMakerAmounts amounts that taker signed /// @param updatedMakerNonce nonce that taker signed /// @return the eip-712 order hash function hash( BlendMultiOrder memory order, uint256[] memory updatedMakerAmounts, uint256 updatedMakerNonce, bytes32 hooksHash ) internal pure returns (bytes32) { uint64 partnerId = uint64(order.flags >> 64); return keccak256( abi.encode( ORDER_TYPE_HASH, partnerId, order.expiry, order.taker_address, order.maker_address, updatedMakerNonce, keccak256(abi.encodePacked(order.taker_tokens)), keccak256(abi.encodePacked(order.maker_tokens)), keccak256(abi.encodePacked(order.taker_amounts)), keccak256(abi.encodePacked(updatedMakerAmounts)), order.receiver, keccak256(order.commands), hooksHash ) ); } function toBatchPermit2(BlendMultiOrder memory order) internal pure returns (IPermit2.PermitBatchTransferFrom memory) { IPermit2.TokenPermissions[] memory permitted = new IPermit2.TokenPermissions[](order.taker_tokens.length); for (uint i; i < order.taker_tokens.length; ++i) { permitted[i] = IPermit2.TokenPermissions(order.taker_tokens[i], order.taker_amounts[i]); } return IPermit2.PermitBatchTransferFrom(permitted, order.flags >> 128, order.expiry); } function toSignatureTransferDetails( BlendMultiOrder memory order, address receiver ) internal pure returns (IPermit2.SignatureTransferDetails[] memory) { IPermit2.SignatureTransferDetails[] memory details = new IPermit2.SignatureTransferDetails[](order.taker_tokens.length); for (uint i; i < order.taker_tokens.length; ++i) { details[i] = IPermit2.SignatureTransferDetails(receiver, order.taker_amounts[i]); } return details; } /// @notice Get maker tokens from the order /// replace all tokens with command=0x04(Commands.NATIVE_TRANSFER) with native token address function getMakerTokens(BlendMultiOrder memory order) internal pure returns (address[] memory makerTokens) { makerTokens = new address[](order.maker_tokens.length); for (uint i; i < order.maker_tokens.length; ++i) { makerTokens[i] = order.commands[i] == 0x04 ? NATIVE_TOKEN : order.maker_tokens[i]; } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "../interfaces/IPermit2.sol"; /// @notice BebopBlend struct for one-to-one trade with one maker struct BlendSingleOrder { uint256 expiry; address taker_address; address maker_address; uint256 maker_nonce; address taker_token; address maker_token; uint256 taker_amount; uint256 maker_amount; address receiver; uint256 packed_commands; uint256 flags; } library BlendSingleOrderLib { bytes internal constant ORDER_TYPE = abi.encodePacked( "SingleOrder(uint64 partner_id,uint256 expiry,address taker_address,address maker_address,uint256 maker_nonce,address taker_token,address maker_token,uint256 taker_amount,uint256 maker_amount,address receiver,uint256 packed_commands,bytes32 hooksHash)" ); bytes32 internal constant ORDER_TYPE_HASH = keccak256(ORDER_TYPE); string internal constant PERMIT2_ORDER_TYPE = string( abi.encodePacked("SingleOrder witness)", ORDER_TYPE, "TokenPermissions(address token,uint256 amount)") ); /// @notice hash the given order using same schema as in BebopBlend contract /// @param order the order to hash /// @param updatedMakerAmount amount that taker signed /// @param updatedMakerNonce nonce that taker signed /// @return the eip-712 order hash function hash( BlendSingleOrder memory order, uint256 updatedMakerAmount, uint256 updatedMakerNonce, bytes32 hooksHash ) internal pure returns (bytes32) { uint64 partnerId = uint64(order.flags >> 64); return keccak256( abi.encode( ORDER_TYPE_HASH, partnerId, order.expiry, order.taker_address, order.maker_address, updatedMakerNonce, order.taker_token, order.maker_token, order.taker_amount, updatedMakerAmount, order.receiver, order.packed_commands, hooksHash ) ); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "../libraries/JamInteraction.sol"; /// @title JamHooks /// @notice JamHooks is a library for managing pre and post interactions library JamHooks { bytes32 internal constant EMPTY_HOOKS_HASH = bytes32(0); /// @dev Data structure for pre and post interactions struct Def { JamInteraction.Data[] beforeSettle; JamInteraction.Data[] afterSettle; } function hash(Def memory hooks) internal pure returns (bytes32) { if (hooks.afterSettle.length == 0 && hooks.beforeSettle.length == 0){ return EMPTY_HOOKS_HASH; } return keccak256(abi.encode(hooks)); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "../interfaces/IJamBalanceManager.sol"; import "../base/Errors.sol"; library JamInteraction { /// @dev Data representing an interaction on the chain struct Data { bool result; // If the interaction is required to succeed address to; uint256 value; bytes data; } function runInteractions(Data[] calldata interactions, IJamBalanceManager balanceManager) internal returns (bool) { for (uint i; i < interactions.length; ++i) { Data calldata interaction = interactions[i]; require(interaction.to != address(balanceManager), CallToBalanceManagerNotAllowed()); (bool execResult,) = payable(interaction.to).call{ value: interaction.value }(interaction.data); if (!execResult && interaction.result) return false; } return true; } function runInteractionsM(Data[] memory interactions, IJamBalanceManager balanceManager) internal returns (bool) { for (uint i; i < interactions.length; ++i) { Data memory interaction = interactions[i]; require(interaction.to != address(balanceManager), CallToBalanceManagerNotAllowed()); (bool execResult,) = payable(interaction.to).call{ value: interaction.value }(interaction.data); if (!execResult && interaction.result) return false; } return true; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.27; import "../interfaces/IPermit2.sol"; import "./JamHooks.sol"; import "../external-libs/PermitHash.sol"; /// @dev Data representing a Jam Order. struct JamOrder { address taker; address receiver; uint256 expiry; uint256 exclusivityDeadline; // if block.timestamp > exclusivityDeadline, then order can be executed by any executor uint256 nonce; address executor; // only msg.sender=executor is allowed to execute (if executor=address(0), then order can be executed by anyone) uint256 partnerInfo; // partnerInfo is a packed struct of [partnerAddress,partnerFee,protocolFee] address[] sellTokens; address[] buyTokens; uint256[] sellAmounts; uint256[] buyAmounts; bool usingPermit2; // this field is excluded from ORDER_TYPE, so taker doesnt need to sign it } /// @title JamOrderLib library JamOrderLib { address internal constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; bytes internal constant ORDER_TYPE = abi.encodePacked( "JamOrder(address taker,address receiver,uint256 expiry,uint256 exclusivityDeadline,uint256 nonce,address executor,uint256 partnerInfo,address[] sellTokens,address[] buyTokens,uint256[] sellAmounts,uint256[] buyAmounts,bytes32 hooksHash)" ); bytes32 internal constant ORDER_TYPE_HASH = keccak256(ORDER_TYPE); string internal constant PERMIT2_ORDER_TYPE = string( abi.encodePacked("JamOrder witness)", ORDER_TYPE, "TokenPermissions(address token,uint256 amount)") ); /// @notice hash the given order /// @param order the order to hash /// @return the eip-712 order hash function hash(JamOrder calldata order, bytes32 hooksHash) internal pure returns (bytes32) { return keccak256( abi.encode( ORDER_TYPE_HASH, order.taker, order.receiver, order.expiry, order.exclusivityDeadline, order.nonce, order.executor, order.partnerInfo, keccak256(abi.encodePacked(order.sellTokens)), keccak256(abi.encodePacked(order.buyTokens)), keccak256(abi.encodePacked(order.sellAmounts)), keccak256(abi.encodePacked(order.buyAmounts)), hooksHash ) ); } function toBatchPermit2(JamOrder calldata order) internal pure returns (IPermit2.PermitBatchTransferFrom memory) { IPermit2.TokenPermissions[] memory permitted = new IPermit2.TokenPermissions[](order.sellTokens.length); for (uint i; i < order.sellTokens.length; ++i) { permitted[i] = IPermit2.TokenPermissions(order.sellTokens[i], order.sellAmounts[i]); } return IPermit2.PermitBatchTransferFrom(permitted, order.nonce, order.expiry); } function toSignatureTransferDetails( JamOrder calldata order, address receiver ) internal pure returns (IPermit2.SignatureTransferDetails[] memory details) { details = new IPermit2.SignatureTransferDetails[](order.sellTokens.length); for (uint i; i < order.sellTokens.length; ++i) { details[i] = IPermit2.SignatureTransferDetails(receiver, order.sellAmounts[i]); } } function permit2OrderHash(JamOrder calldata order, bytes32 hooksHash, address spender) internal pure returns (bytes32) { return PermitHash.hashWithWitness(toBatchPermit2(order), hash(order, hooksHash), PERMIT2_ORDER_TYPE, spender); } }
{ "evmVersion": "paris", "libraries": {}, "optimizer": { "enabled": true, "runs": 1239 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "viaIR": true }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_permit2","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[{"components":[{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"taker_address","type":"address"},{"internalType":"address","name":"maker_address","type":"address"},{"internalType":"uint256","name":"maker_nonce","type":"uint256"},{"internalType":"address","name":"taker_token","type":"address"},{"internalType":"address","name":"maker_token","type":"address"},{"internalType":"uint256","name":"taker_amount","type":"uint256"},{"internalType":"uint256","name":"maker_amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"packed_commands","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"}],"internalType":"struct BlendSingleOrder","name":"order","type":"tuple"},{"components":[{"internalType":"bool","name":"useOldAmount","type":"bool"},{"internalType":"uint256","name":"makerAmount","type":"uint256"},{"internalType":"uint256","name":"makerNonce","type":"uint256"}],"internalType":"struct IBebopBlend.OldSingleQuote","name":"oldSingleQuote","type":"tuple"},{"internalType":"bytes","name":"takerSignature","type":"bytes"},{"internalType":"address","name":"takerAddress","type":"address"},{"internalType":"bytes32","name":"hooksHash","type":"bytes32"}],"name":"transferTokenForBlendSingleOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"}],"name":"transferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"taker_address","type":"address"},{"internalType":"address[]","name":"maker_addresses","type":"address[]"},{"internalType":"uint256[]","name":"maker_nonces","type":"uint256[]"},{"internalType":"address[][]","name":"taker_tokens","type":"address[][]"},{"internalType":"address[][]","name":"maker_tokens","type":"address[][]"},{"internalType":"uint256[][]","name":"taker_amounts","type":"uint256[][]"},{"internalType":"uint256[][]","name":"maker_amounts","type":"uint256[][]"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes","name":"commands","type":"bytes"},{"internalType":"uint256","name":"flags","type":"uint256"}],"internalType":"struct BlendAggregateOrder","name":"order","type":"tuple"},{"components":[{"internalType":"bool","name":"useOldAmount","type":"bool"},{"internalType":"uint256[][]","name":"makerAmounts","type":"uint256[][]"},{"internalType":"uint256[]","name":"makerNonces","type":"uint256[]"}],"internalType":"struct IBebopBlend.OldAggregateQuote","name":"oldAggregateQuote","type":"tuple"},{"internalType":"bytes","name":"takerSignature","type":"bytes"},{"internalType":"address","name":"takerAddress","type":"address"},{"internalType":"bytes32","name":"hooksHash","type":"bytes32"}],"name":"transferTokensForAggregateBebopOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"taker_address","type":"address"},{"internalType":"address","name":"maker_address","type":"address"},{"internalType":"uint256","name":"maker_nonce","type":"uint256"},{"internalType":"address[]","name":"taker_tokens","type":"address[]"},{"internalType":"address[]","name":"maker_tokens","type":"address[]"},{"internalType":"uint256[]","name":"taker_amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"maker_amounts","type":"uint256[]"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes","name":"commands","type":"bytes"},{"internalType":"uint256","name":"flags","type":"uint256"}],"internalType":"struct BlendMultiOrder","name":"order","type":"tuple"},{"components":[{"internalType":"bool","name":"useOldAmount","type":"bool"},{"internalType":"uint256[]","name":"makerAmounts","type":"uint256[]"},{"internalType":"uint256","name":"makerNonce","type":"uint256"}],"internalType":"struct IBebopBlend.OldMultiQuote","name":"oldMultiQuote","type":"tuple"},{"internalType":"bytes","name":"takerSignature","type":"bytes"},{"internalType":"address","name":"takerAddress","type":"address"},{"internalType":"bytes32","name":"hooksHash","type":"bytes32"}],"name":"transferTokensForMultiBebopOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"taker","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"exclusivityDeadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"uint256","name":"partnerInfo","type":"uint256"},{"internalType":"address[]","name":"sellTokens","type":"address[]"},{"internalType":"address[]","name":"buyTokens","type":"address[]"},{"internalType":"uint256[]","name":"sellAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"buyAmounts","type":"uint256[]"},{"internalType":"bool","name":"usingPermit2","type":"bool"}],"internalType":"struct JamOrder","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"hooksHash","type":"bytes32"},{"internalType":"address","name":"receiver","type":"address"}],"name":"transferTokensWithPermit2","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c0346100bd57601f612ad838819003918201601f19168301916001600160401b038311848410176100c25780849260409485528339810103126100bd57610052602061004b836100d8565b92016100d8565b6080919091526001600160a01b031660a0526040516129eb90816100ed82396080518181816103b001528181610c140152818161109a015281816114e80152818161184a0152611ad7015260a051818181610c52015281816110cb015281816118200152611b150152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036100bd5756fe6080604052600436101561001257600080fd5b60003560e01c806357c3af1e146100675780635abff4df1461006257806365221a021461005d57806377c19c1f146100585763fbfa3c5b1461005357600080fd5b610a27565b6107e5565b61050c565b610337565b34610141573660031901610220811261014157610160136101415761008a6101bb565b60043581526100976101fc565b60208201526100a4610209565b604082015260643560608201526100b9610216565b60808201526100c6610223565b60a082015260c43560c082015260e43560e08201526100e3610230565b610100820152610124356101208201526101443561014082015261010636610271565b906101c4359167ffffffffffffffff83116101415761012c61013f9336906004016102af565b61013461023e565b916102043593610c0b565b005b600080fd5b634e487b7160e01b600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761017857604052565b610146565b6040810190811067ffffffffffffffff82111761017857604052565b90601f8019910116810190811067ffffffffffffffff82111761017857604052565b604051906101cb61016083610199565b565b604051906101cb604083610199565b604051906101cb606083610199565b6001600160a01b0381160361014157565b602435906101cb826101eb565b604435906101cb826101eb565b608435906101cb826101eb565b60a435906101cb826101eb565b61010435906101cb826101eb565b6101e435906101cb826101eb565b606435906101cb826101eb565b35906101cb826101eb565b3590811515820361014157565b606090610163190112610141576040519061028b8261015c565b8161016435801515810361014157815261018435602082015260406101a435910152565b81601f820112156101415780359067ffffffffffffffff821161017857604051926102e4601f8401601f191660200185610199565b8284526020838301011161014157816000926020809301838601378301015290565b9181601f840112156101415782359167ffffffffffffffff8311610141576020808501948460051b01011161014157565b346101415760803660031901126101415760043567ffffffffffffffff811161014157610368903690600401610306565b9060243567ffffffffffffffff811161014157610389903690600401610306565b60449391933590610399826101eb565b606435926103a6846101eb565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016946103dc863314610bda565b60005b8281106103e857005b87868686868673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6104256104196104148a868661106b565b611080565b6001600160a01b031690565b1461045c578661045695936104496104196104148460019c9b999761044f9761106b565b9561106b565b3592611f0a565b016103df565b505050508891506001600160a01b03160361047a575b600190610456565b61048581858a61106b565b3590873b15610141576040517f7c317e0f0000000000000000000000000000000000000000000000000000000081526001600160a01b03881660048201526024810192909252600082604481838c5af1918215610507576001926104ec575b509050610472565b806104fb600061050193610199565b80610f88565b386104e4565b611049565b346101415760803660031901126101415760043567ffffffffffffffff81116101415761018060031982360301126101415760243567ffffffffffffffff811161014157366023820112156101415780600401359167ffffffffffffffff83116101415736602484840101116101415761013f9260443591602461058e61024c565b94019060040161108a565b67ffffffffffffffff81116101785760051b60200190565b9080601f830112156101415781356105c881610599565b926105d66040519485610199565b81845260208085019260051b82010192831161014157602001905b8282106105fe5750505090565b60208091833561060d816101eb565b8152019101906105f1565b9080601f8301121561014157813561062f81610599565b9261063d6040519485610199565b81845260208085019260051b82010192831161014157602001905b8282106106655750505090565b8135815260209182019101610658565b9080601f8301121561014157813561068c81610599565b9261069a6040519485610199565b81845260208085019260051b820101918383116101415760208201905b8382106106c657505050505090565b813567ffffffffffffffff8111610141576020916106e9878480948801016105b1565b8152019101906106b7565b9080601f8301121561014157813561070b81610599565b926107196040519485610199565b81845260208085019260051b820101918383116101415760208201905b83821061074557505050505090565b813567ffffffffffffffff81116101415760209161076887848094880101610618565b815201910190610736565b9190606083820312610141576040519061078c8261015c565b819361079781610264565b8352602081013567ffffffffffffffff811161014157826107b99183016106f4565b602084015260408101359167ffffffffffffffff8311610141576040926107e09201610618565b910152565b346101415760a03660031901126101415760043567ffffffffffffffff81116101415761016060031982360301126101415761081f6101bb565b908060040135825261083360248201610259565b6020830152604481013567ffffffffffffffff81116101415761085c90600436918401016105b1565b6040830152606481013567ffffffffffffffff8111610141576108859060043691840101610618565b6060830152608481013567ffffffffffffffff8111610141576108ae9060043691840101610675565b608083015260a481013567ffffffffffffffff8111610141576108d79060043691840101610675565b60a083015260c481013567ffffffffffffffff81116101415761090090600436918401016106f4565b60c083015260e481013567ffffffffffffffff81116101415761092990600436918401016106f4565b60e083015261093b6101048201610259565b6101008301526101248101359067ffffffffffffffff82116101415761096a61014492600436918401016102af565b610120840152013561014082015260243567ffffffffffffffff811161014157610998903690600401610773565b906044359167ffffffffffffffff8311610141576109bd61013f9336906004016102af565b6109c561024c565b91608435936114d9565b91909160608184031261014157604051906109e98261015c565b81936109f482610264565b835260208201359167ffffffffffffffff831161014157610a1b6040939284938301610618565b60208501520135910152565b346101415760a03660031901126101415760043567ffffffffffffffff811161014157610160600319823603011261014157610a616101bb565b9080600401358252610a7560248201610259565b6020830152610a8660448201610259565b604083015260648101356060830152608481013567ffffffffffffffff811161014157610ab990600436918401016105b1565b608083015260a481013567ffffffffffffffff811161014157610ae290600436918401016105b1565b60a083015260c481013567ffffffffffffffff811161014157610b0b9060043691840101610618565b60c083015260e481013567ffffffffffffffff811161014157610b349060043691840101610618565b60e0830152610b466101048201610259565b6101008301526101248101359067ffffffffffffffff821161014157610b7561014492600436918401016102af565b610120840152013561014082015260243567ffffffffffffffff811161014157610ba39036906004016109cf565b906044359167ffffffffffffffff831161014157610bc861013f9336906004016102af565b610bd061024c565b9160843593611ad0565b15610be157565b7f48f5c3ed0000000000000000000000000000000000000000000000000000000060005260046000fd5b90929193610cfe7f000000000000000000000000000000000000000000000000000000000000000091610c486001600160a01b0384163314610bda565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693610c8760808201516001600160a01b031690565b9660c082018051610ca8610c996101cd565b6001600160a01b03909b168b52565b60208a015261014083015160801c835190610cc16101dc565b9a8b5260208b015260408a015251610ce9610cda6101cd565b6001600160a01b039097168752565b60208601526040602082015191015191611e40565b94610d07610ed8565b94833b1561014157610d4e600096928793604051998a98899788967f137c29fe00000000000000000000000000000000000000000000000000000000885260048801610fb8565b03925af1801561050757610d5f5750565b806104fb60006101cb93610199565b6040517f53696e676c654f726465722875696e74363420706172746e65725f69642c756960208201527f6e74323536206578706972792c616464726573732074616b65725f616464726560408201527f73732c61646472657373206d616b65725f616464726573732c75696e7432353660608201527f206d616b65725f6e6f6e63652c616464726573732074616b65725f746f6b656e60808201527f2c61646472657373206d616b65725f746f6b656e2c75696e743235362074616b60a08201527f65725f616d6f756e742c75696e74323536206d616b65725f616d6f756e742c6160c08201527f6464726573732072656365697665722c75696e74323536207061636b65645f6360e08201527f6f6d6d616e64732c6279746573333220686f6f6b73486173682900000000000061010082015260fa8152610eb261011a82610199565b90565b60005b838110610ec85750506000910152565b8181015183820152602001610eb8565b6034610eb2610ee5610d6e565b610f7a6040519384927f53696e676c654f72646572207769746e657373290000000000000000000000006020850152610f278151809260208588019101610eb5565b830101602e907f546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c7581527f696e7432353620616d6f756e742900000000000000000000000000000000000060208201520190565b03601f198101835282610199565b600091031261014157565b90602091610fac81518092818552858086019101610eb5565b601f01601f1916010190565b949161103a9361101b6001600160a01b03926040610eb29a9895610ff08b8251602080916001600160a01b0381511684520151910152565b6020818101518c84015291015160608b015281516001600160a01b031660808b0152015160a0890152565b1660c086015260e0850152610140610100850152610140840190610f93565b91610120818403910152610f93565b6040513d6000823e3d90fd5b634e487b7160e01b600052603260045260246000fd5b919081101561107b5760051b0190565b611055565b35610eb2816101eb565b9190946110c16001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163314610bda565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916110f4611fcc565b5060e084019261110e6111078587611fec565b9050612022565b956000986101208701995b6111238789611fec565b905081101561119257808b6111568261114961114f6104146001978f8f61114991611fec565b9061106b565b938d611fec565b356111716111626101cd565b6001600160a01b039093168352565b6020820152611180828c612080565b5261118b818b612080565b5001611119565b509296976111c9919499506111d992955060808701356040880135906111b66101dc565b9a8b5260208b015260408a015286612094565b926111d386611080565b95612191565b956111e2611353565b843b15610141576000968793610d4e926040519a8b998a98899763fe8ec1a760e01b895260048901611464565b6040517f4a616d4f7264657228616464726573732074616b65722c61646472657373207260208201527f656365697665722c75696e74323536206578706972792c75696e74323536206560408201527f78636c75736976697479446561646c696e652c75696e74323536206e6f6e636560608201527f2c61646472657373206578656375746f722c75696e7432353620706172746e6560808201527f72496e666f2c616464726573735b5d2073656c6c546f6b656e732c616464726560a08201527f73735b5d20627579546f6b656e732c75696e743235365b5d2073656c6c416d6f60c08201527f756e74732c75696e743235365b5d20627579416d6f756e74732c62797465733360e08201527f3220686f6f6b734861736829000000000000000000000000000000000000000061010082015260ec8152610eb261010c82610199565b6031610eb261136061120f565b610f7a6040519384927f4a616d4f72646572207769746e657373290000000000000000000000000000006020850152610f278151809260208588019101610eb5565b90606081019180519260608352835180915260206080840194019060005b8181106113e0575050506040816020829301516020850152015191015290565b90919460206040826114086001948a51602080916001600160a01b0381511684520151910152565b0196019291016113c0565b906020808351928381520192019060005b8181106114315750505090565b90919260206040826114596001948851602080916001600160a01b0381511684520151910152565b019401929101611424565b959290948795946001600160a01b0361149c6114b59561148f60209c9960c08d5260c08d01906113a2565b908b82038d8d0152611413565b9316604089015260608801528682036080880152610f93565b9360a0818603910152818452848401376000828201840152601f01601f1916010190565b949361150f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163314610bda565b600092839484955b604089015151871015611548576115406001916115388960808d0151612080565b515190612351565b960195611517565b93979691945091945061156361155d84612363565b93612363565b936000926000986000995b60408a0151518b10156117fc5761158d906115388c60a08d0151612080565b8a8a61159d826080830151612080565b515160005b8181106115c7575050916115386115bf9260806001950151612080565b9a019961156e565b917f080000000000000000000000000000000000000000000000000000000000000091935061164f6116296101207fff000000000000000000000000000000000000000000000000000000000000009301516116238689612351565b90612395565b517fff000000000000000000000000000000000000000000000000000000000000001690565b16141580156117f4575b61166a575b6001018c918c916115a2565b8c8c6001918361169861168b82611685856080880151612080565b51612080565b516001600160a01b031690565b917f04000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000006116f26116298b611623876101208b015192612351565b16146117d8575b6117148f94968f928f959497989060c0611685920151612080565b51936000905b84821061176f575b5050600195611737575b50505050905061165e565b6117529261174491612080565b906001600160a01b03169052565b61176561175e8b6123a6565b9a8d612080565b523889818c61172c565b9092949596939161168b8461178392612080565b6001600160a01b038087169116146117a7575050600101918c8c929594938f61171a565b9092506117cd826117c7876117c160019a99989686612080565b51612351565b92612080565b528c6000958f611722565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92506116f9565b506000611659565b5093611880939950979095969197808652875261186f611847886001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001697846123b5565b977f000000000000000000000000000000000000000000000000000000000000000090612455565b936040602082015191015191612528565b94611889611a23565b94833b1561014157610d4e600096928793604051998a988997889663fe8ec1a760e01b885260048801611a72565b6040517f4167677265676174654f726465722875696e74363420706172746e65725f696460208201527f2c75696e74323536206578706972792c616464726573732074616b65725f616460408201527f64726573732c616464726573735b5d206d616b65725f6164647265737365732c60608201527f75696e743235365b5d206d616b65725f6e6f6e6365732c616464726573735b5d60808201527f5b5d2074616b65725f746f6b656e732c616464726573735b5d5b5d206d616b6560a08201527f725f746f6b656e732c75696e743235365b5d5b5d2074616b65725f616d6f756e60c08201527f74732c75696e743235365b5d5b5d206d616b65725f616d6f756e74732c61646460e08201527f726573732072656365697665722c627974657320636f6d6d616e64732c6279746101008201527f6573333220686f6f6b734861736829000000000000000000000000000000000061012082015261010f8152610eb261012f82610199565b6037610eb2611a306118b7565b610f7a6040519384927f4167677265676174654f72646572207769746e657373290000000000000000006020850152610f278151809260208588019101610eb5565b9490936001600160a01b03611aa9611ac29594611a9b610eb29a9860c08b5260c08b01906113a2565b9089820360208b0152611413565b9316604087015260608601528482036080860152610f93565b9160a0818403910152610f93565b94909392917f000000000000000000000000000000000000000000000000000000000000000092611b0b6001600160a01b0385163314610bda565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016611b3d611fcc565b506080880196611b4e885151612022565b9660009960c081019a5b8a518051821015611bac57908c611b7f82611b7861168b82600197612080565b9251612080565b51611b8b6111626101cd565b6020820152611b9a828d612080565b52611ba5818c612080565b5001611b58565b50509194985091949850611beb611bfc9396611bcd61014084015160801c90565b835190611bd86101dc565b9a8b5260208b015260408a0152826126b9565b936040602082015191015191612735565b94611889611d49565b6040517f4d756c74694f726465722875696e74363420706172746e65725f69642c75696e60208201527f74323536206578706972792c616464726573732074616b65725f61646472657360408201527f732c61646472657373206d616b65725f616464726573732c75696e743235362060608201527f6d616b65725f6e6f6e63652c616464726573735b5d2074616b65725f746f6b6560808201527f6e732c616464726573735b5d206d616b65725f746f6b656e732c75696e74323560a08201527f365b5d2074616b65725f616d6f756e74732c75696e743235365b5d206d616b6560c08201527f725f616d6f756e74732c616464726573732072656365697665722c627974657360e08201527f20636f6d6d616e64732c6279746573333220686f6f6b7348617368290000000061010082015260fc8152610eb261011c82610199565b6033610eb2611d56611c05565b610f7a6040519384927f4d756c74694f72646572207769746e65737329000000000000000000000000006020850152610f278151809260208588019101610eb5565b611da0610d6e565b6020815191012090565b9a98969492909d9c9b99979593916101a08c019e8c5267ffffffffffffffff1660208c015260408b01526001600160a01b031660608a01526001600160a01b0316608089015260a08801526001600160a01b031660c087015260e08601611e18916001600160a01b03169052565b6101008501526101208401526001600160a01b03166101408301526101608201526101800152565b909161014082015160401c611e5c9067ffffffffffffffff1690565b93611e65611d98565b918351936020810151611e7e906001600160a01b031690565b956040820151611e94906001600160a01b031690565b926080830151611eaa906001600160a01b031690565b60a08401516001600160a01b03169060c085015192610100860151611ed5906001600160a01b031690565b956101200151966040519b8c9b60208d019e8f9c611ef29d611daa565b03601f1981018252611f049082610199565b51902090565b9060006064926020956001600160a01b03839681604051967f23b872dd00000000000000000000000000000000000000000000000000000000885216600487015216602485015260448401525af13d15601f3d1160016000511416171615611f6e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b60405190611fd98261015c565b6000604083606081528260208201520152565b903590601e1981360301821215610141570180359067ffffffffffffffff821161014157602001918160051b3603831361014157565b9061202c82610599565b6120396040519182610199565b828152809261204a601f1991610599565b019060005b82811061205b57505050565b60209060405161206a8161017d565b600081526000838201528282850101520161204f565b805182101561107b5760209160051b010190565b9060e08201916120a76111078483611fec565b9360005b6120b58584611fec565b9050811015612113576001816120d66120b593611149610120880188611fec565b35604051906120e48261017d565b6001600160a01b038816825260208201526120ff828a612080565b5261210a8189612080565b500190506120ab565b5092505050565b611da061120f565b9060005b8181106121335750505090565b9091926020806001926001600160a01b03873561214f816101eb565b168152019401929101612126565b91907f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81116101415760051b809282370190565b61219961211a565b916121a382611080565b926121b060208401611080565b91604084013593606081013590608081013560a082016121cf90611080565b60c08301356121e160e0850185611fec565b9060405180916020820180946121f692612122565b03601f19810182526122089082610199565b5190209161221a610100860186611fec565b90604051809160208201809461222f92612122565b03601f19810182526122419082610199565b51902093612253610120870187611fec565b9060405180916020820180946122689261215d565b03601f198101825261227a9082610199565b51902095610140810161228c91611fec565b9060405180916020820180946122a19261215d565b03601f19810182526122b39082610199565b519020966040519b8c9b60208d019e8f9c611ef29d9a98969492909d9c9b99979593916101a08c019e8c526001600160a01b031660208c01526001600160a01b031660408b015260608a0152608089015260a08801526001600160a01b031660c087015260e08601526101008501526101208401526101408301526101608201526101800152565b634e487b7160e01b600052601160045260246000fd5b9190820180921161235e57565b61233b565b9061236d82610599565b61237a6040519182610199565b828152809261238b601f1991610599565b0190602036910137565b90815181101561107b570160200190565b600019811461235e5760010190565b9291906123c0611fcc565b506123cb8151612022565b9260005b825181101561242657806001600160a01b036123ed60019386612080565b51166123f98287612080565b516124056111626101cd565b60208201526124148288612080565b5261241f8187612080565b50016123cf565b509391505061243a61014082015160801c90565b9051906124456101dc565b9283526020830152604082015290565b906124608251612022565b9160005b81518110156124b5578061247a60019284612080565b51604051906124888261017d565b6001600160a01b038616825260208201526124a38287612080565b526124ae8186612080565b5001612464565b50505090565b611da06118b7565b805160209091019060005b8181106124db5750505090565b82516001600160a01b03168452602093840193909201916001016124ce565b805160209091019060005b8181106125125750505090565b8251845260209384019390920191600101612505565b909161014082015161253a9060401c90565b67ffffffffffffffff169361254d6124bb565b918351936020810151612566906001600160a01b031690565b9560408201516040518060208101928361257f916124c3565b03601f19810182526125919082610199565b51902092604051806020810192836125a8916124fa565b03601f19810182526125ba9082610199565b5190209060808301516125cc9061290b565b8051906020012060a08401516125e19061290b565b805190602001209060c08501516125f79061296b565b80519060200120926126089061296b565b8051906020012093610100860151612626906001600160a01b031690565b95610120015180519060200120966040519b8c9b60208d019e8f9c611ef29d9a98969492909d9c9b99979593916101a08c019e8c5267ffffffffffffffff1660208c015260408b01526001600160a01b031660608a0152608089015260a088015260c087015260e08601526101008501526101208401526001600160a01b03166101408301526101608201526101800152565b919060808301926126cb845151612022565b9260005b85515181101561272557806126ea60019260c0860151612080565b51604051906126f88261017d565b6001600160a01b038716825260208201526127138288612080565b5261271e8187612080565b50016126cf565b509350505090565b611da0611c05565b906101408201516127469060401c90565b67ffffffffffffffff169361275961272d565b918351936020810151612772906001600160a01b031690565b956040820151612788906001600160a01b031690565b926080830151604051806020810192836127a1916124c3565b03601f19810182526127b39082610199565b51902060a0840151604051806020810192836127ce916124c3565b03601f19810182526127e09082610199565b5190209060c0850151604051806020810192836127fc916124fa565b03601f198101825261280e9082610199565b5190209260405180602081019283612825916124fa565b03601f19810182526128379082610199565b51902093610100860151612851906001600160a01b031690565b95610120015180519060200120966040519b8c9b60208d019e8f9c611ef29d9a98969492909d9c9b99979593916101a08c019e8c5267ffffffffffffffff1660208c015260408b01526001600160a01b031660608a01526001600160a01b0316608089015260a088015260c087015260e08601526101008501526101208401526001600160a01b03166101408301526101608201526101800152565b6020929190612903849282815194859201610eb5565b019081520190565b60609080516000905b8082106129215750505090565b909193926001906129616129358588612080565b5160405161294b81610f7a6020820180956124c3565b51902091610f7a604051938492602084016128ed565b9394920190612914565b60609080516000905b8082106129815750505090565b909193926001906129ab6129958588612080565b5160405161294b81610f7a6020820180956124fa565b939492019061297456fea26469706673582212200e61f2bd5da65278e0dc9c3a6fe1f6c1228d2d4f1bf2d5a52191ba5c84e51f0d64736f6c634300081b0033000000000000000000000000beb0b0623f66be8ce162ebdfa2ec543a522f4ea6000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c806357c3af1e146100675780635abff4df1461006257806365221a021461005d57806377c19c1f146100585763fbfa3c5b1461005357600080fd5b610a27565b6107e5565b61050c565b610337565b34610141573660031901610220811261014157610160136101415761008a6101bb565b60043581526100976101fc565b60208201526100a4610209565b604082015260643560608201526100b9610216565b60808201526100c6610223565b60a082015260c43560c082015260e43560e08201526100e3610230565b610100820152610124356101208201526101443561014082015261010636610271565b906101c4359167ffffffffffffffff83116101415761012c61013f9336906004016102af565b61013461023e565b916102043593610c0b565b005b600080fd5b634e487b7160e01b600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761017857604052565b610146565b6040810190811067ffffffffffffffff82111761017857604052565b90601f8019910116810190811067ffffffffffffffff82111761017857604052565b604051906101cb61016083610199565b565b604051906101cb604083610199565b604051906101cb606083610199565b6001600160a01b0381160361014157565b602435906101cb826101eb565b604435906101cb826101eb565b608435906101cb826101eb565b60a435906101cb826101eb565b61010435906101cb826101eb565b6101e435906101cb826101eb565b606435906101cb826101eb565b35906101cb826101eb565b3590811515820361014157565b606090610163190112610141576040519061028b8261015c565b8161016435801515810361014157815261018435602082015260406101a435910152565b81601f820112156101415780359067ffffffffffffffff821161017857604051926102e4601f8401601f191660200185610199565b8284526020838301011161014157816000926020809301838601378301015290565b9181601f840112156101415782359167ffffffffffffffff8311610141576020808501948460051b01011161014157565b346101415760803660031901126101415760043567ffffffffffffffff811161014157610368903690600401610306565b9060243567ffffffffffffffff811161014157610389903690600401610306565b60449391933590610399826101eb565b606435926103a6846101eb565b6001600160a01b037f000000000000000000000000beb0b0623f66be8ce162ebdfa2ec543a522f4ea616946103dc863314610bda565b60005b8281106103e857005b87868686868673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6104256104196104148a868661106b565b611080565b6001600160a01b031690565b1461045c578661045695936104496104196104148460019c9b999761044f9761106b565b9561106b565b3592611f0a565b016103df565b505050508891506001600160a01b03160361047a575b600190610456565b61048581858a61106b565b3590873b15610141576040517f7c317e0f0000000000000000000000000000000000000000000000000000000081526001600160a01b03881660048201526024810192909252600082604481838c5af1918215610507576001926104ec575b509050610472565b806104fb600061050193610199565b80610f88565b386104e4565b611049565b346101415760803660031901126101415760043567ffffffffffffffff81116101415761018060031982360301126101415760243567ffffffffffffffff811161014157366023820112156101415780600401359167ffffffffffffffff83116101415736602484840101116101415761013f9260443591602461058e61024c565b94019060040161108a565b67ffffffffffffffff81116101785760051b60200190565b9080601f830112156101415781356105c881610599565b926105d66040519485610199565b81845260208085019260051b82010192831161014157602001905b8282106105fe5750505090565b60208091833561060d816101eb565b8152019101906105f1565b9080601f8301121561014157813561062f81610599565b9261063d6040519485610199565b81845260208085019260051b82010192831161014157602001905b8282106106655750505090565b8135815260209182019101610658565b9080601f8301121561014157813561068c81610599565b9261069a6040519485610199565b81845260208085019260051b820101918383116101415760208201905b8382106106c657505050505090565b813567ffffffffffffffff8111610141576020916106e9878480948801016105b1565b8152019101906106b7565b9080601f8301121561014157813561070b81610599565b926107196040519485610199565b81845260208085019260051b820101918383116101415760208201905b83821061074557505050505090565b813567ffffffffffffffff81116101415760209161076887848094880101610618565b815201910190610736565b9190606083820312610141576040519061078c8261015c565b819361079781610264565b8352602081013567ffffffffffffffff811161014157826107b99183016106f4565b602084015260408101359167ffffffffffffffff8311610141576040926107e09201610618565b910152565b346101415760a03660031901126101415760043567ffffffffffffffff81116101415761016060031982360301126101415761081f6101bb565b908060040135825261083360248201610259565b6020830152604481013567ffffffffffffffff81116101415761085c90600436918401016105b1565b6040830152606481013567ffffffffffffffff8111610141576108859060043691840101610618565b6060830152608481013567ffffffffffffffff8111610141576108ae9060043691840101610675565b608083015260a481013567ffffffffffffffff8111610141576108d79060043691840101610675565b60a083015260c481013567ffffffffffffffff81116101415761090090600436918401016106f4565b60c083015260e481013567ffffffffffffffff81116101415761092990600436918401016106f4565b60e083015261093b6101048201610259565b6101008301526101248101359067ffffffffffffffff82116101415761096a61014492600436918401016102af565b610120840152013561014082015260243567ffffffffffffffff811161014157610998903690600401610773565b906044359167ffffffffffffffff8311610141576109bd61013f9336906004016102af565b6109c561024c565b91608435936114d9565b91909160608184031261014157604051906109e98261015c565b81936109f482610264565b835260208201359167ffffffffffffffff831161014157610a1b6040939284938301610618565b60208501520135910152565b346101415760a03660031901126101415760043567ffffffffffffffff811161014157610160600319823603011261014157610a616101bb565b9080600401358252610a7560248201610259565b6020830152610a8660448201610259565b604083015260648101356060830152608481013567ffffffffffffffff811161014157610ab990600436918401016105b1565b608083015260a481013567ffffffffffffffff811161014157610ae290600436918401016105b1565b60a083015260c481013567ffffffffffffffff811161014157610b0b9060043691840101610618565b60c083015260e481013567ffffffffffffffff811161014157610b349060043691840101610618565b60e0830152610b466101048201610259565b6101008301526101248101359067ffffffffffffffff821161014157610b7561014492600436918401016102af565b610120840152013561014082015260243567ffffffffffffffff811161014157610ba39036906004016109cf565b906044359167ffffffffffffffff831161014157610bc861013f9336906004016102af565b610bd061024c565b9160843593611ad0565b15610be157565b7f48f5c3ed0000000000000000000000000000000000000000000000000000000060005260046000fd5b90929193610cfe7f000000000000000000000000beb0b0623f66be8ce162ebdfa2ec543a522f4ea691610c486001600160a01b0384163314610bda565b6001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31693610c8760808201516001600160a01b031690565b9660c082018051610ca8610c996101cd565b6001600160a01b03909b168b52565b60208a015261014083015160801c835190610cc16101dc565b9a8b5260208b015260408a015251610ce9610cda6101cd565b6001600160a01b039097168752565b60208601526040602082015191015191611e40565b94610d07610ed8565b94833b1561014157610d4e600096928793604051998a98899788967f137c29fe00000000000000000000000000000000000000000000000000000000885260048801610fb8565b03925af1801561050757610d5f5750565b806104fb60006101cb93610199565b6040517f53696e676c654f726465722875696e74363420706172746e65725f69642c756960208201527f6e74323536206578706972792c616464726573732074616b65725f616464726560408201527f73732c61646472657373206d616b65725f616464726573732c75696e7432353660608201527f206d616b65725f6e6f6e63652c616464726573732074616b65725f746f6b656e60808201527f2c61646472657373206d616b65725f746f6b656e2c75696e743235362074616b60a08201527f65725f616d6f756e742c75696e74323536206d616b65725f616d6f756e742c6160c08201527f6464726573732072656365697665722c75696e74323536207061636b65645f6360e08201527f6f6d6d616e64732c6279746573333220686f6f6b73486173682900000000000061010082015260fa8152610eb261011a82610199565b90565b60005b838110610ec85750506000910152565b8181015183820152602001610eb8565b6034610eb2610ee5610d6e565b610f7a6040519384927f53696e676c654f72646572207769746e657373290000000000000000000000006020850152610f278151809260208588019101610eb5565b830101602e907f546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c7581527f696e7432353620616d6f756e742900000000000000000000000000000000000060208201520190565b03601f198101835282610199565b600091031261014157565b90602091610fac81518092818552858086019101610eb5565b601f01601f1916010190565b949161103a9361101b6001600160a01b03926040610eb29a9895610ff08b8251602080916001600160a01b0381511684520151910152565b6020818101518c84015291015160608b015281516001600160a01b031660808b0152015160a0890152565b1660c086015260e0850152610140610100850152610140840190610f93565b91610120818403910152610f93565b6040513d6000823e3d90fd5b634e487b7160e01b600052603260045260246000fd5b919081101561107b5760051b0190565b611055565b35610eb2816101eb565b9190946110c16001600160a01b037f000000000000000000000000beb0b0623f66be8ce162ebdfa2ec543a522f4ea6163314610bda565b6001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba316916110f4611fcc565b5060e084019261110e6111078587611fec565b9050612022565b956000986101208701995b6111238789611fec565b905081101561119257808b6111568261114961114f6104146001978f8f61114991611fec565b9061106b565b938d611fec565b356111716111626101cd565b6001600160a01b039093168352565b6020820152611180828c612080565b5261118b818b612080565b5001611119565b509296976111c9919499506111d992955060808701356040880135906111b66101dc565b9a8b5260208b015260408a015286612094565b926111d386611080565b95612191565b956111e2611353565b843b15610141576000968793610d4e926040519a8b998a98899763fe8ec1a760e01b895260048901611464565b6040517f4a616d4f7264657228616464726573732074616b65722c61646472657373207260208201527f656365697665722c75696e74323536206578706972792c75696e74323536206560408201527f78636c75736976697479446561646c696e652c75696e74323536206e6f6e636560608201527f2c61646472657373206578656375746f722c75696e7432353620706172746e6560808201527f72496e666f2c616464726573735b5d2073656c6c546f6b656e732c616464726560a08201527f73735b5d20627579546f6b656e732c75696e743235365b5d2073656c6c416d6f60c08201527f756e74732c75696e743235365b5d20627579416d6f756e74732c62797465733360e08201527f3220686f6f6b734861736829000000000000000000000000000000000000000061010082015260ec8152610eb261010c82610199565b6031610eb261136061120f565b610f7a6040519384927f4a616d4f72646572207769746e657373290000000000000000000000000000006020850152610f278151809260208588019101610eb5565b90606081019180519260608352835180915260206080840194019060005b8181106113e0575050506040816020829301516020850152015191015290565b90919460206040826114086001948a51602080916001600160a01b0381511684520151910152565b0196019291016113c0565b906020808351928381520192019060005b8181106114315750505090565b90919260206040826114596001948851602080916001600160a01b0381511684520151910152565b019401929101611424565b959290948795946001600160a01b0361149c6114b59561148f60209c9960c08d5260c08d01906113a2565b908b82038d8d0152611413565b9316604089015260608801528682036080880152610f93565b9360a0818603910152818452848401376000828201840152601f01601f1916010190565b949361150f6001600160a01b037f000000000000000000000000beb0b0623f66be8ce162ebdfa2ec543a522f4ea6163314610bda565b600092839484955b604089015151871015611548576115406001916115388960808d0151612080565b515190612351565b960195611517565b93979691945091945061156361155d84612363565b93612363565b936000926000986000995b60408a0151518b10156117fc5761158d906115388c60a08d0151612080565b8a8a61159d826080830151612080565b515160005b8181106115c7575050916115386115bf9260806001950151612080565b9a019961156e565b917f080000000000000000000000000000000000000000000000000000000000000091935061164f6116296101207fff000000000000000000000000000000000000000000000000000000000000009301516116238689612351565b90612395565b517fff000000000000000000000000000000000000000000000000000000000000001690565b16141580156117f4575b61166a575b6001018c918c916115a2565b8c8c6001918361169861168b82611685856080880151612080565b51612080565b516001600160a01b031690565b917f04000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000006116f26116298b611623876101208b015192612351565b16146117d8575b6117148f94968f928f959497989060c0611685920151612080565b51936000905b84821061176f575b5050600195611737575b50505050905061165e565b6117529261174491612080565b906001600160a01b03169052565b61176561175e8b6123a6565b9a8d612080565b523889818c61172c565b9092949596939161168b8461178392612080565b6001600160a01b038087169116146117a7575050600101918c8c929594938f61171a565b9092506117cd826117c7876117c160019a99989686612080565b51612351565b92612080565b528c6000958f611722565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92506116f9565b506000611659565b5093611880939950979095969197808652875261186f611847886001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31697846123b5565b977f000000000000000000000000beb0b0623f66be8ce162ebdfa2ec543a522f4ea690612455565b936040602082015191015191612528565b94611889611a23565b94833b1561014157610d4e600096928793604051998a988997889663fe8ec1a760e01b885260048801611a72565b6040517f4167677265676174654f726465722875696e74363420706172746e65725f696460208201527f2c75696e74323536206578706972792c616464726573732074616b65725f616460408201527f64726573732c616464726573735b5d206d616b65725f6164647265737365732c60608201527f75696e743235365b5d206d616b65725f6e6f6e6365732c616464726573735b5d60808201527f5b5d2074616b65725f746f6b656e732c616464726573735b5d5b5d206d616b6560a08201527f725f746f6b656e732c75696e743235365b5d5b5d2074616b65725f616d6f756e60c08201527f74732c75696e743235365b5d5b5d206d616b65725f616d6f756e74732c61646460e08201527f726573732072656365697665722c627974657320636f6d6d616e64732c6279746101008201527f6573333220686f6f6b734861736829000000000000000000000000000000000061012082015261010f8152610eb261012f82610199565b6037610eb2611a306118b7565b610f7a6040519384927f4167677265676174654f72646572207769746e657373290000000000000000006020850152610f278151809260208588019101610eb5565b9490936001600160a01b03611aa9611ac29594611a9b610eb29a9860c08b5260c08b01906113a2565b9089820360208b0152611413565b9316604087015260608601528482036080860152610f93565b9160a0818403910152610f93565b94909392917f000000000000000000000000beb0b0623f66be8ce162ebdfa2ec543a522f4ea692611b0b6001600160a01b0385163314610bda565b6001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba316611b3d611fcc565b506080880196611b4e885151612022565b9660009960c081019a5b8a518051821015611bac57908c611b7f82611b7861168b82600197612080565b9251612080565b51611b8b6111626101cd565b6020820152611b9a828d612080565b52611ba5818c612080565b5001611b58565b50509194985091949850611beb611bfc9396611bcd61014084015160801c90565b835190611bd86101dc565b9a8b5260208b015260408a0152826126b9565b936040602082015191015191612735565b94611889611d49565b6040517f4d756c74694f726465722875696e74363420706172746e65725f69642c75696e60208201527f74323536206578706972792c616464726573732074616b65725f61646472657360408201527f732c61646472657373206d616b65725f616464726573732c75696e743235362060608201527f6d616b65725f6e6f6e63652c616464726573735b5d2074616b65725f746f6b6560808201527f6e732c616464726573735b5d206d616b65725f746f6b656e732c75696e74323560a08201527f365b5d2074616b65725f616d6f756e74732c75696e743235365b5d206d616b6560c08201527f725f616d6f756e74732c616464726573732072656365697665722c627974657360e08201527f20636f6d6d616e64732c6279746573333220686f6f6b7348617368290000000061010082015260fc8152610eb261011c82610199565b6033610eb2611d56611c05565b610f7a6040519384927f4d756c74694f72646572207769746e65737329000000000000000000000000006020850152610f278151809260208588019101610eb5565b611da0610d6e565b6020815191012090565b9a98969492909d9c9b99979593916101a08c019e8c5267ffffffffffffffff1660208c015260408b01526001600160a01b031660608a01526001600160a01b0316608089015260a08801526001600160a01b031660c087015260e08601611e18916001600160a01b03169052565b6101008501526101208401526001600160a01b03166101408301526101608201526101800152565b909161014082015160401c611e5c9067ffffffffffffffff1690565b93611e65611d98565b918351936020810151611e7e906001600160a01b031690565b956040820151611e94906001600160a01b031690565b926080830151611eaa906001600160a01b031690565b60a08401516001600160a01b03169060c085015192610100860151611ed5906001600160a01b031690565b956101200151966040519b8c9b60208d019e8f9c611ef29d611daa565b03601f1981018252611f049082610199565b51902090565b9060006064926020956001600160a01b03839681604051967f23b872dd00000000000000000000000000000000000000000000000000000000885216600487015216602485015260448401525af13d15601f3d1160016000511416171615611f6e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b60405190611fd98261015c565b6000604083606081528260208201520152565b903590601e1981360301821215610141570180359067ffffffffffffffff821161014157602001918160051b3603831361014157565b9061202c82610599565b6120396040519182610199565b828152809261204a601f1991610599565b019060005b82811061205b57505050565b60209060405161206a8161017d565b600081526000838201528282850101520161204f565b805182101561107b5760209160051b010190565b9060e08201916120a76111078483611fec565b9360005b6120b58584611fec565b9050811015612113576001816120d66120b593611149610120880188611fec565b35604051906120e48261017d565b6001600160a01b038816825260208201526120ff828a612080565b5261210a8189612080565b500190506120ab565b5092505050565b611da061120f565b9060005b8181106121335750505090565b9091926020806001926001600160a01b03873561214f816101eb565b168152019401929101612126565b91907f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81116101415760051b809282370190565b61219961211a565b916121a382611080565b926121b060208401611080565b91604084013593606081013590608081013560a082016121cf90611080565b60c08301356121e160e0850185611fec565b9060405180916020820180946121f692612122565b03601f19810182526122089082610199565b5190209161221a610100860186611fec565b90604051809160208201809461222f92612122565b03601f19810182526122419082610199565b51902093612253610120870187611fec565b9060405180916020820180946122689261215d565b03601f198101825261227a9082610199565b51902095610140810161228c91611fec565b9060405180916020820180946122a19261215d565b03601f19810182526122b39082610199565b519020966040519b8c9b60208d019e8f9c611ef29d9a98969492909d9c9b99979593916101a08c019e8c526001600160a01b031660208c01526001600160a01b031660408b015260608a0152608089015260a08801526001600160a01b031660c087015260e08601526101008501526101208401526101408301526101608201526101800152565b634e487b7160e01b600052601160045260246000fd5b9190820180921161235e57565b61233b565b9061236d82610599565b61237a6040519182610199565b828152809261238b601f1991610599565b0190602036910137565b90815181101561107b570160200190565b600019811461235e5760010190565b9291906123c0611fcc565b506123cb8151612022565b9260005b825181101561242657806001600160a01b036123ed60019386612080565b51166123f98287612080565b516124056111626101cd565b60208201526124148288612080565b5261241f8187612080565b50016123cf565b509391505061243a61014082015160801c90565b9051906124456101dc565b9283526020830152604082015290565b906124608251612022565b9160005b81518110156124b5578061247a60019284612080565b51604051906124888261017d565b6001600160a01b038616825260208201526124a38287612080565b526124ae8186612080565b5001612464565b50505090565b611da06118b7565b805160209091019060005b8181106124db5750505090565b82516001600160a01b03168452602093840193909201916001016124ce565b805160209091019060005b8181106125125750505090565b8251845260209384019390920191600101612505565b909161014082015161253a9060401c90565b67ffffffffffffffff169361254d6124bb565b918351936020810151612566906001600160a01b031690565b9560408201516040518060208101928361257f916124c3565b03601f19810182526125919082610199565b51902092604051806020810192836125a8916124fa565b03601f19810182526125ba9082610199565b5190209060808301516125cc9061290b565b8051906020012060a08401516125e19061290b565b805190602001209060c08501516125f79061296b565b80519060200120926126089061296b565b8051906020012093610100860151612626906001600160a01b031690565b95610120015180519060200120966040519b8c9b60208d019e8f9c611ef29d9a98969492909d9c9b99979593916101a08c019e8c5267ffffffffffffffff1660208c015260408b01526001600160a01b031660608a0152608089015260a088015260c087015260e08601526101008501526101208401526001600160a01b03166101408301526101608201526101800152565b919060808301926126cb845151612022565b9260005b85515181101561272557806126ea60019260c0860151612080565b51604051906126f88261017d565b6001600160a01b038716825260208201526127138288612080565b5261271e8187612080565b50016126cf565b509350505090565b611da0611c05565b906101408201516127469060401c90565b67ffffffffffffffff169361275961272d565b918351936020810151612772906001600160a01b031690565b956040820151612788906001600160a01b031690565b926080830151604051806020810192836127a1916124c3565b03601f19810182526127b39082610199565b51902060a0840151604051806020810192836127ce916124c3565b03601f19810182526127e09082610199565b5190209060c0850151604051806020810192836127fc916124fa565b03601f198101825261280e9082610199565b5190209260405180602081019283612825916124fa565b03601f19810182526128379082610199565b51902093610100860151612851906001600160a01b031690565b95610120015180519060200120966040519b8c9b60208d019e8f9c611ef29d9a98969492909d9c9b99979593916101a08c019e8c5267ffffffffffffffff1660208c015260408b01526001600160a01b031660608a01526001600160a01b0316608089015260a088015260c087015260e08601526101008501526101208401526001600160a01b03166101408301526101608201526101800152565b6020929190612903849282815194859201610eb5565b019081520190565b60609080516000905b8082106129215750505090565b909193926001906129616129358588612080565b5160405161294b81610f7a6020820180956124c3565b51902091610f7a604051938492602084016128ed565b9394920190612914565b60609080516000905b8082106129815750505090565b909193926001906129ab6129958588612080565b5160405161294b81610f7a6020820180956124fa565b939492019061297456fea26469706673582212200e61f2bd5da65278e0dc9c3a6fe1f6c1228d2d4f1bf2d5a52191ba5c84e51f0d64736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000beb0b0623f66be8ce162ebdfa2ec543a522f4ea6000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
-----Decoded View---------------
Arg [0] : _operator (address): 0xbeb0b0623f66bE8cE162EbDfA2ec543A522F4ea6
Arg [1] : _permit2 (address): 0x000000000022D473030F116dDEE9F6B43aC78BA3
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000beb0b0623f66be8ce162ebdfa2ec543a522f4ea6
Arg [1] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.