编译器
0.8.20+commit.a1b79de6
文件 1 的 4:BatchDistributor.sol
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "../interfaces/IDistributor.sol";
import "../Errors.sol";
contract BatchDistributor is ReentrancyGuard {
struct BatchClaimParams {
address distributorContract;
bool isInit;
bytes32 userVestingId;
bytes proof;
}
event BatchClaimed(address indexed caller, address[] distributors, address recipient);
constructor() {
}
function batchClaim(BatchClaimParams[] calldata params, address recipient) external nonReentrant {
if (params.length == 0) revert EmptyArray();
if (recipient != msg.sender) revert InvalidRecipient();
address[] memory distributors = new address[](params.length);
for (uint256 i = 0; i < params.length; i++) {
BatchClaimParams memory param = params[i];
distributors[i] = param.distributorContract;
IDistributor distributor = IDistributor(param.distributorContract);
if (param.isInit) {
if (param.proof.length == 0) revert InvalidProofs();
distributor.initClaim(
msg.sender,
param.proof,
recipient
);
} else {
distributor.claim(
msg.sender,
param.userVestingId,
recipient
);
}
}
emit BatchClaimed(msg.sender, distributors, recipient);
}
}
文件 2 的 4:Errors.sol
pragma solidity ^0.8.20;
error InvalidSignature();
error AlreadyClaimed();
error ZeroAddress();
error DeadlinePassed();
error InvalidProofs();
error RootHashAlreadySet();
error SlotExists();
error InvalidRecipient();
error InvalidCaller();
error VestingConfigNotSet();
error InvalidVestingConfig();
error EmptyArray();
error InvalidUserVestingId();
文件 3 的 4:IDistributor.sol
pragma solidity ^0.8.20;
import "../Errors.sol";
interface IDistributor {
function initClaim(address caller, bytes calldata proofs, address recipient) external;
function claim(address caller, bytes32 userVestingId, address recipient) external;
}
文件 4 的 4:ReentrancyGuard.sol
pragma solidity ^0.8.20;
abstract contract ReentrancyGuard {
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
_status = ENTERED;
}
function _nonReentrantAfter() private {
_status = NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
{
"compilationTarget": {
"contracts/v2/BatchDistributor.sol": "BatchDistributor"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmptyArray","type":"error"},{"inputs":[],"name":"InvalidProofs","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address[]","name":"distributors","type":"address[]"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"BatchClaimed","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"distributorContract","type":"address"},{"internalType":"bool","name":"isInit","type":"bool"},{"internalType":"bytes32","name":"userVestingId","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"internalType":"struct BatchDistributor.BatchClaimParams[]","name":"params","type":"tuple[]"},{"internalType":"address","name":"recipient","type":"address"}],"name":"batchClaim","outputs":[],"stateMutability":"nonpayable","type":"function"}]