编译器
0.8.17+commit.8df45f5f
文件 1 的 4:IConduit.sol
pragma solidity ^0.8.9;
interface IConduitController {
function getConduitCodeHashes()
external
view
returns (bytes32 creationCodeHash, bytes32 runtimeCodeHash);
}
interface IConduit {
enum ConduitItemType {
NATIVE,
ERC20,
ERC721,
ERC1155
}
struct ConduitTransfer {
ConduitItemType itemType;
address token;
address from;
address to;
uint256 identifier;
uint256 amount;
}
function execute(ConduitTransfer[] calldata transfers) external returns (bytes4 magicValue);
}
文件 2 的 4:IReservoirV6_0_1.sol
pragma solidity ^0.8.9;
interface IReservoirV6_0_1 {
struct ExecutionInfo {
address module;
bytes data;
uint256 value;
}
function execute(ExecutionInfo[] calldata executionInfos) external payable;
}
文件 3 的 4:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
}
文件 4 的 4:ReservoirApprovalProxy.sol
pragma solidity ^0.8.9;
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {IConduit, IConduitController} from "../interfaces/IConduit.sol";
import {IReservoirV6_0_1} from "../interfaces/IReservoirV6_0_1.sol";
contract ReservoirApprovalProxy is ReentrancyGuard {
struct TransferHelperItem {
IConduit.ConduitItemType itemType;
address token;
uint256 identifier;
uint256 amount;
}
struct TransferHelperItemsWithRecipient {
TransferHelperItem[] items;
address recipient;
}
error ConduitExecutionFailed();
error InvalidRecipient();
IConduitController internal immutable _CONDUIT_CONTROLLER;
bytes32 internal immutable _CONDUIT_CREATION_CODE_HASH;
bytes32 internal immutable _CONDUIT_RUNTIME_CODE_HASH;
IReservoirV6_0_1 internal immutable _ROUTER;
constructor(address conduitController, address router) {
IConduitController controller = IConduitController(conduitController);
(_CONDUIT_CREATION_CODE_HASH, _CONDUIT_RUNTIME_CODE_HASH) = controller.getConduitCodeHashes();
_CONDUIT_CONTROLLER = controller;
_ROUTER = IReservoirV6_0_1(router);
}
function bulkTransferWithExecute(
TransferHelperItemsWithRecipient[] calldata transfers,
IReservoirV6_0_1.ExecutionInfo[] calldata executionInfos,
bytes32 conduitKey
) external nonReentrant {
uint256 numTransfers = transfers.length;
address conduit = address(
uint160(
uint256(
keccak256(
abi.encodePacked(
bytes1(0xff),
address(_CONDUIT_CONTROLLER),
conduitKey,
_CONDUIT_CREATION_CODE_HASH
)
)
)
)
);
uint256 sumOfItemsAcrossAllTransfers;
unchecked {
for (uint256 i = 0; i < numTransfers; ++i) {
TransferHelperItemsWithRecipient calldata transfer = transfers[i];
sumOfItemsAcrossAllTransfers += transfer.items.length;
}
}
IConduit.ConduitTransfer[] memory conduitTransfers = new IConduit.ConduitTransfer[](
sumOfItemsAcrossAllTransfers
);
uint256 itemIndex;
unchecked {
for (uint256 i = 0; i < numTransfers; ++i) {
TransferHelperItemsWithRecipient calldata transfer = transfers[i];
TransferHelperItem[] calldata transferItems = transfer.items;
_checkRecipientIsNotZeroAddress(transfer.recipient);
uint256 numItemsInTransfer = transferItems.length;
for (uint256 j = 0; j < numItemsInTransfer; ++j) {
TransferHelperItem calldata item = transferItems[j];
conduitTransfers[itemIndex] = IConduit.ConduitTransfer(
item.itemType,
item.token,
msg.sender,
transfer.recipient,
item.identifier,
item.amount
);
++itemIndex;
}
}
}
bytes4 conduitMagicValue = IConduit(conduit).execute(conduitTransfers);
if (conduitMagicValue != IConduit.execute.selector) {
revert ConduitExecutionFailed();
}
_ROUTER.execute(executionInfos);
}
function _checkRecipientIsNotZeroAddress(address recipient) internal pure {
if (recipient == address(0x0)) {
revert InvalidRecipient();
}
}
}
{
"compilationTarget": {
"contracts/misc/ReservoirApprovalProxy.sol": "ReservoirApprovalProxy"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [],
"viaIR": true
}
[{"inputs":[{"internalType":"address","name":"conduitController","type":"address"},{"internalType":"address","name":"router","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ConduitExecutionFailed","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[{"components":[{"components":[{"internalType":"enum IConduit.ConduitItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ReservoirApprovalProxy.TransferHelperItem[]","name":"items","type":"tuple[]"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ReservoirApprovalProxy.TransferHelperItemsWithRecipient[]","name":"transfers","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IReservoirV6_0_1.ExecutionInfo[]","name":"executionInfos","type":"tuple[]"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"}],"name":"bulkTransferWithExecute","outputs":[],"stateMutability":"nonpayable","type":"function"}]