RfqExecutor
0xf4da3c42d9c9f494d4688a0112a9db3c9b18a914
Verification
Verified
v0.8.27+commit.40a35a09
Type
Contract
2,688 bytes
ABI entries
13
5 read · 1 write
License
none
Contract information
- Address
- 0xf4da3c42d9c9f494d4688a0112a9db3c9b18a914
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.27+commit.40a35a09
- Optimization
- Enabled
- Creator
- 0x84bF99545E…1644f79F99
- Creation tx
- 0xdcae0cf18d…8b3fb69409
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (5)
ARCUS_RFQ_QUOTE_TYPEHASH() → bytes32
ARCUS_RFQ_QUOTE_WITNESS_TYPE_STRING() → string
PERMIT2() → address
hashArcusRfqQuote(tuple) → bytes32
settlement() → address
Events (1)
ArcusRfqFilled
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "settlement_",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "OnlySettlement",
"type": "error"
},
{
"inputs": [],
"name": "QuoteExpired",
"type": "error"
},
{
"inputs": [],
"name": "QuoteMismatch",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "SafeERC20FailedOperation",
"type": "error"
},
{
"inputs": [],
"name": "WrappedQuoteUnsupported",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "quoteId",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "maker",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "taker",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "makerBuyToken",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "makerSellToken",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "makerBuyAmount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "makerSellAmount",
"type": "uint256"
}
],
"name": "ArcusRfqFilled",
"type": "event"
},
{
"inputs": [],
"name": "ARCUS_RFQ_QUOTE_TYPEHASH",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "ARCUS_RFQ_QUOTE_WITNESS_TYPE_STRING",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "PERMIT2",
"outputs": [
{
"internalType": "contract IPermit2",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "taker",
"type": "address"
},
{
"internalType": "address",
"name": "inputToken",
"type": "address"
},
{
"internalType": "uint256",
"name": "inputAmount",
"type": "uint256"
},
{
"internalType": "address",
"name": "outputToken",
"type": "address"
},
{
"internalType": "uint256",
"name": "minOutputAmount",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "executorData",
"type": "bytes"
}
],
"name": "execute",
"outputs": [
{
"internalType": "uint256",
"name": "outputAmount",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "bytes32",
"name": "quoteId",
"type": "bytes32"
},
{
"internalType": "address",
"name": "maker",
"type": "address"
},
{
"internalType": "address",
"name": "taker",
"type": "address"
},
{
"internalType": "address",
"name": "makerBuyToken",
"type": "address"
},
{
"internalType": "address",
"name": "makerSellToken",
"type": "address"
},
{
"internalType": "uint256",
"name": "makerBuyAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "makerSellAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "nonce",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "validUntil",
"type": "uint256"
},
{
"internalType": "bool",
"name": "wrapped",
"type": "bool"
}
],
"internalType": "struct ArcusRfqQuote",
"name": "quote",
"type": "tuple"
}
],
"name": "hashArcusRfqQuote",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "settlement",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
]Source code
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IArcusExecutor} from "../interfaces/IArcusExecutor.sol";
import {IPermit2} from "../interfaces/IPermit2.sol";
import {ArcusRfqQuote, ArcusRfqQuoteLib} from "../lib/ArcusRfqQuoteLib.sol";
/// @notice Ordinary RFQ executor for fixed-size maker quotes.
contract RfqExecutor is IArcusExecutor {
using SafeERC20 for IERC20;
IPermit2 public constant PERMIT2 = IPermit2(0x000000000022D473030F116dDEE9F6B43aC78BA3);
string public constant ARCUS_RFQ_QUOTE_WITNESS_TYPE_STRING =
"ArcusRfqQuote witness)ArcusRfqQuote(bytes32 quoteId,address maker,address taker,address makerBuyToken,address makerSellToken,uint256 makerBuyAmount,uint256 makerSellAmount,uint256 nonce,uint256 validUntil,bool wrapped)TokenPermissions(address token,uint256 amount)";
address public immutable settlement;
event ArcusRfqFilled(
bytes32 indexed quoteId,
address indexed maker,
address indexed taker,
address makerBuyToken,
address makerSellToken,
uint256 makerBuyAmount,
uint256 makerSellAmount
);
error OnlySettlement();
error QuoteExpired();
error WrappedQuoteUnsupported();
error QuoteMismatch();
constructor(address settlement_) {
settlement = settlement_;
}
function execute(
address taker,
address inputToken,
uint256 inputAmount,
address outputToken,
uint256 minOutputAmount,
bytes calldata executorData
) external override returns (uint256 outputAmount) {
if (msg.sender != settlement) revert OnlySettlement();
(ArcusRfqQuote memory quote, bytes memory makerSig) = abi.decode(executorData, (ArcusRfqQuote, bytes));
if (quote.wrapped) revert WrappedQuoteUnsupported();
if (block.timestamp > quote.validUntil) revert QuoteExpired();
if (
quote.taker != taker || inputToken != quote.makerBuyToken || inputAmount != quote.makerBuyAmount
|| outputToken != quote.makerSellToken || quote.makerBuyAmount == 0 || quote.makerSellAmount == 0
|| quote.makerSellAmount < minOutputAmount
) revert QuoteMismatch();
PERMIT2.permitWitnessTransferFrom(
IPermit2.PermitTransferFrom({
permitted: IPermit2.TokenPermissions({token: quote.makerSellToken, amount: quote.makerSellAmount}),
nonce: quote.nonce,
deadline: quote.validUntil
}),
IPermit2.SignatureTransferDetails({to: address(this), requestedAmount: quote.makerSellAmount}),
quote.maker,
_hashArcusRfqQuote(quote),
ARCUS_RFQ_QUOTE_WITNESS_TYPE_STRING,
makerSig
);
IERC20(quote.makerBuyToken).safeTransfer(quote.maker, quote.makerBuyAmount);
IERC20(quote.makerSellToken).safeTransfer(msg.sender, quote.makerSellAmount);
emit ArcusRfqFilled(
quote.quoteId,
quote.maker,
quote.taker,
quote.makerBuyToken,
quote.makerSellToken,
quote.makerBuyAmount,
quote.makerSellAmount
);
return quote.makerSellAmount;
}
function hashArcusRfqQuote(ArcusRfqQuote calldata quote) external pure returns (bytes32) {
return _hashArcusRfqQuote(quote);
}
function ARCUS_RFQ_QUOTE_TYPEHASH() external pure returns (bytes32) {
return ArcusRfqQuoteLib.typehash();
}
function _hashArcusRfqQuote(ArcusRfqQuote memory quote) internal pure returns (bytes32) {
return ArcusRfqQuoteLib.hash(quote);
}
}
Chain explorer3112msChain node93ms