Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PMMProtocol
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "./EIP712.sol";
import "./helpers/AmountCalculator.sol";
import "./interfaces/IWETH.sol";
import "./libraries/Errors.sol";
import "./libraries/SafeERC20.sol";
import "./OrderRFQLib.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract PMMProtocol is EIP712, ReentrancyGuard {
using SafeERC20 for IERC20;
using OrderRFQLib for OrderRFQLib.OrderRFQ;
/**
* @notice Emitted when RFQ gets filled
* @param rfqId RFQ order id
* @param expiry Expiration timestamp of the order
* @param makerAsset Address of the maker asset
* @param takerAsset Address of the taker asset
* @param makerAddress Address of the maker
* @param expectedMakerAmount Expected amount of maker asset
* @param expectedTakerAmount Expected amount of taker asset
* @param filledMakerAmount Actual amount of maker asset that was transferred
* @param filledTakerAmount Actual amount of taker asset that was transferred
*/
event OrderFilledRFQ(
uint256 indexed rfqId,
uint256 expiry,
address indexed makerAsset,
address indexed takerAsset,
address makerAddress,
uint256 expectedMakerAmount,
uint256 expectedTakerAmount,
uint256 filledMakerAmount,
uint256 filledTakerAmount,
bool usePermit2
);
string private constant _NAME = "OKX Lab PMM Protocol";
string private constant _VERSION = "1.0";
uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;
uint256 private constant _MAKER_AMOUNT_FLAG = 1 << 255;
uint256 private constant _SIGNER_SMART_CONTRACT_HINT = 1 << 254;
uint256 private constant _IS_VALID_SIGNATURE_65_BYTES = 1 << 253;
uint256 private constant _UNWRAP_WETH_FLAG = 1 << 252;
uint256 private constant _SETTLE_LIMIT = 6000;
uint256 private constant _SETTLE_LIMIT_BASE = 10000;
uint256 private constant _AMOUNT_MASK =
0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff; // max uint160
IWETH private immutable _WETH;
mapping(address => mapping(uint256 => uint256)) private _invalidator;
constructor(IWETH weth) EIP712(_NAME, _VERSION) {
_WETH = weth;
}
receive() external payable {
if (msg.sender != address(_WETH))
revert Errors.RFQ_EthDepositRejected();
}
function DOMAIN_SEPARATOR() external view returns (bytes32) {
return _domainSeparatorV4();
}
function invalidatorForOrderRFQ(
address maker,
uint256 slot
) external view returns (uint256 /* result */) {
return _invalidator[maker][slot];
}
function isRfqIdUsed(
address maker,
uint64 rfqId
) external view returns (bool) {
uint256 invalidatorSlot = uint64(rfqId) >> 8;
uint256 invalidatorBits = 1 << (uint8(rfqId) & 0xff);
uint256 bitMap = _invalidator[maker][invalidatorSlot];
return (bitMap & invalidatorBits) != 0;
}
function fillOrderRFQ(
OrderRFQLib.OrderRFQ memory order,
bytes calldata signature,
uint256 flagsAndAmount
)
external
payable
returns (
uint256 /* filledMakerAmount */,
uint256 /* filledTakerAmount */,
bytes32 /* orderHash */
)
{
return fillOrderRFQTo(order, signature, flagsAndAmount, msg.sender);
}
function fillOrderRFQCompact(
OrderRFQLib.OrderRFQ memory order,
bytes32 r,
bytes32 vs,
uint256 flagsAndAmount
)
external
payable
nonReentrant
returns (
uint256 filledMakerAmount,
uint256 filledTakerAmount,
bytes32 orderHash
)
{
orderHash = order.hash(_domainSeparatorV4());
if (flagsAndAmount & _SIGNER_SMART_CONTRACT_HINT != 0) {
if (flagsAndAmount & _IS_VALID_SIGNATURE_65_BYTES != 0) {
if (
!ECDSA.isValidSignature65(
order.makerAddress,
orderHash,
r,
vs
)
) revert Errors.RFQ_BadSignature(order.rfqId);
} else {
if (
!ECDSA.isValidSignature(
order.makerAddress,
orderHash,
r,
vs
)
) revert Errors.RFQ_BadSignature(order.rfqId);
}
} else {
if (
!ECDSA.recoverOrIsValidSignature(
order.makerAddress,
orderHash,
r,
vs
)
) revert Errors.RFQ_BadSignature(order.rfqId);
}
(filledMakerAmount, filledTakerAmount) = _fillOrderRFQTo(
order,
flagsAndAmount,
msg.sender
);
emit OrderFilledRFQ(
order.rfqId,
order.expiry,
order.makerAsset,
order.takerAsset,
order.makerAddress,
order.makerAmount,
order.takerAmount,
filledMakerAmount,
filledTakerAmount,
order.usePermit2
);
}
function fillOrderRFQToWithPermit(
OrderRFQLib.OrderRFQ memory order,
bytes calldata signature,
uint256 flagsAndAmount,
address target,
bytes calldata permit
)
external
returns (
uint256 /* filledMakerAmount */,
uint256 /* filledTakerAmount */,
bytes32 /* orderHash */
)
{
IERC20(order.takerAsset).safePermit(permit);
return fillOrderRFQTo(order, signature, flagsAndAmount, target);
}
// Anyone can fill the order, including via front-running.
// This is acceptable by design and does not cause any loss to the maker.
// This function does not support deflationary or rebasing tokens.
// The protocol assumes standard token behavior with exact transfer amounts,
// which is valid for mainstream tokens typically used by market makers.
function fillOrderRFQTo(
OrderRFQLib.OrderRFQ memory order,
bytes calldata signature,
uint256 flagsAndAmount,
address target
)
public
payable
nonReentrant
returns (
uint256 filledMakerAmount,
uint256 filledTakerAmount,
bytes32 orderHash
)
{
orderHash = order.hash(_domainSeparatorV4());
if (flagsAndAmount & _SIGNER_SMART_CONTRACT_HINT != 0) {
if (
flagsAndAmount & _IS_VALID_SIGNATURE_65_BYTES != 0 &&
signature.length != 65
) revert Errors.RFQ_BadSignature(order.rfqId);
if (
!ECDSA.isValidSignature(
order.makerAddress,
orderHash,
signature
)
) revert Errors.RFQ_BadSignature(order.rfqId);
} else {
if (
!ECDSA.recoverOrIsValidSignature(
order.makerAddress,
orderHash,
signature
)
) revert Errors.RFQ_BadSignature(order.rfqId);
}
(filledMakerAmount, filledTakerAmount) = _fillOrderRFQTo(
order,
flagsAndAmount,
target
);
emit OrderFilledRFQ(
order.rfqId,
order.expiry,
order.makerAsset,
order.takerAsset,
order.makerAddress,
order.makerAmount,
order.takerAmount,
filledMakerAmount,
filledTakerAmount,
order.usePermit2
);
}
function _fillOrderRFQTo(
OrderRFQLib.OrderRFQ memory order,
uint256 flagsAndAmount,
address target
) private returns (uint256 makerAmount, uint256 takerAmount) {
if (target == address(0))
revert Errors.RFQ_ZeroTargetIsForbidden(order.rfqId);
address maker = order.makerAddress;
{
// Stack too deep
// Check time expiration
uint256 expiration = order.expiry;
if (expiration != 0 && block.timestamp > expiration)
revert Errors.RFQ_OrderExpired(order.rfqId); // solhint-disable-line not-rely-on-time
_invalidateOrder(maker, order.rfqId);
}
// user: AMM->PMM
{
// Stack too deep
uint256 orderMakerAmount = order.makerAmount;
uint256 orderTakerAmount = order.takerAmount;
uint256 amount = flagsAndAmount & _AMOUNT_MASK;
// Compute partial fill if needed
if (amount == 0) {
// zero amount means whole order
// Check if order amounts exceed uint160.max limit for Permit2 transfers
makerAmount = orderMakerAmount;
takerAmount = orderTakerAmount;
if (order.usePermit2 && makerAmount > type(uint160).max) {
revert Errors.RFQ_AmountTooLarge(order.rfqId);
}
} else if (flagsAndAmount & _MAKER_AMOUNT_FLAG != 0) {
if (amount > orderMakerAmount)
revert Errors.RFQ_MakerAmountExceeded(order.rfqId);
makerAmount = amount;
takerAmount = AmountCalculator.getTakerAmount(
orderMakerAmount,
orderTakerAmount,
makerAmount
);
} else {
if (amount > orderTakerAmount)
revert Errors.RFQ_TakerAmountExceeded(order.rfqId);
takerAmount = amount;
makerAmount = AmountCalculator.getMakerAmount(
orderMakerAmount,
orderTakerAmount,
takerAmount
);
}
}
if (makerAmount == 0 || takerAmount == 0)
revert Errors.RFQ_SwapWithZeroAmount(order.rfqId);
// Check if settlement amounts meet minimum limit (60%)
if (
makerAmount < (order.makerAmount * _SETTLE_LIMIT) / _SETTLE_LIMIT_BASE ||
takerAmount < (order.takerAmount * _SETTLE_LIMIT) / _SETTLE_LIMIT_BASE
) {
revert Errors.RFQ_SettlementAmountTooSmall(order.rfqId);
}
bool needUnwrap = order.makerAsset == address(_WETH) &&
flagsAndAmount & _UNWRAP_WETH_FLAG != 0;
// Maker => Taker
address receiver = needUnwrap ? address(this) : target;
if (order.usePermit2) {
IERC20(order.makerAsset).safeTransferFromPermit2(
maker,
receiver,
makerAmount
);
} else {
IERC20(order.makerAsset).safeTransferFrom(
maker,
receiver,
makerAmount
);
}
if (needUnwrap) {
_WETH.withdraw(makerAmount);
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = target.call{
value: makerAmount,
gas: _RAW_CALL_GAS_LIMIT
}("");
if (!success) revert Errors.RFQ_ETHTransferFailed(order.rfqId);
}
// Taker => Maker
if (order.takerAsset == address(_WETH) && msg.value > 0) {
if (msg.value != takerAmount)
revert Errors.RFQ_InvalidMsgValue(order.rfqId);
_WETH.deposit{value: takerAmount}();
_WETH.transfer(maker, takerAmount);
} else {
if (msg.value != 0) revert Errors.RFQ_InvalidMsgValue(order.rfqId);
IERC20(order.takerAsset).safeTransferFrom(
msg.sender,
maker,
takerAmount
);
}
}
/// @dev Prevents replay of RFQ orders by tracking used rfqIds with a bitmask per maker.
function _invalidateOrder(address maker, uint256 rfqId) private {
uint256 invalidatorSlot = uint64(rfqId) >> 8;
uint256 invalidatorBits = (1 << (uint8(rfqId) & 0xff));
mapping(uint256 => uint256) storage invalidatorStorage = _invalidator[
maker
];
uint256 invalidator = invalidatorStorage[invalidatorSlot];
if (invalidator & invalidatorBits == invalidatorBits)
revert Errors.RFQ_InvalidatedOrder(rfqId);
invalidatorStorage[invalidatorSlot] = invalidator | invalidatorBits;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* _Available since v3.4._
*/
import "./libraries/ECDSA.sol";
abstract contract EIP712 {
/* solhint-disable var-name-mixedcase */
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
// invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
/* solhint-enable var-name-mixedcase */
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(
typeHash,
hashedName,
hashedVersion
);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (
address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID
) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return
_buildDomainSeparator(
_TYPE_HASH,
_HASHED_NAME,
_HASHED_VERSION
);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return
keccak256(
abi.encode(
typeHash,
nameHash,
versionHash,
block.chainid,
address(this)
)
);
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(
bytes32 structHash
) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/// @title A helper contract for calculations related to order amounts
library AmountCalculator {
/// @notice Calculates maker amount
/// @return Result Floored maker amount
function getMakerAmount(
uint256 orderMakerAmount,
uint256 orderTakerAmount,
uint256 swapTakerAmount
) internal pure returns (uint256) {
return (swapTakerAmount * orderMakerAmount) / orderTakerAmount;
}
/// @notice Calculates taker amount
/// @return Result Ceiled taker amount
function getTakerAmount(
uint256 orderMakerAmount,
uint256 orderTakerAmount,
uint256 swapMakerAmount
) internal pure returns (uint256) {
return
(swapMakerAmount * orderTakerAmount + orderMakerAmount - 1) /
orderMakerAmount;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH is IERC20 {
function deposit() external payable;
function withdraw(uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
library Errors {
error RFQ_InvalidMsgValue(uint256 rfqId);
error RFQ_ETHTransferFailed(uint256 rfqId);
error RFQ_EthDepositRejected();
error RFQ_ZeroTargetIsForbidden(uint256 rfqId);
error RFQ_BadSignature(uint256 rfqId);
error RFQ_OrderExpired(uint256 rfqId);
error RFQ_MakerAmountExceeded(uint256 rfqId);
error RFQ_TakerAmountExceeded(uint256 rfqId);
error RFQ_SwapWithZeroAmount(uint256 rfqId);
error RFQ_InvalidatedOrder(uint256 rfqId);
error RFQ_AmountTooLarge(uint256 rfqId);
error RFQ_SettlementAmountTooSmall(uint256 rfqId);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "../interfaces/IDaiLikePermit.sol";
import "../interfaces/IPermit2.sol";
import "../libraries/RevertReasonForwarder.sol";
// All core libs are copied from 1inch
// v5: https://etherscan.io/address/0x1111111254EEB25477B68fb85Ed929f73A960582#code
// v6: https://etherscan.io/address/0x111111125421ca6dc452d289314280a0f8842a65#code
/// @title Implements efficient safe methods for ERC20 interface.
library SafeERC20 {
error SafeTransferFailed();
error SafeTransferFromFailed();
error ForceApproveFailed();
error SafeIncreaseAllowanceFailed();
error SafeDecreaseAllowanceFailed();
error SafePermitBadLength();
error Permit2TransferAmountTooHigh();
address public constant _PERMIT2 =
0x000000000022D473030F116dDEE9F6B43aC78BA3;
/**
* @notice Attempts to safely transfer tokens from one address to another using the Permit2 standard.
* @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
* the caller to make sure that the higher 96 bits of the `from` and `to` parameters are clean.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param from The address from which the tokens will be transferred.
* @param to The address to which the tokens will be transferred.
* @param amount The amount of tokens to transfer.
*/
function safeTransferFromPermit2(
IERC20 token,
address from,
address to,
uint256 amount
) internal {
if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh();
bytes4 selector = IPermit2.transferFrom.selector;
bool success;
assembly ("memory-safe") {
// solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), from)
mstore(add(data, 0x24), to)
mstore(add(data, 0x44), amount)
mstore(add(data, 0x64), token)
success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0)
if success {
success := gt(extcodesize(_PERMIT2), 0)
}
}
if (!success) revert SafeTransferFromFailed();
}
// Ensures method do not revert or return boolean `true`, admits call to non-smart-contract
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 amount
) internal {
bytes4 selector = token.transferFrom.selector;
bool success;
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), from)
mstore(add(data, 0x24), to)
mstore(add(data, 0x44), amount)
success := call(gas(), token, 0, data, 100, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
if (!success) revert SafeTransferFromFailed();
}
// Ensures method do not revert or return boolean `true`, admits call to non-smart-contract
function safeTransfer(IERC20 token, address to, uint256 value) internal {
if (!_makeCall(token, token.transfer.selector, to, value)) {
revert SafeTransferFailed();
}
}
// If `approve(from, to, amount)` fails, try to `approve(from, to, 0)` before retry
function forceApprove(
IERC20 token,
address spender,
uint256 value
) internal {
if (!_makeCall(token, token.approve.selector, spender, value)) {
if (
!_makeCall(token, token.approve.selector, spender, 0) ||
!_makeCall(token, token.approve.selector, spender, value)
) {
revert ForceApproveFailed();
}
}
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 allowance = token.allowance(address(this), spender);
if (value > type(uint256).max - allowance)
revert SafeIncreaseAllowanceFailed();
forceApprove(token, spender, allowance + value);
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 allowance = token.allowance(address(this), spender);
if (value > allowance) revert SafeDecreaseAllowanceFailed();
forceApprove(token, spender, allowance - value);
}
function safePermit(IERC20 token, bytes calldata permit) internal {
bool success;
if (permit.length == 32 * 7) {
success = _makeCalldataCall(
token,
IERC20Permit.permit.selector,
permit
);
} else if (permit.length == 32 * 8) {
success = _makeCalldataCall(
token,
IDaiLikePermit.permit.selector,
permit
);
} else {
revert SafePermitBadLength();
}
if (!success) RevertReasonForwarder.reRevert();
}
function _makeCall(
IERC20 token,
bytes4 selector,
address to,
uint256 amount
) private returns (bool success) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let data := mload(0x40)
mstore(data, selector)
mstore(add(data, 0x04), to)
mstore(add(data, 0x24), amount)
success := call(gas(), token, 0, data, 0x44, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
}
function _makeCalldataCall(
IERC20 token,
bytes4 selector,
bytes calldata args
) private returns (bool success) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let len := add(4, args.length)
let data := mload(0x40)
mstore(data, selector)
calldatacopy(add(data, 0x04), args.offset, args.length)
success := call(gas(), token, 0, data, len, 0x0, 0x20)
if success {
switch returndatasize()
case 0 {
success := gt(extcodesize(token), 0)
}
default {
success := and(gt(returndatasize(), 31), eq(mload(0), 1))
}
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "./libraries/ECDSA.sol";
library OrderRFQLib {
struct OrderRFQ {
uint256 rfqId; // 0x00
uint256 expiry; // 0x20
address makerAsset; // 0x40
address takerAsset; // 0x60
address makerAddress; // 0x80
uint256 makerAmount; // 0xa0
uint256 takerAmount; // 0xc0
bool usePermit2; // 0xe0;
}
bytes32 internal constant _LIMIT_ORDER_RFQ_TYPEHASH =
keccak256(
"OrderRFQ("
"uint256 rfqId,"
"uint256 expiry,"
"address makerAsset,"
"address takerAsset,"
"address makerAddress,"
"uint256 makerAmount,"
"uint256 takerAmount,"
"bool usePermit2"
")"
);
function hash(
OrderRFQ memory order,
bytes32 domainSeparator
) internal pure returns (bytes32 result) {
// Manually encoding each field instead of abi.encode(..., order)
// to avoid Yul "stack too deep" errors caused by expanding memory structs.
bytes32 structHash = keccak256(
abi.encode(
_LIMIT_ORDER_RFQ_TYPEHASH,
order.rfqId,
order.expiry,
order.makerAsset,
order.takerAsset,
order.makerAddress,
order.makerAmount,
order.takerAmount,
order.usePermit2
)
);
return ECDSA.toTypedDataHash(domainSeparator, structHash);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
library ECDSA {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
uint256 private constant _S_BOUNDARY =
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 + 1;
uint256 private constant _COMPACT_S_MASK =
0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
uint256 private constant _COMPACT_V_SHIFT = 255;
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (address signer) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
if lt(s, _S_BOUNDARY) {
let ptr := mload(0x40)
mstore(ptr, hash)
mstore(add(ptr, 0x20), v)
mstore(add(ptr, 0x40), r)
mstore(add(ptr, 0x60), s)
mstore(0, 0)
pop(staticcall(gas(), 0x1, ptr, 0x80, 0, 0x20))
signer := mload(0)
}
}
}
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (address signer) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let s := and(vs, _COMPACT_S_MASK)
if lt(s, _S_BOUNDARY) {
let ptr := mload(0x40)
mstore(ptr, hash)
mstore(add(ptr, 0x20), add(27, shr(_COMPACT_V_SHIFT, vs)))
mstore(add(ptr, 0x40), r)
mstore(add(ptr, 0x60), s)
mstore(0, 0)
pop(staticcall(gas(), 0x1, ptr, 0x80, 0, 0x20))
signer := mload(0)
}
}
}
/// @dev WARNING!!!
/// There is a known signature malleability issue with two representations of signatures!
/// Even though this function is able to verify both standard 65-byte and compact 64-byte EIP-2098 signatures
/// one should never use raw signatures for any kind of invalidation logic in their code.
/// As the standard and compact representations are interchangeable any invalidation logic that relies on
/// signature uniqueness will get rekt.
/// More info: https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories/GHSA-4h98-2769-gh6h
function recover(
bytes32 hash,
bytes calldata signature
) internal view returns (address signer) {
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
// memory[ptr:ptr+0x80] = (hash, v, r, s)
switch signature.length
case 65 {
// memory[ptr+0x20:ptr+0x80] = (v, r, s)
mstore(
add(ptr, 0x20),
byte(0, calldataload(add(signature.offset, 0x40)))
)
calldatacopy(add(ptr, 0x40), signature.offset, 0x40)
}
case 64 {
// memory[ptr+0x20:ptr+0x80] = (v, r, s)
let vs := calldataload(add(signature.offset, 0x20))
mstore(add(ptr, 0x20), add(27, shr(_COMPACT_V_SHIFT, vs)))
calldatacopy(add(ptr, 0x40), signature.offset, 0x20)
mstore(add(ptr, 0x60), and(vs, _COMPACT_S_MASK))
}
default {
ptr := 0
}
if ptr {
if lt(mload(add(ptr, 0x60)), _S_BOUNDARY) {
// memory[ptr:ptr+0x20] = (hash)
mstore(ptr, hash)
mstore(0, 0)
pop(staticcall(gas(), 0x1, ptr, 0x80, 0, 0x20))
signer := mload(0)
}
}
}
}
function recoverOrIsValidSignature(
address signer,
bytes32 hash,
bytes calldata signature
) internal view returns (bool success) {
if (signer == address(0)) return false;
if (
(signature.length == 64 || signature.length == 65) &&
recover(hash, signature) == signer
) {
return true;
}
return isValidSignature(signer, hash, signature);
}
function recoverOrIsValidSignature(
address signer,
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (bool success) {
if (signer == address(0)) return false;
if (recover(hash, v, r, s) == signer) {
return true;
}
return isValidSignature(signer, hash, v, r, s);
}
function recoverOrIsValidSignature(
address signer,
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (bool success) {
if (signer == address(0)) return false;
if (recover(hash, r, vs) == signer) {
return true;
}
return isValidSignature(signer, hash, r, vs);
}
function recoverOrIsValidSignature65(
address signer,
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (bool success) {
if (signer == address(0)) return false;
if (recover(hash, r, vs) == signer) {
return true;
}
return isValidSignature65(signer, hash, r, vs);
}
function isValidSignature(
address signer,
bytes32 hash,
bytes calldata signature
) internal view returns (bool success) {
// (bool success, bytes memory data) = signer.staticcall(abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature));
// return success && data.length >= 4 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;
bytes4 selector = IERC1271.isValidSignature.selector;
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(ptr, selector)
mstore(add(ptr, 0x04), hash)
mstore(add(ptr, 0x24), 0x40)
mstore(add(ptr, 0x44), signature.length)
calldatacopy(add(ptr, 0x64), signature.offset, signature.length)
if staticcall(
gas(),
signer,
ptr,
add(0x64, signature.length),
0,
0x20
) {
success := and(
eq(selector, mload(0)),
eq(returndatasize(), 0x20)
)
}
}
}
function isValidSignature(
address signer,
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal view returns (bool success) {
bytes4 selector = IERC1271.isValidSignature.selector;
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(ptr, selector)
mstore(add(ptr, 0x04), hash)
mstore(add(ptr, 0x24), 0x40)
mstore(add(ptr, 0x44), 65)
mstore(add(ptr, 0x64), r)
mstore(add(ptr, 0x84), s)
mstore8(add(ptr, 0xa4), v)
if staticcall(gas(), signer, ptr, 0xa5, 0, 0x20) {
success := and(
eq(selector, mload(0)),
eq(returndatasize(), 0x20)
)
}
}
}
function isValidSignature(
address signer,
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (bool success) {
// (bool success, bytes memory data) = signer.staticcall(abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, abi.encodePacked(r, vs)));
// return success && data.length >= 4 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;
bytes4 selector = IERC1271.isValidSignature.selector;
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(ptr, selector)
mstore(add(ptr, 0x04), hash)
mstore(add(ptr, 0x24), 0x40)
mstore(add(ptr, 0x44), 64)
mstore(add(ptr, 0x64), r)
mstore(add(ptr, 0x84), vs)
if staticcall(gas(), signer, ptr, 0xa4, 0, 0x20) {
success := and(
eq(selector, mload(0)),
eq(returndatasize(), 0x20)
)
}
}
}
function isValidSignature65(
address signer,
bytes32 hash,
bytes32 r,
bytes32 vs
) internal view returns (bool success) {
// (bool success, bytes memory data) = signer.staticcall(abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, abi.encodePacked(r, vs & ~uint256(1 << 255), uint8(vs >> 255))));
// return success && data.length >= 4 && abi.decode(data, (bytes4)) == IERC1271.isValidSignature.selector;
bytes4 selector = IERC1271.isValidSignature.selector;
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(ptr, selector)
mstore(add(ptr, 0x04), hash)
mstore(add(ptr, 0x24), 0x40)
mstore(add(ptr, 0x44), 65)
mstore(add(ptr, 0x64), r)
mstore(add(ptr, 0x84), and(vs, _COMPACT_S_MASK))
mstore8(add(ptr, 0xa4), add(27, shr(_COMPACT_V_SHIFT, vs)))
if staticcall(gas(), signer, ptr, 0xa5, 0, 0x20) {
success := and(
eq(selector, mload(0)),
eq(returndatasize(), 0x20)
)
}
}
}
function toEthSignedMessageHash(
bytes32 hash
) internal pure returns (bytes32 res) {
// 32 is the length in bytes of hash, enforced by the type signature above
// return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
mstore(
0,
0x19457468657265756d205369676e6564204d6573736167653a0a333200000000
) // "\x19Ethereum Signed Message:\n32"
mstore(28, hash)
res := keccak256(0, 60)
}
}
function toTypedDataHash(
bytes32 domainSeparator,
bytes32 structHash
) internal pure returns (bytes32 res) {
// return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
mstore(
ptr,
0x1901000000000000000000000000000000000000000000000000000000000000
) // "\x19\x01"
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
res := keccak256(ptr, 66)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` 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 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IDaiLikePermit {
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IPermit2 {
struct PermitDetails {
// ERC20 token address
address token;
// the maximum amount allowed to spend
uint160 amount;
// timestamp at which a spender's token allowances become invalid
uint48 expiration;
// an incrementing value indexed per owner,token,and spender for each signature
uint48 nonce;
}
/// @notice The permit message signed for a single token allownce
struct PermitSingle {
// the permit data for a single token allowance
PermitDetails details;
// address permissioned on the allowed tokens
address spender;
// deadline on the permit signature
uint256 sigDeadline;
}
/// @notice Packed allowance
struct PackedAllowance {
// amount allowed
uint160 amount;
// permission expiry
uint48 expiration;
// an incrementing value indexed per owner,token,and spender for each signature
uint48 nonce;
}
function transferFrom(
address user,
address spender,
uint160 amount,
address token
) external;
function permit(
address owner,
PermitSingle memory permitSingle,
bytes calldata signature
) external;
function allowance(
address user,
address token,
address spender
) external view returns (PackedAllowance memory);
/// @notice Approves the spender to use up to amount of the specified token up until the expiration
/// @param token The token to approve
/// @param spender The spender address to approve
/// @param amount The approved amount of the token
/// @param expiration The timestamp at which the approval is no longer valid
/// @dev The packed allowance also holds a nonce, which will stay unchanged in approve
/// @dev Setting amount to type(uint160).max sets an unlimited approval
function approve(address token, address spender, uint160 amount, uint48 expiration) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Revert reason forwarder.
library RevertReasonForwarder {
function reRevert() internal pure {
// bubble up revert reason from latest external call
/// @solidity memory-safe-assembly
assembly {
// solhint-disable-line no-inline-assembly
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*
* _Available since v4.1._
*/
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}{
"remappings": [
"forge-std/=lib/forge-std/src/",
"@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IWETH","name":"weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Permit2TransferAmountTooHigh","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_AmountTooLarge","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_BadSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_ETHTransferFailed","type":"error"},{"inputs":[],"name":"RFQ_EthDepositRejected","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_InvalidMsgValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_InvalidatedOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_MakerAmountExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_OrderExpired","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_SettlementAmountTooSmall","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_SwapWithZeroAmount","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_TakerAmountExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"rfqId","type":"uint256"}],"name":"RFQ_ZeroTargetIsForbidden","type":"error"},{"inputs":[],"name":"SafePermitBadLength","type":"error"},{"inputs":[],"name":"SafeTransferFromFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rfqId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expiry","type":"uint256"},{"indexed":true,"internalType":"address","name":"makerAsset","type":"address"},{"indexed":true,"internalType":"address","name":"takerAsset","type":"address"},{"indexed":false,"internalType":"address","name":"makerAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"expectedMakerAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expectedTakerAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"filledMakerAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"filledTakerAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"usePermit2","type":"bool"}],"name":"OrderFilledRFQ","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rfqId","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"uint256","name":"makerAmount","type":"uint256"},{"internalType":"uint256","name":"takerAmount","type":"uint256"},{"internalType":"bool","name":"usePermit2","type":"bool"}],"internalType":"struct OrderRFQLib.OrderRFQ","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"flagsAndAmount","type":"uint256"}],"name":"fillOrderRFQ","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rfqId","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"uint256","name":"makerAmount","type":"uint256"},{"internalType":"uint256","name":"takerAmount","type":"uint256"},{"internalType":"bool","name":"usePermit2","type":"bool"}],"internalType":"struct OrderRFQLib.OrderRFQ","name":"order","type":"tuple"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"},{"internalType":"uint256","name":"flagsAndAmount","type":"uint256"}],"name":"fillOrderRFQCompact","outputs":[{"internalType":"uint256","name":"filledMakerAmount","type":"uint256"},{"internalType":"uint256","name":"filledTakerAmount","type":"uint256"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rfqId","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"uint256","name":"makerAmount","type":"uint256"},{"internalType":"uint256","name":"takerAmount","type":"uint256"},{"internalType":"bool","name":"usePermit2","type":"bool"}],"internalType":"struct OrderRFQLib.OrderRFQ","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"flagsAndAmount","type":"uint256"},{"internalType":"address","name":"target","type":"address"}],"name":"fillOrderRFQTo","outputs":[{"internalType":"uint256","name":"filledMakerAmount","type":"uint256"},{"internalType":"uint256","name":"filledTakerAmount","type":"uint256"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rfqId","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"uint256","name":"makerAmount","type":"uint256"},{"internalType":"uint256","name":"takerAmount","type":"uint256"},{"internalType":"bool","name":"usePermit2","type":"bool"}],"internalType":"struct OrderRFQLib.OrderRFQ","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"flagsAndAmount","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"permit","type":"bytes"}],"name":"fillOrderRFQToWithPermit","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"maker","type":"address"},{"internalType":"uint256","name":"slot","type":"uint256"}],"name":"invalidatorForOrderRFQ","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"maker","type":"address"},{"internalType":"uint64","name":"rfqId","type":"uint64"}],"name":"isRfqIdUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6101603461019257601f61167738819003918201601f19168301926001600160401b039290918385118386101761017c57816020928492604097885283398101031261019257516001600160a01b038116810361019257825161006181610197565b601481526003602082017f4f4b58204c616220504d4d2050726f746f636f6c00000000000000000000000081526020865161009b81610197565b8381520192620312e360ec1b845251902091208160e052610100948186524660a05280519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f948585528284015260608301524660808301523060a083015260a0825260c08201958287109087111761017c578590525190206080523060c05261012090815260016000556101409182526114c493846101b3853960805184610a01015260a05184610acd015260c051846109cb015260e05184610a5001525183610a7601525182610a2d01525181818160200152610d5c0152f35b634e487b7160e01b600052604160045260246000fd5b600080fd5b604081019081106001600160401b0382111761017c5760405256fe608060408181526004918236101561005d575b50361561001e57600080fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361005057005b5163f4a0897760e01b8152fd5b60009060e0908235821c9081632154dec01461081c575080633644e515146107f857806356f16124146107b75780638db379da146104d5578063a806e57e146103b0578063c77e97f9146102c55763eafc8c6a146100bb5750610012565b83836101603660031901126102c1576100d336610903565b9361010435926101443590610124356100ea610af3565b6100fb6100f56109c8565b89610b49565b95600160fe1b8416156102a657600160fd1b8416156102745760208560a560018060a01b0360808d0151169482958a5191630b135d3f60e11b968784528d8a8501528c602485015260416044850152606484015260018060ff1b038116608484015260ff1c601b0160a48301535afa610264575b501561024d575061024993929161018b6001925b339089610c64565b9781977f712a85889720deeca46bcf02498ae1a7ba95372db831987c3a9572b9d96f6a158251918b61022a896020870151928a8060a01b039889838a015116988a6060820151169a6080820151169660a08201519060c08301519201511515945197889788959260c09592989794919860e0880199885260018060a01b0316602088015260408701526060860152608085015260a08401521515910152565b0390a45551938493846040919493926060820195825260208201520152565b0390f35b865184516387a26f4160e01b815291820152602490fd5b8451143d6020141690508861016f565b608089015161028f92919088906001600160a01b03166113da565b1561024d575061024993929161018b600192610183565b608089015161028f92919088906001600160a01b0316611309565b8380fd5b5083836101403660031901126102c1576102de36610903565b936101043567ffffffffffffffff81116103ac576102ff903690850161099a565b9093610124359161030e610af3565b6103196100f56109c8565b95600160fe1b84161561039157600160fd1b8416151580610386575b61036e57608089015161035492919088906001600160a01b031661138c565b1561024d575061024993929161018b600192339089610c64565b602483878b519051916387a26f4160e01b8352820152fd5b506041821415610335565b608089015161028f92919088906001600160a01b03166111fa565b5080fd5b5083836101603660031901126102c1576103c936610903565b936101043567ffffffffffffffff81116103ac576103ea903690850161099a565b909361012435906103f96108a0565b92610402610af3565b61041361040d6109c8565b8a610b49565b96600160fe1b8416156104a257600160fd1b8416151580610497575b61047f5760808a015161044e92919089906001600160a01b031661138c565b1561046857509161018b6001926102499695945b89610c64565b875185516387a26f4160e01b815291820152602490fd5b602483888c519051916387a26f4160e01b8352820152fd5b50604182141561042f565b60808a01516104bd92919089906001600160a01b03166111fa565b1561046857509161018b600192610249969594610462565b509290346107b4576101803660031901126107b4576104f336610903565b9367ffffffffffffffff92610104358481116102c157610516903690830161099a565b929094610124356105256108a0565b91610164359081116107b05761053e903690860161099a565b94909560608b01958a8960018060a01b03998a8a5116938981146000146107445780602094519263d505accf60e01b84528884013786019082855af19081610722575b505b15610718578a90610592610af3565b6105a361059d6109c8565b83610b49565b998a89600160fe1b8716156106ca57509192509050600160fd1b84161515806106bf575b6106a757906105dd918a8960808f01511661138c565b1561069057509261022a987f712a85889720deeca46bcf02498ae1a7ba95372db831987c3a9572b9d96f6a1561024998979461061f8b98956001985b85610c64565b9c819c8e86939651966020850151948a8085830151169a51169a6080820151169660a08201519060c08301519201511515945197889788959260c09592989794919860e0880199885260018060a01b0316602088015260408701526060860152608085015260a08401521515910152565b895189516387a26f4160e01b815291820152602490fd5b6024838c8e519051916387a26f4160e01b8352820152fd5b5060418214156105c7565b60806106d8950151166111fa565b1561069057509261022a987f712a85889720deeca46bcf02498ae1a7ba95372db831987c3a9572b9d96f6a1561024998979461061f8b9895600198610619565b89513d89823e3d90fd5b90503d1561073c57506001885114601f3d11165b38610581565b3b1515610736565b909250905061010081036107a0578c516323f2ebc360e21b81526020928c929081908884013786019082855af1908161077e575b50610583565b90503d1561079857506001885114601f3d11165b38610778565b3b1515610792565b8c51636827585760e01b81528590fd5b8680fd5b80fd5b8284346103ac57806003193601126103ac5760209181906001600160a01b036107de610885565b168152600184528181206024358252845220549051908152f35b8284346103ac57816003193601126103ac576020906108156109c8565b9051908152f35b849084346107b457826003193601126107b457610837610885565b926024359367ffffffffffffffff851685036108815760ff602095600192838060a01b0316855282875283852066ffffffffffffff8260081c1686528752161b9120541615158152f35b8280fd5b600435906001600160a01b038216820361089b57565b600080fd5b61014435906001600160a01b038216820361089b57565b67ffffffffffffffff81116108cb57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176108cb57604052565b906101008092600319011261089b5760405191820182811067ffffffffffffffff8211176108cb5760405260043582526024356020830152816001600160a01b03604435818116810361089b576040830152606435818116810361089b576060830152608435908116810361089b57608082015260a43560a082015260c43560c082015260e43590811515820361089b5760e00152565b9181601f8401121561089b5782359167ffffffffffffffff831161089b576020838186019501011161089b57565b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480610aca575b15610a23577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f000000000000000000000000000000000000000000000000000000000000000082527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176108cb5760405251902090565b507f000000000000000000000000000000000000000000000000000000000000000046146109fa565b600260005414610b04576002600055565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b9081519060208301519260018060a01b03908160408201511691806060830151169060808301511660a08301519160e060c08501519401511515946040519860208a01987fba577cf7d9c125d516b52eea5a2fc42f7be241ddae1c8b4372340d5c6da609228a5260408b015260608a0152608089015260a088015260c087015260e08601526101008501526101209081850152835261014083019183831067ffffffffffffffff8411176108cb576042936101629184604052815190209261190160f01b855261014282015201522090565b81810292918115918404141715610c2e57565b634e487b7160e01b600052601160045260246000fd5b8115610c4e570490565b634e487b7160e01b600052601260045260246000fd5b6001600160a01b039390600090848616156111e15785608082015116956020918281015180151590816111d7575b506111be5780519166ffffffffffffff8360081c1692600160ff82161b908a87526001865260409485882090808952818852868920549284808516146111a7575088528652178386205560a082019788519760c0840180519a848316801560001461110b57508a9b9a8560e088015115159182611101575b50506110e8575b8b1580156110e0575b6110c75751611770808202918083048214901517156110b3576127108092048d1092831561107f575b5050506110665790839291858c95018380825116918d827f000000000000000000000000000000000000000000000000000000000000000016988985149586611056575b50851561104f5730945b60e08a01511561103b57505050511690848d1161102a57908d91885192631b63c28b60e11b8452600484015260248301528c60448301526064820152888060846e22d473030f116ddee9f6b43ac78ba39382855af1908161101f575b501561100e575b610f40575b506060820183828251161480610f37575b15610efa575050863403610ee05750803b156102c1578151630d0e30db60e41b81529784896004818a865af1988915610ed6578596979899610eb4575b5090604484928451968793849263a9059cbb60e01b845260048401528b60248401525af1908115610eab5750610e7c57505050565b81813d8311610ea4575b610e9081836108e1565b810103126103ac5751801515036107b45750565b503d610e86565b513d85823e3d90fd5b610ec3909591929394956108b7565b610ed257908493929138610e47565b8480fd5b83513d87823e3d90fd5b518251637d0bdf8160e01b81526004810191909152602490fd5b945094509050969394959634610f1e575050918491610f1c935116339061141e565b565b6024925051905190637d0bdf8160e01b82526004820152fd5b50341515610e0a565b833b156107b0578451632e1a7d4d60e01b8152600481018b9052878160248183895af1801561100457908b9291610fef575b50878080938193611388f13d15610fea573d67ffffffffffffffff8111610fd657855190610fa9601f8201601f19168901836108e1565b815287873d92013e5b15610fbd5738610df9565b6024848351905190631952c5f360e01b82526004820152fd5b634e487b7160e01b88526041600452602488fd5b610fb2565b610ffc90989192986108b7565b969038610f72565b86513d8a823e3d90fd5b855163f405907160e01b8152600490fd5b90503b151538610ded565b8751638112e11960e01b8152600490fd5b9091935061104a94925061141e565b610df4565b8694610d91565b600160fc1b161515955038610d87565b602485855190519063a1475d7b60e01b82526004820152fd5b909192505181810291818304149015171561109f57048910388080610d43565b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b8a52601160045260248afd5b60248787519051906394d4247160e01b82526004820152fd5b508a15610d1a565b602487875190519063637b21d960e11b82526004820152fd5b1190508538610d0a565b9b909a90600160ff1b84161561116b57818d116111525761112c908d610c1b565b8181018091116110b35760001981019081116110b3579061114c91610c44565b99610d11565b6024888851905190630910e58760e31b82526004820152fd5b90818d9c9d1161118e5790611183611188928d610c1b565b610c44565b9a610d11565b60248888519051906328e30ac760e11b82526004820152fd5b602490885190636fe432b360e01b82526004820152fd5b60249051604051906384935d5760e01b82526004820152fd5b9050421138610c92565b602490516040519063047ef2e360e51b82526004820152fd5b9291906001600160a01b0380851680156112fe576040918286149283156112f3575b8361123e575b505050611235576112329361138c565b90565b50505050600190565b909192506000908051908782816041146112db57506040146112b057505080805b61126f575b501614388080611222565b816fa2a8918ca85bafe22016d0b997e4df5f600160ff1b03606083015110611298575b50611264565b608082876020945282805260015afa50513881611292565b819060208881810135928360ff1c601b01838601528401376001600160ff1b0316606082015261125f565b91809150880135841a6020830152878183013761125f565b60418714935061121c565b505050505050600090565b9291906001600160a01b038085169081156112fe5760006001600160ff1b038616816fa2a8918ca85bafe22016d0b997e4df5f600160ff1b03821061135a575b5050161461123557611232936113da565b6080602092604051908882528a60ff1c601b0185830152896040830152606082015282805260015afa50513881611349565b6000906020929395949582968060405192630b135d3f60e11b978885526004850152604060248501528160448501526064840137606401915afa6113cd5750565b600051143d602014169150565b60a460209293600092969596839760405192630b135d3f60e11b9788855260048501526040602485015260406044850152606484015260848301525afa6113cd5750565b9260209291606491600093604051926323b872dd60e01b845260048401526024830152604482015282855af1908161146b575b501561145957565b60405163f405907160e01b8152600490fd5b90503d156114865750600160005114601f3d11165b38611451565b3b151561148056fea2646970667358221220e0014c1934bd56a39324902a0ae80feba40e5d0c66178d16519bf3f225d3851264736f6c6343000811003300000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Deployed Bytecode
0x608060408181526004918236101561005d575b50361561001e57600080fd5b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b0316330361005057005b5163f4a0897760e01b8152fd5b60009060e0908235821c9081632154dec01461081c575080633644e515146107f857806356f16124146107b75780638db379da146104d5578063a806e57e146103b0578063c77e97f9146102c55763eafc8c6a146100bb5750610012565b83836101603660031901126102c1576100d336610903565b9361010435926101443590610124356100ea610af3565b6100fb6100f56109c8565b89610b49565b95600160fe1b8416156102a657600160fd1b8416156102745760208560a560018060a01b0360808d0151169482958a5191630b135d3f60e11b968784528d8a8501528c602485015260416044850152606484015260018060ff1b038116608484015260ff1c601b0160a48301535afa610264575b501561024d575061024993929161018b6001925b339089610c64565b9781977f712a85889720deeca46bcf02498ae1a7ba95372db831987c3a9572b9d96f6a158251918b61022a896020870151928a8060a01b039889838a015116988a6060820151169a6080820151169660a08201519060c08301519201511515945197889788959260c09592989794919860e0880199885260018060a01b0316602088015260408701526060860152608085015260a08401521515910152565b0390a45551938493846040919493926060820195825260208201520152565b0390f35b865184516387a26f4160e01b815291820152602490fd5b8451143d6020141690508861016f565b608089015161028f92919088906001600160a01b03166113da565b1561024d575061024993929161018b600192610183565b608089015161028f92919088906001600160a01b0316611309565b8380fd5b5083836101403660031901126102c1576102de36610903565b936101043567ffffffffffffffff81116103ac576102ff903690850161099a565b9093610124359161030e610af3565b6103196100f56109c8565b95600160fe1b84161561039157600160fd1b8416151580610386575b61036e57608089015161035492919088906001600160a01b031661138c565b1561024d575061024993929161018b600192339089610c64565b602483878b519051916387a26f4160e01b8352820152fd5b506041821415610335565b608089015161028f92919088906001600160a01b03166111fa565b5080fd5b5083836101603660031901126102c1576103c936610903565b936101043567ffffffffffffffff81116103ac576103ea903690850161099a565b909361012435906103f96108a0565b92610402610af3565b61041361040d6109c8565b8a610b49565b96600160fe1b8416156104a257600160fd1b8416151580610497575b61047f5760808a015161044e92919089906001600160a01b031661138c565b1561046857509161018b6001926102499695945b89610c64565b875185516387a26f4160e01b815291820152602490fd5b602483888c519051916387a26f4160e01b8352820152fd5b50604182141561042f565b60808a01516104bd92919089906001600160a01b03166111fa565b1561046857509161018b600192610249969594610462565b509290346107b4576101803660031901126107b4576104f336610903565b9367ffffffffffffffff92610104358481116102c157610516903690830161099a565b929094610124356105256108a0565b91610164359081116107b05761053e903690860161099a565b94909560608b01958a8960018060a01b03998a8a5116938981146000146107445780602094519263d505accf60e01b84528884013786019082855af19081610722575b505b15610718578a90610592610af3565b6105a361059d6109c8565b83610b49565b998a89600160fe1b8716156106ca57509192509050600160fd1b84161515806106bf575b6106a757906105dd918a8960808f01511661138c565b1561069057509261022a987f712a85889720deeca46bcf02498ae1a7ba95372db831987c3a9572b9d96f6a1561024998979461061f8b98956001985b85610c64565b9c819c8e86939651966020850151948a8085830151169a51169a6080820151169660a08201519060c08301519201511515945197889788959260c09592989794919860e0880199885260018060a01b0316602088015260408701526060860152608085015260a08401521515910152565b895189516387a26f4160e01b815291820152602490fd5b6024838c8e519051916387a26f4160e01b8352820152fd5b5060418214156105c7565b60806106d8950151166111fa565b1561069057509261022a987f712a85889720deeca46bcf02498ae1a7ba95372db831987c3a9572b9d96f6a1561024998979461061f8b9895600198610619565b89513d89823e3d90fd5b90503d1561073c57506001885114601f3d11165b38610581565b3b1515610736565b909250905061010081036107a0578c516323f2ebc360e21b81526020928c929081908884013786019082855af1908161077e575b50610583565b90503d1561079857506001885114601f3d11165b38610778565b3b1515610792565b8c51636827585760e01b81528590fd5b8680fd5b80fd5b8284346103ac57806003193601126103ac5760209181906001600160a01b036107de610885565b168152600184528181206024358252845220549051908152f35b8284346103ac57816003193601126103ac576020906108156109c8565b9051908152f35b849084346107b457826003193601126107b457610837610885565b926024359367ffffffffffffffff851685036108815760ff602095600192838060a01b0316855282875283852066ffffffffffffff8260081c1686528752161b9120541615158152f35b8280fd5b600435906001600160a01b038216820361089b57565b600080fd5b61014435906001600160a01b038216820361089b57565b67ffffffffffffffff81116108cb57604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176108cb57604052565b906101008092600319011261089b5760405191820182811067ffffffffffffffff8211176108cb5760405260043582526024356020830152816001600160a01b03604435818116810361089b576040830152606435818116810361089b576060830152608435908116810361089b57608082015260a43560a082015260c43560c082015260e43590811515820361089b5760e00152565b9181601f8401121561089b5782359167ffffffffffffffff831161089b576020838186019501011161089b57565b307f00000000000000000000000011939393f0cadfc06194ae983dafba2dcdf7308b6001600160a01b03161480610aca575b15610a23577fd5388a67dd1ccb5759f1e47436de7a7fdef252212c91cceb2d67fd3190fa8e2290565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1a148ebfaaf79dde62f16dbb955ac50fa57fe5a3d9a2d42c39d4ed4a0a026a8660408201527fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b360608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176108cb5760405251902090565b507f000000000000000000000000000000000000000000000000000000000000a4b146146109fa565b600260005414610b04576002600055565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b9081519060208301519260018060a01b03908160408201511691806060830151169060808301511660a08301519160e060c08501519401511515946040519860208a01987fba577cf7d9c125d516b52eea5a2fc42f7be241ddae1c8b4372340d5c6da609228a5260408b015260608a0152608089015260a088015260c087015260e08601526101008501526101209081850152835261014083019183831067ffffffffffffffff8411176108cb576042936101629184604052815190209261190160f01b855261014282015201522090565b81810292918115918404141715610c2e57565b634e487b7160e01b600052601160045260246000fd5b8115610c4e570490565b634e487b7160e01b600052601260045260246000fd5b6001600160a01b039390600090848616156111e15785608082015116956020918281015180151590816111d7575b506111be5780519166ffffffffffffff8360081c1692600160ff82161b908a87526001865260409485882090808952818852868920549284808516146111a7575088528652178386205560a082019788519760c0840180519a848316801560001461110b57508a9b9a8560e088015115159182611101575b50506110e8575b8b1580156110e0575b6110c75751611770808202918083048214901517156110b3576127108092048d1092831561107f575b5050506110665790839291858c95018380825116918d827f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab116988985149586611056575b50851561104f5730945b60e08a01511561103b57505050511690848d1161102a57908d91885192631b63c28b60e11b8452600484015260248301528c60448301526064820152888060846e22d473030f116ddee9f6b43ac78ba39382855af1908161101f575b501561100e575b610f40575b506060820183828251161480610f37575b15610efa575050863403610ee05750803b156102c1578151630d0e30db60e41b81529784896004818a865af1988915610ed6578596979899610eb4575b5090604484928451968793849263a9059cbb60e01b845260048401528b60248401525af1908115610eab5750610e7c57505050565b81813d8311610ea4575b610e9081836108e1565b810103126103ac5751801515036107b45750565b503d610e86565b513d85823e3d90fd5b610ec3909591929394956108b7565b610ed257908493929138610e47565b8480fd5b83513d87823e3d90fd5b518251637d0bdf8160e01b81526004810191909152602490fd5b945094509050969394959634610f1e575050918491610f1c935116339061141e565b565b6024925051905190637d0bdf8160e01b82526004820152fd5b50341515610e0a565b833b156107b0578451632e1a7d4d60e01b8152600481018b9052878160248183895af1801561100457908b9291610fef575b50878080938193611388f13d15610fea573d67ffffffffffffffff8111610fd657855190610fa9601f8201601f19168901836108e1565b815287873d92013e5b15610fbd5738610df9565b6024848351905190631952c5f360e01b82526004820152fd5b634e487b7160e01b88526041600452602488fd5b610fb2565b610ffc90989192986108b7565b969038610f72565b86513d8a823e3d90fd5b855163f405907160e01b8152600490fd5b90503b151538610ded565b8751638112e11960e01b8152600490fd5b9091935061104a94925061141e565b610df4565b8694610d91565b600160fc1b161515955038610d87565b602485855190519063a1475d7b60e01b82526004820152fd5b909192505181810291818304149015171561109f57048910388080610d43565b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b8a52601160045260248afd5b60248787519051906394d4247160e01b82526004820152fd5b508a15610d1a565b602487875190519063637b21d960e11b82526004820152fd5b1190508538610d0a565b9b909a90600160ff1b84161561116b57818d116111525761112c908d610c1b565b8181018091116110b35760001981019081116110b3579061114c91610c44565b99610d11565b6024888851905190630910e58760e31b82526004820152fd5b90818d9c9d1161118e5790611183611188928d610c1b565b610c44565b9a610d11565b60248888519051906328e30ac760e11b82526004820152fd5b602490885190636fe432b360e01b82526004820152fd5b60249051604051906384935d5760e01b82526004820152fd5b9050421138610c92565b602490516040519063047ef2e360e51b82526004820152fd5b9291906001600160a01b0380851680156112fe576040918286149283156112f3575b8361123e575b505050611235576112329361138c565b90565b50505050600190565b909192506000908051908782816041146112db57506040146112b057505080805b61126f575b501614388080611222565b816fa2a8918ca85bafe22016d0b997e4df5f600160ff1b03606083015110611298575b50611264565b608082876020945282805260015afa50513881611292565b819060208881810135928360ff1c601b01838601528401376001600160ff1b0316606082015261125f565b91809150880135841a6020830152878183013761125f565b60418714935061121c565b505050505050600090565b9291906001600160a01b038085169081156112fe5760006001600160ff1b038616816fa2a8918ca85bafe22016d0b997e4df5f600160ff1b03821061135a575b5050161461123557611232936113da565b6080602092604051908882528a60ff1c601b0185830152896040830152606082015282805260015afa50513881611349565b6000906020929395949582968060405192630b135d3f60e11b978885526004850152604060248501528160448501526064840137606401915afa6113cd5750565b600051143d602014169150565b60a460209293600092969596839760405192630b135d3f60e11b9788855260048501526040602485015260406044850152606484015260848301525afa6113cd5750565b9260209291606491600093604051926323b872dd60e01b845260048401526024830152604482015282855af1908161146b575b501561145957565b60405163f405907160e01b8152600490fd5b90503d156114865750600160005114601f3d11165b38611451565b3b151561148056fea2646970667358221220e0014c1934bd56a39324902a0ae80feba40e5d0c66178d16519bf3f225d3851264736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
-----Decoded View---------------
Arg [0] : weth (address): 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.