Latest 25 from a total of 3,222 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Batch Claim | 24314254 | 16 hrs ago | IN | 0 ETH | 0.00016681 | ||||
| Batch Claim | 24313830 | 18 hrs ago | IN | 0 ETH | 0.000711 | ||||
| Batch Claim | 24312953 | 20 hrs ago | IN | 0 ETH | 0.00099042 | ||||
| Batch Claim | 24306931 | 41 hrs ago | IN | 0 ETH | 0.00229066 | ||||
| Batch Claim | 24303540 | 2 days ago | IN | 0 ETH | 0.00003959 | ||||
| Batch Claim | 24302188 | 2 days ago | IN | 0 ETH | 0.00041471 | ||||
| Batch Claim | 24296459 | 3 days ago | IN | 0 ETH | 0.00002296 | ||||
| Batch Claim | 24296370 | 3 days ago | IN | 0 ETH | 0.00005 | ||||
| Batch Claim | 24292245 | 3 days ago | IN | 0 ETH | 0.00006807 | ||||
| Batch Claim | 24286995 | 4 days ago | IN | 0 ETH | 0.00002993 | ||||
| Batch Claim | 24277779 | 5 days ago | IN | 0 ETH | 0.00014372 | ||||
| Batch Claim | 24276351 | 5 days ago | IN | 0 ETH | 0.00007985 | ||||
| Batch Claim | 24275085 | 6 days ago | IN | 0 ETH | 0.00185689 | ||||
| Batch Claim | 24274591 | 6 days ago | IN | 0 ETH | 0.00001675 | ||||
| Batch Claim | 24274220 | 6 days ago | IN | 0 ETH | 0.00010135 | ||||
| Batch Claim | 24270209 | 6 days ago | IN | 0 ETH | 0.00002056 | ||||
| Batch Claim | 24268919 | 7 days ago | IN | 0 ETH | 0.00004333 | ||||
| Batch Claim | 24264854 | 7 days ago | IN | 0 ETH | 0.00002791 | ||||
| Batch Claim | 24263117 | 7 days ago | IN | 0 ETH | 0.00001113 | ||||
| Batch Claim | 24261476 | 8 days ago | IN | 0 ETH | 0.00002925 | ||||
| Batch Claim | 24259854 | 8 days ago | IN | 0 ETH | 0.00003689 | ||||
| Batch Claim | 24259572 | 8 days ago | IN | 0 ETH | 0.00001662 | ||||
| Batch Claim | 24259441 | 8 days ago | IN | 0 ETH | 0.00002629 | ||||
| Batch Claim | 24258783 | 8 days ago | IN | 0 ETH | 0.00002842 | ||||
| Batch Claim | 24258589 | 8 days ago | IN | 0 ETH | 0.00003182 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60c06040 | 19983089 | 605 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
RewardsDistributor
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
/// library imports
import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol";
import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
/// local imports
import { Error } from "src/libraries/Error.sol";
import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol";
import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol";
import { IRewardsDistributor } from "src/interfaces/IRewardsDistributor.sol";
/// @title RewardsDistributor
/// @author Zeropoint Labs
/// @notice This will be SUPERFORM_RECEIVER in SuperRegistry.
/// @notice Also, requires a new REWARDS_ADMIN_ROLE (a fireblocks address)
contract RewardsDistributor is IRewardsDistributor {
using SafeERC20 for IERC20;
//////////////////////////////////////////////////////////////
// CONSTANTS //
//////////////////////////////////////////////////////////////
ISuperRegistry public immutable superRegistry;
uint64 public immutable CHAIN_ID;
bytes32 internal constant ZERO_BYTES32 = bytes32(0);
uint256 public constant DEADLINE = 52 weeks;
//////////////////////////////////////////////////////////////
// STATE VARIABLES //
//////////////////////////////////////////////////////////////
uint256 public currentPeriodId;
/// @dev maps the periodic rewards id to its corresponding merkle root and startTimestamp
mapping(uint256 periodId => PeriodicRewardsData data) public periodicRewardsMerkleRootData;
/// @dev mapping from periodId to claimer address to claimed status
mapping(uint256 periodId => mapping(address claimerAddress => bool claimed)) public periodicRewardsClaimed;
//////////////////////////////////////////////////////////////
// MODIFIERS //
//////////////////////////////////////////////////////////////
modifier onlyRewardsAdmin() {
if (
!ISuperRBAC(superRegistry.getAddress(keccak256("SUPER_RBAC"))).hasRole(
keccak256("REWARDS_ADMIN_ROLE"), msg.sender
)
) {
revert NOT_REWARDS_ADMIN();
}
_;
}
//////////////////////////////////////////////////////////////
// CONSTRUCTOR //
//////////////////////////////////////////////////////////////
/// @param superRegistry_ the superform registry contract
constructor(address superRegistry_) {
if (superRegistry_ == address(0)) {
revert Error.ZERO_ADDRESS();
}
if (block.chainid > type(uint64).max) {
revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS();
}
superRegistry = ISuperRegistry(superRegistry_);
CHAIN_ID = uint64(block.chainid);
}
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @inheritdoc IRewardsDistributor
function setPeriodicRewards(bytes32 root_) external payable override onlyRewardsAdmin {
if (root_ == ZERO_BYTES32) revert INVALID_MERKLE_ROOT();
uint256 periodId = currentPeriodId;
uint256 startTimestamp = block.timestamp;
periodicRewardsMerkleRootData[periodId].startTimestamp = startTimestamp;
periodicRewardsMerkleRootData[periodId].merkleRoot = root_;
++currentPeriodId;
emit PeriodicRewardsSet(periodId, root_, startTimestamp);
}
/// @inheritdoc IRewardsDistributor
function claim(
address receiver_,
uint256 periodId_,
address[] calldata rewardTokens_,
uint256[] calldata amountsClaimed_,
bytes32[] calldata proof_
)
external
override
{
if (receiver_ == address(0)) revert INVALID_RECEIVER();
uint256 tokensToClaim = rewardTokens_.length;
if (tokensToClaim == 0) revert ZERO_ARR_LENGTH();
if (tokensToClaim != amountsClaimed_.length) revert INVALID_REQ_TOKENS_AMOUNTS();
_claim(receiver_, periodId_, rewardTokens_, amountsClaimed_, tokensToClaim, proof_);
emit RewardsClaimed(msg.sender, receiver_, periodId_, rewardTokens_, amountsClaimed_);
}
/// @inheritdoc IRewardsDistributor
function batchClaim(
address receiver_,
uint256[] calldata periodIds_,
address[][] calldata rewardTokens_,
uint256[][] calldata amountsClaimed_,
bytes32[][] calldata proofs_
)
external
override
{
if (receiver_ == address(0)) revert INVALID_RECEIVER();
uint256 len = periodIds_.length;
if (len == 0) revert ZERO_ARR_LENGTH();
if (!(len == proofs_.length && len == rewardTokens_.length && len == amountsClaimed_.length)) {
revert INVALID_BATCH_REQ();
}
for (uint256 i; i < len; ++i) {
uint256 tokensToClaim = rewardTokens_[i].length;
if (tokensToClaim == 0) revert ZERO_ARR_LENGTH();
if (tokensToClaim != amountsClaimed_[i].length) revert INVALID_BATCH_REQ_TOKENS_AMOUNTS();
_claim(receiver_, periodIds_[i], rewardTokens_[i], amountsClaimed_[i], tokensToClaim, proofs_[i]);
emit RewardsClaimed(msg.sender, receiver_, periodIds_[i], rewardTokens_[i], amountsClaimed_[i]);
}
}
/// @inheritdoc IRewardsDistributor
function rescueRewards(
address[] calldata rewardTokens_,
uint256[] calldata amounts_
)
external
override
onlyRewardsAdmin
{
address receiver = superRegistry.getAddress(keccak256("PAYMASTER"));
uint256 len = rewardTokens_.length;
if (len == 0) revert ZERO_ARR_LENGTH();
if (len != amounts_.length) revert INVALID_REQ_TOKENS_AMOUNTS();
_transferRewards(receiver, rewardTokens_, amounts_, rewardTokens_.length);
}
/// @inheritdoc IRewardsDistributor
function invalidatePeriod(uint256 periodId_) external override onlyRewardsAdmin {
delete periodicRewardsMerkleRootData[periodId_];
}
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @inheritdoc IRewardsDistributor
function verifyClaim(
address receiver_,
uint256 periodId_,
address[] calldata rewardTokens_,
uint256[] calldata amountsClaimed_,
bytes32[] calldata proof_
)
public
view
override
returns (bool valid)
{
bytes32 root = periodicRewardsMerkleRootData[periodId_].merkleRoot;
if (root == ZERO_BYTES32) revert MERKLE_ROOT_NOT_SET();
uint256 deadlineTimestamp = periodicRewardsMerkleRootData[periodId_].startTimestamp + DEADLINE;
if (block.timestamp > deadlineTimestamp) revert CLAIM_DEADLINE_PASSED();
/// @dev a given receiver cannot claim rewards a second time for a given period
if (periodicRewardsClaimed[periodId_][receiver_]) revert ALREADY_CLAIMED();
/// @dev double hashing is used to protect from
/// https://www.rareskills.io/post/merkle-tree-second-preimage-attack
bytes32 leaf = keccak256(
bytes.concat(keccak256(abi.encode(receiver_, periodId_, rewardTokens_, amountsClaimed_, CHAIN_ID)))
);
return MerkleProof.verify(proof_, root, leaf);
}
//////////////////////////////////////////////////////////////
// INTERNAL FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice helper function for processing claim
function _claim(
address receiver_,
uint256 periodId_,
address[] calldata rewardTokens_,
uint256[] calldata amountsClaimed_,
uint256 tokensToClaim_,
bytes32[] calldata proof_
)
internal
{
/// @dev claim verification is on receiver, this allows anyone to permissionessly claim on behalf of any address
if (!verifyClaim(receiver_, periodId_, rewardTokens_, amountsClaimed_, proof_)) revert INVALID_CLAIM();
periodicRewardsClaimed[periodId_][receiver_] = true;
_transferRewards(receiver_, rewardTokens_, amountsClaimed_, tokensToClaim_);
}
/// @notice transfer token rewards to the receiver
function _transferRewards(
address receiver_,
address[] calldata rewardTokens_,
uint256[] calldata amountsClaimed_,
uint256 tokensToClaim_
)
internal
{
for (uint256 i; i < tokensToClaim_; ++i) {
IERC20(rewardTokens_[i]).safeTransfer(receiver_, amountsClaimed_[i]);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.20;
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the Merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates Merkle trees that are safe
* against this attack out of the box.
*/
library MerkleProof {
/**
*@dev The multiproof provided is not valid.
*/
error MerkleProofInvalidMultiproof();
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*/
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Calldata version of {processProof}
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Calldata version of {multiProofVerify}
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Calldata version of {processMultiProof}.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the Merkle tree.
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Sorts the pair (a, b) and hashes the result.
*/
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
/**
* @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
*/
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
library Error {
//////////////////////////////////////////////////////////////
// CONFIGURATION ERRORS //
//////////////////////////////////////////////////////////////
///@notice errors thrown in protocol setup
/// @dev thrown if chain id exceeds max(uint64)
error BLOCK_CHAIN_ID_OUT_OF_BOUNDS();
/// @dev thrown if not possible to revoke a role in broadcasting
error CANNOT_REVOKE_NON_BROADCASTABLE_ROLES();
/// @dev thrown if not possible to revoke last admin
error CANNOT_REVOKE_LAST_ADMIN();
/// @dev thrown if trying to set again pseudo immutables in super registry
error DISABLED();
/// @dev thrown if rescue delay is not yet set for a chain
error DELAY_NOT_SET();
/// @dev thrown if get native token price estimate in paymentHelper is 0
error INVALID_NATIVE_TOKEN_PRICE();
/// @dev thrown if wormhole refund chain id is not set
error REFUND_CHAIN_ID_NOT_SET();
/// @dev thrown if wormhole relayer is not set
error RELAYER_NOT_SET();
/// @dev thrown if a role to be revoked is not assigned
error ROLE_NOT_ASSIGNED();
//////////////////////////////////////////////////////////////
// AUTHORIZATION ERRORS //
//////////////////////////////////////////////////////////////
///@notice errors thrown if functions cannot be called
/// COMMON AUTHORIZATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if caller is not address(this), internal call
error INVALID_INTERNAL_CALL();
/// @dev thrown if msg.sender is not a valid amb implementation
error NOT_AMB_IMPLEMENTATION();
/// @dev thrown if msg.sender is not an allowed broadcaster
error NOT_ALLOWED_BROADCASTER();
/// @dev thrown if msg.sender is not broadcast amb implementation
error NOT_BROADCAST_AMB_IMPLEMENTATION();
/// @dev thrown if msg.sender is not broadcast state registry
error NOT_BROADCAST_REGISTRY();
/// @dev thrown if msg.sender is not core state registry
error NOT_CORE_STATE_REGISTRY();
/// @dev thrown if msg.sender is not emergency admin
error NOT_EMERGENCY_ADMIN();
/// @dev thrown if msg.sender is not emergency queue
error NOT_EMERGENCY_QUEUE();
/// @dev thrown if msg.sender is not minter
error NOT_MINTER();
/// @dev thrown if msg.sender is not minter state registry
error NOT_MINTER_STATE_REGISTRY_ROLE();
/// @dev thrown if msg.sender is not paymaster
error NOT_PAYMASTER();
/// @dev thrown if msg.sender is not payment admin
error NOT_PAYMENT_ADMIN();
/// @dev thrown if msg.sender is not protocol admin
error NOT_PROTOCOL_ADMIN();
/// @dev thrown if msg.sender is not state registry
error NOT_STATE_REGISTRY();
/// @dev thrown if msg.sender is not super registry
error NOT_SUPER_REGISTRY();
/// @dev thrown if msg.sender is not superform router
error NOT_SUPERFORM_ROUTER();
/// @dev thrown if msg.sender is not a superform
error NOT_SUPERFORM();
/// @dev thrown if msg.sender is not superform factory
error NOT_SUPERFORM_FACTORY();
/// @dev thrown if msg.sender is not timelock form
error NOT_TIMELOCK_SUPERFORM();
/// @dev thrown if msg.sender is not timelock state registry
error NOT_TIMELOCK_STATE_REGISTRY();
/// @dev thrown if msg.sender is not user or disputer
error NOT_VALID_DISPUTER();
/// @dev thrown if the msg.sender is not privileged caller
error NOT_PRIVILEGED_CALLER(bytes32 role);
/// STATE REGISTRY AUTHORIZATION ERRORS
/// ---------------------------------------------------------
/// @dev layerzero adapter specific error, thrown if caller not layerzero endpoint
error CALLER_NOT_ENDPOINT();
/// @dev hyperlane adapter specific error, thrown if caller not hyperlane mailbox
error CALLER_NOT_MAILBOX();
/// @dev wormhole relayer specific error, thrown if caller not wormhole relayer
error CALLER_NOT_RELAYER();
/// @dev thrown if src chain sender is not valid
error INVALID_SRC_SENDER();
//////////////////////////////////////////////////////////////
// INPUT VALIDATION ERRORS //
//////////////////////////////////////////////////////////////
///@notice errors thrown if input variables are not valid
/// COMMON INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if there is an array length mismatch
error ARRAY_LENGTH_MISMATCH();
/// @dev thrown if payload id does not exist
error INVALID_PAYLOAD_ID();
/// @dev error thrown when msg value should be zero in certain payable functions
error MSG_VALUE_NOT_ZERO();
/// @dev thrown if amb ids length is 0
error ZERO_AMB_ID_LENGTH();
/// @dev thrown if address input is address 0
error ZERO_ADDRESS();
/// @dev thrown if amount input is 0
error ZERO_AMOUNT();
/// @dev thrown if final token is address 0
error ZERO_FINAL_TOKEN();
/// @dev thrown if value input is 0
error ZERO_INPUT_VALUE();
/// SUPERFORM ROUTER INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if the vaults data is invalid
error INVALID_SUPERFORMS_DATA();
/// @dev thrown if receiver address is not set
error RECEIVER_ADDRESS_NOT_SET();
/// SUPERFORM FACTORY INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if a form is not ERC165 compatible
error ERC165_UNSUPPORTED();
/// @dev thrown if a form is not form interface compatible
error FORM_INTERFACE_UNSUPPORTED();
/// @dev error thrown if form implementation address already exists
error FORM_IMPLEMENTATION_ALREADY_EXISTS();
/// @dev error thrown if form implementation id already exists
error FORM_IMPLEMENTATION_ID_ALREADY_EXISTS();
/// @dev thrown if a form does not exist
error FORM_DOES_NOT_EXIST();
/// @dev thrown if form id is larger than max uint16
error INVALID_FORM_ID();
/// @dev thrown if superform not on factory
error SUPERFORM_ID_NONEXISTENT();
/// @dev thrown if same vault and form implementation is used to create new superform
error VAULT_FORM_IMPLEMENTATION_COMBINATION_EXISTS();
/// FORM INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if in case of no txData, if liqData.token != vault.asset()
/// in case of txData, if token output of swap != vault.asset()
error DIFFERENT_TOKENS();
/// @dev thrown if the amount in direct withdraw is not correct
error DIRECT_WITHDRAW_INVALID_LIQ_REQUEST();
/// @dev thrown if the amount in xchain withdraw is not correct
error XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST();
/// LIQUIDITY BRIDGE INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if route id is blacklisted in socket
error BLACKLISTED_ROUTE_ID();
/// @dev thrown if route id is not blacklisted in socket
error NOT_BLACKLISTED_ROUTE_ID();
/// @dev error thrown when txData selector of lifi bridge is a blacklisted selector
error BLACKLISTED_SELECTOR();
/// @dev error thrown when txData selector of lifi bridge is not a blacklisted selector
error NOT_BLACKLISTED_SELECTOR();
/// @dev thrown if a certain action of the user is not allowed given the txData provided
error INVALID_ACTION();
/// @dev thrown if in deposits, the liqDstChainId doesn't match the stateReq dstChainId
error INVALID_DEPOSIT_LIQ_DST_CHAIN_ID();
/// @dev thrown if index is invalid
error INVALID_INDEX();
/// @dev thrown if the chain id in the txdata is invalid
error INVALID_TXDATA_CHAIN_ID();
/// @dev thrown if the validation of bridge txData fails due to a destination call present
error INVALID_TXDATA_NO_DESTINATIONCALL_ALLOWED();
/// @dev thrown if the validation of bridge txData fails due to wrong receiver
error INVALID_TXDATA_RECEIVER();
/// @dev thrown if the validation of bridge txData fails due to wrong token
error INVALID_TXDATA_TOKEN();
/// @dev thrown if txData is not present (in case of xChain actions)
error NO_TXDATA_PRESENT();
/// STATE REGISTRY INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if payload is being updated with final amounts length different than amounts length
error DIFFERENT_PAYLOAD_UPDATE_AMOUNTS_LENGTH();
/// @dev thrown if payload is being updated with tx data length different than liq data length
error DIFFERENT_PAYLOAD_UPDATE_TX_DATA_LENGTH();
/// @dev thrown if keeper update final token is different than the vault underlying
error INVALID_UPDATE_FINAL_TOKEN();
/// @dev thrown if broadcast finality for wormhole is invalid
error INVALID_BROADCAST_FINALITY();
/// @dev thrown if amb id is not valid leading to an address 0 of the implementation
error INVALID_BRIDGE_ID();
/// @dev thrown if chain id involved in xchain message is invalid
error INVALID_CHAIN_ID();
/// @dev thrown if payload update amount isn't equal to dst swapper amount
error INVALID_DST_SWAP_AMOUNT();
/// @dev thrown if message amb and proof amb are the same
error INVALID_PROOF_BRIDGE_ID();
/// @dev thrown if order of proof AMBs is incorrect, either duplicated or not incrementing
error INVALID_PROOF_BRIDGE_IDS();
/// @dev thrown if rescue data lengths are invalid
error INVALID_RESCUE_DATA();
/// @dev thrown if delay is invalid
error INVALID_TIMELOCK_DELAY();
/// @dev thrown if amounts being sent in update payload mean a negative slippage
error NEGATIVE_SLIPPAGE();
/// @dev thrown if slippage is outside of bounds
error SLIPPAGE_OUT_OF_BOUNDS();
/// SUPERPOSITION INPUT VALIDATION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if src senders mismatch in state sync
error SRC_SENDER_MISMATCH();
/// @dev thrown if src tx types mismatch in state sync
error SRC_TX_TYPE_MISMATCH();
//////////////////////////////////////////////////////////////
// EXECUTION ERRORS //
//////////////////////////////////////////////////////////////
///@notice errors thrown due to function execution logic
/// COMMON EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if the swap in a direct deposit resulted in insufficient tokens
error DIRECT_DEPOSIT_SWAP_FAILED();
/// @dev thrown if payload is not unique
error DUPLICATE_PAYLOAD();
/// @dev thrown if native tokens fail to be sent to superform contracts
error FAILED_TO_SEND_NATIVE();
/// @dev thrown if allowance is not correct to deposit
error INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT();
/// @dev thrown if contract has insufficient balance for operations
error INSUFFICIENT_BALANCE();
/// @dev thrown if native amount is not at least equal to the amount in the request
error INSUFFICIENT_NATIVE_AMOUNT();
/// @dev thrown if payload cannot be decoded
error INVALID_PAYLOAD();
/// @dev thrown if payload status is invalid
error INVALID_PAYLOAD_STATUS();
/// @dev thrown if payload type is invalid
error INVALID_PAYLOAD_TYPE();
/// LIQUIDITY BRIDGE EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if we try to decode the final swap output token in a xChain liquidity bridging action
error CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN();
/// @dev thrown if liquidity bridge fails for erc20 or native tokens
error FAILED_TO_EXECUTE_TXDATA(address token);
/// @dev thrown if asset being used for deposit mismatches in multivault deposits
error INVALID_DEPOSIT_TOKEN();
/// STATE REGISTRY EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if bridge tokens haven't arrived to destination
error BRIDGE_TOKENS_PENDING();
/// @dev thrown if withdrawal tx data cannot be updated
error CANNOT_UPDATE_WITHDRAW_TX_DATA();
/// @dev thrown if rescue passed dispute deadline
error DISPUTE_TIME_ELAPSED();
/// @dev thrown if message failed to reach the specified level of quorum needed
error INSUFFICIENT_QUORUM();
/// @dev thrown if broadcast payload is invalid
error INVALID_BROADCAST_PAYLOAD();
/// @dev thrown if broadcast fee is invalid
error INVALID_BROADCAST_FEE();
/// @dev thrown if retry fees is less than required
error INVALID_RETRY_FEE();
/// @dev thrown if broadcast message type is wrong
error INVALID_MESSAGE_TYPE();
/// @dev thrown if payload hash is invalid during `retryMessage` on Layezero implementation
error INVALID_PAYLOAD_HASH();
/// @dev thrown if update payload function was called on a wrong payload
error INVALID_PAYLOAD_UPDATE_REQUEST();
/// @dev thrown if a state registry id is 0
error INVALID_REGISTRY_ID();
/// @dev thrown if a form state registry id is 0
error INVALID_FORM_REGISTRY_ID();
/// @dev thrown if trying to finalize the payload but the withdraw is still locked
error LOCKED();
/// @dev thrown if payload is already updated (during xChain deposits)
error PAYLOAD_ALREADY_UPDATED();
/// @dev thrown if payload is already processed
error PAYLOAD_ALREADY_PROCESSED();
/// @dev thrown if payload is not in UPDATED state
error PAYLOAD_NOT_UPDATED();
/// @dev thrown if rescue is still in timelocked state
error RESCUE_LOCKED();
/// @dev thrown if rescue is already proposed
error RESCUE_ALREADY_PROPOSED();
/// @dev thrown if payload hash is zero during `retryMessage` on Layezero implementation
error ZERO_PAYLOAD_HASH();
/// DST SWAPPER EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if process dst swap is tried for processed payload id
error DST_SWAP_ALREADY_PROCESSED();
/// @dev thrown if indices have duplicates
error DUPLICATE_INDEX();
/// @dev thrown if failed dst swap is already updated
error FAILED_DST_SWAP_ALREADY_UPDATED();
/// @dev thrown if indices are out of bounds
error INDEX_OUT_OF_BOUNDS();
/// @dev thrown if failed swap token amount is 0
error INVALID_DST_SWAPPER_FAILED_SWAP();
/// @dev thrown if failed swap token amount is not 0 and if token balance is less than amount (non zero)
error INVALID_DST_SWAPPER_FAILED_SWAP_NO_TOKEN_BALANCE();
/// @dev thrown if failed swap token amount is not 0 and if native amount is less than amount (non zero)
error INVALID_DST_SWAPPER_FAILED_SWAP_NO_NATIVE_BALANCE();
/// @dev forbid xChain deposits with destination swaps without interim token set (for user protection)
error INVALID_INTERIM_TOKEN();
/// @dev thrown if dst swap output is less than minimum expected
error INVALID_SWAP_OUTPUT();
/// FORM EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if try to forward 4626 share from the superform
error CANNOT_FORWARD_4646_TOKEN();
/// @dev thrown in KYCDAO form if no KYC token is present
error NO_VALID_KYC_TOKEN();
/// @dev thrown in forms where a certain functionality is not allowed or implemented
error NOT_IMPLEMENTED();
/// @dev thrown if form implementation is PAUSED, users cannot perform any action
error PAUSED();
/// @dev thrown if shares != deposit output or assets != redeem output when minting SuperPositions
error VAULT_IMPLEMENTATION_FAILED();
/// @dev thrown if withdrawal tx data is not updated
error WITHDRAW_TOKEN_NOT_UPDATED();
/// @dev thrown if withdrawal tx data is not updated
error WITHDRAW_TX_DATA_NOT_UPDATED();
/// @dev thrown when redeeming from vault yields zero collateral
error WITHDRAW_ZERO_COLLATERAL();
/// PAYMENT HELPER EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if chainlink is reporting an improper price
error CHAINLINK_MALFUNCTION();
/// @dev thrown if chainlink is reporting an incomplete round
error CHAINLINK_INCOMPLETE_ROUND();
/// @dev thrown if feed decimals is not 8
error CHAINLINK_UNSUPPORTED_DECIMAL();
/// EMERGENCY QUEUE EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if emergency withdraw is not queued
error EMERGENCY_WITHDRAW_NOT_QUEUED();
/// @dev thrown if emergency withdraw is already processed
error EMERGENCY_WITHDRAW_PROCESSED_ALREADY();
/// SUPERPOSITION EXECUTION ERRORS
/// ---------------------------------------------------------
/// @dev thrown if uri cannot be updated
error DYNAMIC_URI_FROZEN();
/// @dev thrown if tx history is not found while state sync
error TX_HISTORY_NOT_FOUND();
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
import { IAccessControl } from "openzeppelin-contracts/contracts/access/IAccessControl.sol";
/// @title ISuperRBAC
/// @dev Interface for SuperRBAC
/// @author Zeropoint Labs
interface ISuperRBAC is IAccessControl {
//////////////////////////////////////////////////////////////
// STRUCTS //
//////////////////////////////////////////////////////////////
struct InitialRoleSetup {
address admin;
address emergencyAdmin;
address paymentAdmin;
address csrProcessor;
address tlProcessor;
address brProcessor;
address csrUpdater;
address srcVaaRelayer;
address dstSwapper;
address csrRescuer;
address csrDisputer;
}
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @dev is emitted when superRegistry is set
event SuperRegistrySet(address indexed superRegistry);
/// @dev is emitted when an admin is set for a role
event RoleAdminSet(bytes32 role, bytes32 adminRole);
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev returns the id of the protocol admin role
function PROTOCOL_ADMIN_ROLE() external view returns (bytes32);
/// @dev returns the id of the emergency admin role
function EMERGENCY_ADMIN_ROLE() external view returns (bytes32);
/// @dev returns the id of the payment admin role
function PAYMENT_ADMIN_ROLE() external view returns (bytes32);
/// @dev returns the id of the broadcaster role
function BROADCASTER_ROLE() external view returns (bytes32);
/// @dev returns the id of the core state registry processor role
function CORE_STATE_REGISTRY_PROCESSOR_ROLE() external view returns (bytes32);
/// @dev returns the id of the timelock state registry processor role
function TIMELOCK_STATE_REGISTRY_PROCESSOR_ROLE() external view returns (bytes32);
/// @dev returns the id of the broadcast state registry processor role
function BROADCAST_STATE_REGISTRY_PROCESSOR_ROLE() external view returns (bytes32);
/// @dev returns the id of the core state registry updater role
function CORE_STATE_REGISTRY_UPDATER_ROLE() external view returns (bytes32);
/// @dev returns the id of the dst swapper role
function DST_SWAPPER_ROLE() external view returns (bytes32);
/// @dev returns the id of the core state registry rescuer role
function CORE_STATE_REGISTRY_RESCUER_ROLE() external view returns (bytes32);
/// @dev returns the id of the core state registry rescue disputer role
function CORE_STATE_REGISTRY_DISPUTER_ROLE() external view returns (bytes32);
/// @dev returns the id of wormhole vaa relayer role
function WORMHOLE_VAA_RELAYER_ROLE() external view returns (bytes32);
/// @dev returns whether the given address has the protocol admin role
/// @param admin_ the address to check
function hasProtocolAdminRole(address admin_) external view returns (bool);
/// @dev returns whether the given address has the emergency admin role
/// @param admin_ the address to check
function hasEmergencyAdminRole(address admin_) external view returns (bool);
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev updates the super registry address
function setSuperRegistry(address superRegistry_) external;
/// @dev configures a new role in superForm
/// @param role_ the role to set
/// @param adminRole_ the admin role to set as admin
function setRoleAdmin(bytes32 role_, bytes32 adminRole_) external;
/// @dev revokes the role_ from superRegistryAddressId_ on all chains
/// @param role_ the role to revoke
/// @param extraData_ amb config if broadcasting is required
/// @param superRegistryAddressId_ the super registry address id
function revokeRoleSuperBroadcast(
bytes32 role_,
bytes memory extraData_,
bytes32 superRegistryAddressId_
)
external
payable;
/// @dev allows sync of global roles from different chains using broadcast registry
/// @notice may not work for all roles
function stateSyncBroadcast(bytes memory data_) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
/// @title ISuperRegistry
/// @dev Interface for SuperRegistry
/// @author Zeropoint Labs
interface ISuperRegistry {
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @dev emitted when permit2 is set.
event SetPermit2(address indexed permit2);
/// @dev is emitted when an address is set.
event AddressUpdated(
bytes32 indexed protocolAddressId, uint64 indexed chainId, address indexed oldAddress, address newAddress
);
/// @dev is emitted when a new token bridge is configured.
event SetBridgeAddress(uint256 indexed bridgeId, address indexed bridgeAddress);
/// @dev is emitted when a new bridge validator is configured.
event SetBridgeValidator(uint256 indexed bridgeId, address indexed bridgeValidator);
/// @dev is emitted when a new amb is configured.
event SetAmbAddress(uint8 indexed ambId_, address indexed ambAddress_, bool indexed isBroadcastAMB_);
/// @dev is emitted when a new state registry is configured.
event SetStateRegistryAddress(uint8 indexed registryId_, address indexed registryAddress_);
/// @dev is emitted when a new delay is configured.
event SetDelay(uint256 indexed oldDelay_, uint256 indexed newDelay_);
/// @dev is emitted when a new vault limit is configured
event SetVaultLimitPerDestination(uint64 indexed chainId_, uint256 indexed vaultLimit_);
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev gets the deposit rescue delay
function delay() external view returns (uint256);
/// @dev returns the permit2 address
function PERMIT2() external view returns (address);
/// @dev returns the id of the superform router module
function SUPERFORM_ROUTER() external view returns (bytes32);
/// @dev returns the id of the superform factory module
function SUPERFORM_FACTORY() external view returns (bytes32);
/// @dev returns the id of the superform paymaster contract
function PAYMASTER() external view returns (bytes32);
/// @dev returns the id of the superform payload helper contract
function PAYMENT_HELPER() external view returns (bytes32);
/// @dev returns the id of the core state registry module
function CORE_STATE_REGISTRY() external view returns (bytes32);
/// @dev returns the id of the timelock form state registry module
function TIMELOCK_STATE_REGISTRY() external view returns (bytes32);
/// @dev returns the id of the broadcast state registry module
function BROADCAST_REGISTRY() external view returns (bytes32);
/// @dev returns the id of the super positions module
function SUPER_POSITIONS() external view returns (bytes32);
/// @dev returns the id of the super rbac module
function SUPER_RBAC() external view returns (bytes32);
/// @dev returns the id of the payload helper module
function PAYLOAD_HELPER() external view returns (bytes32);
/// @dev returns the id of the dst swapper keeper
function DST_SWAPPER() external view returns (bytes32);
/// @dev returns the id of the emergency queue
function EMERGENCY_QUEUE() external view returns (bytes32);
/// @dev returns the id of the superform receiver
function SUPERFORM_RECEIVER() external view returns (bytes32);
/// @dev returns the id of the payment admin keeper
function PAYMENT_ADMIN() external view returns (bytes32);
/// @dev returns the id of the core state registry processor keeper
function CORE_REGISTRY_PROCESSOR() external view returns (bytes32);
/// @dev returns the id of the broadcast registry processor keeper
function BROADCAST_REGISTRY_PROCESSOR() external view returns (bytes32);
/// @dev returns the id of the timelock form state registry processor keeper
function TIMELOCK_REGISTRY_PROCESSOR() external view returns (bytes32);
/// @dev returns the id of the core state registry updater keeper
function CORE_REGISTRY_UPDATER() external view returns (bytes32);
/// @dev returns the id of the core state registry updater keeper
function CORE_REGISTRY_RESCUER() external view returns (bytes32);
/// @dev returns the id of the core state registry updater keeper
function CORE_REGISTRY_DISPUTER() external view returns (bytes32);
/// @dev returns the id of the core state registry updater keeper
function DST_SWAPPER_PROCESSOR() external view returns (bytes32);
/// @dev gets the address of a contract on current chain
/// @param id_ is the id of the contract
function getAddress(bytes32 id_) external view returns (address);
/// @dev gets the address of a contract on a target chain
/// @param id_ is the id of the contract
/// @param chainId_ is the chain id of that chain
function getAddressByChainId(bytes32 id_, uint64 chainId_) external view returns (address);
/// @dev gets the address of a bridge
/// @param bridgeId_ is the id of a bridge
/// @return bridgeAddress_ is the address of the form
function getBridgeAddress(uint8 bridgeId_) external view returns (address bridgeAddress_);
/// @dev gets the address of a bridge validator
/// @param bridgeId_ is the id of a bridge
/// @return bridgeValidator_ is the address of the form
function getBridgeValidator(uint8 bridgeId_) external view returns (address bridgeValidator_);
/// @dev gets the address of a amb
/// @param ambId_ is the id of a bridge
/// @return ambAddress_ is the address of the form
function getAmbAddress(uint8 ambId_) external view returns (address ambAddress_);
/// @dev gets the id of the amb
/// @param ambAddress_ is the address of an amb
/// @return ambId_ is the identifier of an amb
function getAmbId(address ambAddress_) external view returns (uint8 ambId_);
/// @dev gets the address of the registry
/// @param registryId_ is the id of the state registry
/// @return registryAddress_ is the address of the state registry
function getStateRegistry(uint8 registryId_) external view returns (address registryAddress_);
/// @dev gets the id of the registry
/// @notice reverts if the id is not found
/// @param registryAddress_ is the address of the state registry
/// @return registryId_ is the id of the state registry
function getStateRegistryId(address registryAddress_) external view returns (uint8 registryId_);
/// @dev gets the safe vault limit
/// @param chainId_ is the id of the remote chain
/// @return vaultLimitPerDestination_ is the safe number of vaults to deposit
/// without hitting out of gas error
function getVaultLimitPerDestination(uint64 chainId_) external view returns (uint256 vaultLimitPerDestination_);
/// @dev helps validate if an address is a valid state registry
/// @param registryAddress_ is the address of the state registry
/// @return valid_ a flag indicating if its valid.
function isValidStateRegistry(address registryAddress_) external view returns (bool valid_);
/// @dev helps validate if an address is a valid amb implementation
/// @param ambAddress_ is the address of the amb implementation
/// @return valid_ a flag indicating if its valid.
function isValidAmbImpl(address ambAddress_) external view returns (bool valid_);
/// @dev helps validate if an address is a valid broadcast amb implementation
/// @param ambAddress_ is the address of the broadcast amb implementation
/// @return valid_ a flag indicating if its valid.
function isValidBroadcastAmbImpl(address ambAddress_) external view returns (bool valid_);
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @dev sets the deposit rescue delay
/// @param delay_ the delay in seconds before the deposit rescue can be finalized
function setDelay(uint256 delay_) external;
/// @dev sets the permit2 address
/// @param permit2_ the address of the permit2 contract
function setPermit2(address permit2_) external;
/// @dev sets the safe vault limit
/// @param chainId_ is the remote chain identifier
/// @param vaultLimit_ is the max limit of vaults per transaction
function setVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_) external;
/// @dev sets new addresses on specific chains.
/// @param ids_ are the identifiers of the address on that chain
/// @param newAddresses_ are the new addresses on that chain
/// @param chainIds_ are the chain ids of that chain
function batchSetAddress(
bytes32[] calldata ids_,
address[] calldata newAddresses_,
uint64[] calldata chainIds_
)
external;
/// @dev sets a new address on a specific chain.
/// @param id_ the identifier of the address on that chain
/// @param newAddress_ the new address on that chain
/// @param chainId_ the chain id of that chain
function setAddress(bytes32 id_, address newAddress_, uint64 chainId_) external;
/// @dev allows admin to set the bridge address for an bridge id.
/// @notice this function operates in an APPEND-ONLY fashion.
/// @param bridgeId_ represents the bridge unique identifier.
/// @param bridgeAddress_ represents the bridge address.
/// @param bridgeValidator_ represents the bridge validator address.
function setBridgeAddresses(
uint8[] memory bridgeId_,
address[] memory bridgeAddress_,
address[] memory bridgeValidator_
)
external;
/// @dev allows admin to set the amb address for an amb id.
/// @notice this function operates in an APPEND-ONLY fashion.
/// @param ambId_ represents the bridge unique identifier.
/// @param ambAddress_ represents the bridge address.
/// @param isBroadcastAMB_ represents whether the amb implementation supports broadcasting
function setAmbAddress(
uint8[] memory ambId_,
address[] memory ambAddress_,
bool[] memory isBroadcastAMB_
)
external;
/// @dev allows admin to set the state registry address for an state registry id.
/// @notice this function operates in an APPEND-ONLY fashion.
/// @param registryId_ represents the state registry's unique identifier.
/// @param registryAddress_ represents the state registry's address.
function setStateRegistryAddress(uint8[] memory registryId_, address[] memory registryAddress_) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
/// @title IRewardsDistributor
/// @notice interface for the RewardsDistributor contract
/// @author Zeropoint Labs
interface IRewardsDistributor {
//////////////////////////////////////////////////////////////
// ERRORS //
//////////////////////////////////////////////////////////////
/// @dev error message for not being a rewards admin
error NOT_REWARDS_ADMIN();
/// @dev error message for an invalid claim
error INVALID_CLAIM();
/// @dev error message for an invalid batch request (different array lengths)
error INVALID_BATCH_REQ();
/// @dev error message for an invalid claim (invalid token/amounts array length)
error INVALID_REQ_TOKENS_AMOUNTS();
/// @dev error message for an invalid batch claim (invalid token/amounts array length)
error INVALID_BATCH_REQ_TOKENS_AMOUNTS();
/// @dev error message for an invalid merkle root
error INVALID_MERKLE_ROOT();
/// @dev error message for an invalid receiver
error INVALID_RECEIVER();
/// @dev error message for when merkle root is not set
error MERKLE_ROOT_NOT_SET();
/// @dev error message for when the array length is zero
error ZERO_ARR_LENGTH();
/// @dev error message for when the claimer has already claimed their rewards
error ALREADY_CLAIMED();
/// @dev error message for when the claim deadline has passed
error CLAIM_DEADLINE_PASSED();
//////////////////////////////////////////////////////////////
// EVENTS //
//////////////////////////////////////////////////////////////
/// @dev Emitted when tokens are claimed.
event RewardsClaimed(
address indexed claimer,
address indexed receiver,
uint256 periodId,
address[] rewardTokens_,
uint256[] amountsClaimed_
);
/// @dev Emitted when new periodic rewards are set.
event PeriodicRewardsSet(uint256 indexed periodId, bytes32 merkleRoot, uint256 startTimestamp);
//////////////////////////////////////////////////////////////
// STRUCTS //
//////////////////////////////////////////////////////////////
struct PeriodicRewardsData {
uint256 startTimestamp;
bytes32 merkleRoot;
}
//////////////////////////////////////////////////////////////
// EXTERNAL WRITE FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice allows owner to set the merkle root for the current period rewards
/// @param root_ is the merkle root for that period generated offchain
/// @dev [gas-opt]: function is payable to avoid msg.value checks
function setPeriodicRewards(bytes32 root_) external payable;
/// @notice lets an account claim a given quantity of reward tokens.
/// @param receiver_ is the receiver of the tokens to claim.
/// @param periodId_ is the specific period to claim
/// @param rewardTokens_ are the address of the rewards token to claim on the specific period
/// @param amountsClaimed_ adre the amount of tokens to claim for each reward token
/// @param proof_ the merkle proof
function claim(
address receiver_,
uint256 periodId_,
address[] calldata rewardTokens_,
uint256[] calldata amountsClaimed_,
bytes32[] calldata proof_
)
external;
/// @notice is a batching version of claim()
function batchClaim(
address receiver_,
uint256[] calldata periodIds_,
address[][] calldata rewardTokens_,
uint256[][] calldata amountsClaimed_,
bytes32[][] calldata proofs_
)
external;
/// @notice allows the owner to rescue any ERC20 tokens sent to the contract
/// @param rewardTokens_ are the address of the rewards token to claim on the specific period
/// @param amounts_ are the amount of tokens to claim for each reward token
function rescueRewards(address[] calldata rewardTokens_, uint256[] calldata amounts_) external;
/// @notice allows the owner to invalidate a period
/// @param periodId_ is the period identifier
function invalidatePeriod(uint256 periodId_) external;
//////////////////////////////////////////////////////////////
// EXTERNAL VIEW FUNCTIONS //
//////////////////////////////////////////////////////////////
/// @notice helps validate if the claim is valid
/// @param claimer_ is the address of the claiming wallet
/// @param periodId_ is the period identifier
/// @param rewardTokens_ are the address of the rewards token to claim on the specific period
/// @param amountsClaimed_ adre the amount of tokens to claim for each reward token
/// @param proof_ is the merkle proof
/// @dev returns false even if proof is valid and user already claimed their periodic rewards
function verifyClaim(
address claimer_,
uint256 periodId_,
address[] calldata rewardTokens_,
uint256[] calldata amountsClaimed_,
bytes32[] calldata proof_
)
external
view
returns (bool valid);
}// 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: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC-20 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.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
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].
*
* CAUTION: See Security Considerations above.
*/
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
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC-165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}{
"remappings": [
"solmate/=lib/ERC1155A/lib/solmate/src/",
"ERC1155A/=lib/ERC1155A/src/",
"@openzeppelin/contracts/=lib/ERC1155A/lib/openzeppelin-contracts/contracts/",
"ds-test/=lib/ds-test/src/",
"erc4626-tests/=lib/ERC1155A/lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/ERC1155A/lib/openzeppelin-contracts/",
"pigeon/=lib/pigeon/src/",
"solady/=lib/pigeon/lib/solady/",
"super-vaults/=lib/super-vaults/src/",
"v2-core/=lib/super-vaults/lib/v2-core/contracts/",
"v2-periphery/=lib/super-vaults/lib/v2-periphery/contracts/",
"v3-core/=lib/super-vaults/lib/v3-core/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"superRegistry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ALREADY_CLAIMED","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"BLOCK_CHAIN_ID_OUT_OF_BOUNDS","type":"error"},{"inputs":[],"name":"CLAIM_DEADLINE_PASSED","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"INVALID_BATCH_REQ","type":"error"},{"inputs":[],"name":"INVALID_BATCH_REQ_TOKENS_AMOUNTS","type":"error"},{"inputs":[],"name":"INVALID_CLAIM","type":"error"},{"inputs":[],"name":"INVALID_MERKLE_ROOT","type":"error"},{"inputs":[],"name":"INVALID_RECEIVER","type":"error"},{"inputs":[],"name":"INVALID_REQ_TOKENS_AMOUNTS","type":"error"},{"inputs":[],"name":"MERKLE_ROOT_NOT_SET","type":"error"},{"inputs":[],"name":"NOT_REWARDS_ADMIN","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_ARR_LENGTH","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"periodId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"startTimestamp","type":"uint256"}],"name":"PeriodicRewardsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimer","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"periodId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"rewardTokens_","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amountsClaimed_","type":"uint256[]"}],"name":"RewardsClaimed","type":"event"},{"inputs":[],"name":"CHAIN_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEADLINE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256[]","name":"periodIds_","type":"uint256[]"},{"internalType":"address[][]","name":"rewardTokens_","type":"address[][]"},{"internalType":"uint256[][]","name":"amountsClaimed_","type":"uint256[][]"},{"internalType":"bytes32[][]","name":"proofs_","type":"bytes32[][]"}],"name":"batchClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256","name":"periodId_","type":"uint256"},{"internalType":"address[]","name":"rewardTokens_","type":"address[]"},{"internalType":"uint256[]","name":"amountsClaimed_","type":"uint256[]"},{"internalType":"bytes32[]","name":"proof_","type":"bytes32[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentPeriodId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"periodId_","type":"uint256"}],"name":"invalidatePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"periodId","type":"uint256"},{"internalType":"address","name":"claimerAddress","type":"address"}],"name":"periodicRewardsClaimed","outputs":[{"internalType":"bool","name":"claimed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"periodId","type":"uint256"}],"name":"periodicRewardsMerkleRootData","outputs":[{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"rewardTokens_","type":"address[]"},{"internalType":"uint256[]","name":"amounts_","type":"uint256[]"}],"name":"rescueRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root_","type":"bytes32"}],"name":"setPeriodicRewards","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"superRegistry","outputs":[{"internalType":"contract ISuperRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256","name":"periodId_","type":"uint256"},{"internalType":"address[]","name":"rewardTokens_","type":"address[]"},{"internalType":"uint256[]","name":"amountsClaimed_","type":"uint256[]"},{"internalType":"bytes32[]","name":"proof_","type":"bytes32[]"}],"name":"verifyClaim","outputs":[{"internalType":"bool","name":"valid","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60c060405234801561001057600080fd5b5060405161168f38038061168f83398101604081905261002f9161009c565b6001600160a01b0381166100565760405163538ba4f960e01b815260040160405180910390fd5b6001600160401b0346111561007e57604051637ecdf93360e01b815260040160405180910390fd5b6001600160a01b03166080526001600160401b03461660a0526100cc565b6000602082840312156100ae57600080fd5b81516001600160a01b03811681146100c557600080fd5b9392505050565b60805160a05161157c610113600039600081816101ef0152610c7701526000818160d30152818161030401528181610826015281816109920152610aea015261157c6000f3fe6080604052600436106100a75760003560e01c80637426159111610064578063742615911461019257806385e1f4d0146101dd578063988e65951461022a578063a082c86e1461024e578063b6e5ef1814610266578063e08480d01461028657600080fd5b80632462cbfb146100ac57806324c73dda146100c15780632ad750371461011257806347575953146101325780634cf309ae146101525780635092089414610172575b600080fd5b6100bf6100ba366004611066565b6102cf565b005b3480156100cd57600080fd5b506100f57f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561011e57600080fd5b506100bf61012d3660046110e0565b6104b2565b34801561013e57600080fd5b506100bf61014d366004611196565b61058b565b34801561015e57600080fd5b506100bf61016d366004611066565b6107f1565b34801561017e57600080fd5b506100bf61018d36600461126f565b61095d565b34801561019e57600080fd5b506101cd6101ad3660046112db565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610109565b3480156101e957600080fd5b506102117f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610109565b34801561023657600080fd5b5061024060005481565b604051908152602001610109565b34801561025a57600080fd5b506102406301dfe20081565b34801561027257600080fd5b506101cd6102813660046110e0565b610bb8565b34801561029257600080fd5b506102ba6102a1366004611066565b6001602081905260009182526040909120805491015482565b60408051928352602083019190915201610109565b6040516321f8a72160e01b81527f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa86860048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015610353573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610377919061130b565b604051632474521560e21b81527fdb6fbae5cd13d8264d7ed12219ef2882c1e83b8b12f47819baa96f32f69a168260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa1580156103e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104079190611328565b61042457604051636b950a2760e01b815260040160405180910390fd5b80610442576040516351fe655d60e11b815260040160405180910390fd5b600080548082526001602081905260408320428082559101849055825491929091819061046e90611360565b90915550604080518481526020810183905283917f2a3da266b34544817d84244346155ad671b49cae5d8277fc1c68befe5538928b910160405180910390a2505050565b6001600160a01b0388166104d957604051632b0ddb9160e01b815260040160405180910390fd5b8460008190036104fc57604051637935375d60e01b815260040160405180910390fd5b80841461051c5760405163b070f43760e01b815260040160405180910390fd5b61052d898989898989878a8a610d31565b886001600160a01b0316336001600160a01b03167f98ccd44fec17fcfcde09b0afc6bfc3e943dc858ff079d4c0fc60847f79f2cc1a8a8a8a8a8a6040516105789594939291906113f4565b60405180910390a3505050505050505050565b6001600160a01b0389166105b257604051632b0ddb9160e01b815260040160405180910390fd5b8660008190036105d557604051637935375d60e01b815260040160405180910390fd5b80821480156105e357508086145b80156105ee57508084145b61060b576040516318e168b160e21b815260040160405180910390fd5b60005b818110156107e457600088888381811061062a5761062a61142d565b905060200281019061063c9190611443565b905090508060000361066157604051637935375d60e01b815260040160405180910390fd5b8686838181106106735761067361142d565b90506020028101906106859190611443565b905081146106a65760405163de7215af60e01b815260040160405180910390fd5b6107358c8c8c858181106106bc576106bc61142d565b905060200201358b8b868181106106d5576106d561142d565b90506020028101906106e79190611443565b8b8b888181106106f9576106f961142d565b905060200281019061070b9190611443565b878c8c8b81811061071e5761071e61142d565b90506020028101906107309190611443565b610d31565b6001600160a01b038c16337f98ccd44fec17fcfcde09b0afc6bfc3e943dc858ff079d4c0fc60847f79f2cc1a8d8d868181106107735761077361142d565b905060200201358c8c8781811061078c5761078c61142d565b905060200281019061079e9190611443565b8c8c898181106107b0576107b061142d565b90506020028101906107c29190611443565b6040516107d39594939291906113f4565b60405180910390a35060010161060e565b5050505050505050505050565b6040516321f8a72160e01b81527f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa86860048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015610875573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610899919061130b565b604051632474521560e21b81527fdb6fbae5cd13d8264d7ed12219ef2882c1e83b8b12f47819baa96f32f69a168260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610905573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109299190611328565b61094657604051636b950a2760e01b815260040160405180910390fd5b600090815260016020819052604082208281550155565b6040516321f8a72160e01b81527f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa86860048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa1580156109e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a05919061130b565b604051632474521560e21b81527fdb6fbae5cd13d8264d7ed12219ef2882c1e83b8b12f47819baa96f32f69a168260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611328565b610ab257604051636b950a2760e01b815260040160405180910390fd5b6040516321f8a72160e01b81527fbddfa8c39a1f6275bcfb3aa5c70638c466999edbf14e6162d81b3492caca9fce60048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906321f8a72190602401602060405180830381865afa158015610b39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5d919061130b565b9050836000819003610b8257604051637935375d60e01b815260040160405180910390fd5b808314610ba25760405163b070f43760e01b815260040160405180910390fd5b610bb0828787878782610da4565b505050505050565b60008781526001602081905260408220015480610be857604051631ddb8b6b60e21b815260040160405180910390fd5b600089815260016020526040812054610c06906301dfe2009061148d565b905080421115610c295760405163712174ff60e11b815260040160405180910390fd5b60008a81526002602090815260408083206001600160a01b038f16845290915290205460ff1615610c6d5760405163a308b6e360e01b815260040160405180910390fd5b60008b8b8b8b8b8b7f0000000000000000000000000000000000000000000000000000000000000000604051602001610cac97969594939291906114a0565b60408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001209050610d21868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250879250859150610e149050565b9c9b505050505050505050505050565b610d418989898989898888610bb8565b610d5e5760405163095f258360e01b815260040160405180910390fd5b60008881526002602090815260408083206001600160a01b038d1684529091529020805460ff19166001179055610d99898888888888610da4565b505050505050505050565b60005b81811015610e0b57610e0387858584818110610dc557610dc561142d565b90506020020135888885818110610dde57610dde61142d565b9050602002016020810190610df391906114fa565b6001600160a01b03169190610e2c565b600101610da7565b50505050505050565b600082610e218584610e83565b1490505b9392505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610e7e908490610ec8565b505050565b600081815b8451811015610ebe57610eb482868381518110610ea757610ea761142d565b6020026020010151610f30565b9150600101610e88565b5090505b92915050565b6000610edd6001600160a01b03841683610f5c565b90508051600014158015610f02575080806020019051810190610f009190611328565b155b15610e7e57604051635274afe760e01b81526001600160a01b03841660048201526024015b60405180910390fd5b6000818310610f4c576000828152602084905260409020610e25565b5060009182526020526040902090565b6060610e258383600084600080856001600160a01b03168486604051610f829190611517565b60006040518083038185875af1925050503d8060008114610fbf576040519150601f19603f3d011682016040523d82523d6000602084013e610fc4565b606091505b5091509150610fd4868383610fde565b9695505050505050565b606082610ff357610fee8261103a565b610e25565b815115801561100a57506001600160a01b0384163b155b1561103357604051639996b31560e01b81526001600160a01b0385166004820152602401610f27565b5080610e25565b80511561104a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b60006020828403121561107857600080fd5b5035919050565b6001600160a01b038116811461106357600080fd5b60008083601f8401126110a657600080fd5b50813567ffffffffffffffff8111156110be57600080fd5b6020830191508360208260051b85010111156110d957600080fd5b9250929050565b60008060008060008060008060a0898b0312156110fc57600080fd5b88356111078161107f565b975060208901359650604089013567ffffffffffffffff8082111561112b57600080fd5b6111378c838d01611094565b909850965060608b013591508082111561115057600080fd5b61115c8c838d01611094565b909650945060808b013591508082111561117557600080fd5b506111828b828c01611094565b999c989b5096995094979396929594505050565b600080600080600080600080600060a08a8c0312156111b457600080fd5b89356111bf8161107f565b985060208a013567ffffffffffffffff808211156111dc57600080fd5b6111e88d838e01611094565b909a50985060408c013591508082111561120157600080fd5b61120d8d838e01611094565b909850965060608c013591508082111561122657600080fd5b6112328d838e01611094565b909650945060808c013591508082111561124b57600080fd5b506112588c828d01611094565b915080935050809150509295985092959850929598565b6000806000806040858703121561128557600080fd5b843567ffffffffffffffff8082111561129d57600080fd5b6112a988838901611094565b909650945060208701359150808211156112c257600080fd5b506112cf87828801611094565b95989497509550505050565b600080604083850312156112ee57600080fd5b8235915060208301356113008161107f565b809150509250929050565b60006020828403121561131d57600080fd5b8151610e258161107f565b60006020828403121561133a57600080fd5b81518015158114610e2557600080fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016113725761137261134a565b5060010190565b8183526000602080850194508260005b858110156113b757813561139c8161107f565b6001600160a01b031687529582019590820190600101611389565b509495945050505050565b81835260006001600160fb1b038311156113db57600080fd5b8260051b80836020870137939093016020019392505050565b85815260606020820152600061140e606083018688611379565b82810360408401526114218185876113c2565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261145a57600080fd5b83018035915067ffffffffffffffff82111561147557600080fd5b6020019150600581901b36038213156110d957600080fd5b80820180821115610ec257610ec261134a565b60018060a01b038816815286602082015260a0604082015260006114c860a083018789611379565b82810360608401526114db8186886113c2565b91505067ffffffffffffffff8316608083015298975050505050505050565b60006020828403121561150c57600080fd5b8135610e258161107f565b6000825160005b81811015611538576020818601810151858301520161151e565b50600092019182525091905056fea2646970667358221220241b9e92ed55f629d54163ec0fea64e8fedbdff5a64305db9bcb257e674f828764736f6c6343000817003300000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514
Deployed Bytecode
0x6080604052600436106100a75760003560e01c80637426159111610064578063742615911461019257806385e1f4d0146101dd578063988e65951461022a578063a082c86e1461024e578063b6e5ef1814610266578063e08480d01461028657600080fd5b80632462cbfb146100ac57806324c73dda146100c15780632ad750371461011257806347575953146101325780634cf309ae146101525780635092089414610172575b600080fd5b6100bf6100ba366004611066565b6102cf565b005b3480156100cd57600080fd5b506100f57f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a251481565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561011e57600080fd5b506100bf61012d3660046110e0565b6104b2565b34801561013e57600080fd5b506100bf61014d366004611196565b61058b565b34801561015e57600080fd5b506100bf61016d366004611066565b6107f1565b34801561017e57600080fd5b506100bf61018d36600461126f565b61095d565b34801561019e57600080fd5b506101cd6101ad3660046112db565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610109565b3480156101e957600080fd5b506102117f000000000000000000000000000000000000000000000000000000000000000181565b60405167ffffffffffffffff9091168152602001610109565b34801561023657600080fd5b5061024060005481565b604051908152602001610109565b34801561025a57600080fd5b506102406301dfe20081565b34801561027257600080fd5b506101cd6102813660046110e0565b610bb8565b34801561029257600080fd5b506102ba6102a1366004611066565b6001602081905260009182526040909120805491015482565b60408051928352602083019190915201610109565b6040516321f8a72160e01b81527f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa86860048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015610353573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610377919061130b565b604051632474521560e21b81527fdb6fbae5cd13d8264d7ed12219ef2882c1e83b8b12f47819baa96f32f69a168260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa1580156103e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104079190611328565b61042457604051636b950a2760e01b815260040160405180910390fd5b80610442576040516351fe655d60e11b815260040160405180910390fd5b600080548082526001602081905260408320428082559101849055825491929091819061046e90611360565b90915550604080518481526020810183905283917f2a3da266b34544817d84244346155ad671b49cae5d8277fc1c68befe5538928b910160405180910390a2505050565b6001600160a01b0388166104d957604051632b0ddb9160e01b815260040160405180910390fd5b8460008190036104fc57604051637935375d60e01b815260040160405180910390fd5b80841461051c5760405163b070f43760e01b815260040160405180910390fd5b61052d898989898989878a8a610d31565b886001600160a01b0316336001600160a01b03167f98ccd44fec17fcfcde09b0afc6bfc3e943dc858ff079d4c0fc60847f79f2cc1a8a8a8a8a8a6040516105789594939291906113f4565b60405180910390a3505050505050505050565b6001600160a01b0389166105b257604051632b0ddb9160e01b815260040160405180910390fd5b8660008190036105d557604051637935375d60e01b815260040160405180910390fd5b80821480156105e357508086145b80156105ee57508084145b61060b576040516318e168b160e21b815260040160405180910390fd5b60005b818110156107e457600088888381811061062a5761062a61142d565b905060200281019061063c9190611443565b905090508060000361066157604051637935375d60e01b815260040160405180910390fd5b8686838181106106735761067361142d565b90506020028101906106859190611443565b905081146106a65760405163de7215af60e01b815260040160405180910390fd5b6107358c8c8c858181106106bc576106bc61142d565b905060200201358b8b868181106106d5576106d561142d565b90506020028101906106e79190611443565b8b8b888181106106f9576106f961142d565b905060200281019061070b9190611443565b878c8c8b81811061071e5761071e61142d565b90506020028101906107309190611443565b610d31565b6001600160a01b038c16337f98ccd44fec17fcfcde09b0afc6bfc3e943dc858ff079d4c0fc60847f79f2cc1a8d8d868181106107735761077361142d565b905060200201358c8c8781811061078c5761078c61142d565b905060200281019061079e9190611443565b8c8c898181106107b0576107b061142d565b90506020028101906107c29190611443565b6040516107d39594939291906113f4565b60405180910390a35060010161060e565b5050505050505050505050565b6040516321f8a72160e01b81527f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa86860048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015610875573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610899919061130b565b604051632474521560e21b81527fdb6fbae5cd13d8264d7ed12219ef2882c1e83b8b12f47819baa96f32f69a168260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610905573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109299190611328565b61094657604051636b950a2760e01b815260040160405180910390fd5b600090815260016020819052604082208281550155565b6040516321f8a72160e01b81527f6b50fa17b77d24e42e27a04b69fe50cd6967cfb767d18de0bd5fe7e1a32aa86860048201527f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa1580156109e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a05919061130b565b604051632474521560e21b81527fdb6fbae5cd13d8264d7ed12219ef2882c1e83b8b12f47819baa96f32f69a168260048201523360248201526001600160a01b0391909116906391d1485490604401602060405180830381865afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611328565b610ab257604051636b950a2760e01b815260040160405180910390fd5b6040516321f8a72160e01b81527fbddfa8c39a1f6275bcfb3aa5c70638c466999edbf14e6162d81b3492caca9fce60048201526000907f00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a25146001600160a01b0316906321f8a72190602401602060405180830381865afa158015610b39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5d919061130b565b9050836000819003610b8257604051637935375d60e01b815260040160405180910390fd5b808314610ba25760405163b070f43760e01b815260040160405180910390fd5b610bb0828787878782610da4565b505050505050565b60008781526001602081905260408220015480610be857604051631ddb8b6b60e21b815260040160405180910390fd5b600089815260016020526040812054610c06906301dfe2009061148d565b905080421115610c295760405163712174ff60e11b815260040160405180910390fd5b60008a81526002602090815260408083206001600160a01b038f16845290915290205460ff1615610c6d5760405163a308b6e360e01b815260040160405180910390fd5b60008b8b8b8b8b8b7f0000000000000000000000000000000000000000000000000000000000000001604051602001610cac97969594939291906114a0565b60408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001209050610d21868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250879250859150610e149050565b9c9b505050505050505050505050565b610d418989898989898888610bb8565b610d5e5760405163095f258360e01b815260040160405180910390fd5b60008881526002602090815260408083206001600160a01b038d1684529091529020805460ff19166001179055610d99898888888888610da4565b505050505050505050565b60005b81811015610e0b57610e0387858584818110610dc557610dc561142d565b90506020020135888885818110610dde57610dde61142d565b9050602002016020810190610df391906114fa565b6001600160a01b03169190610e2c565b600101610da7565b50505050505050565b600082610e218584610e83565b1490505b9392505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610e7e908490610ec8565b505050565b600081815b8451811015610ebe57610eb482868381518110610ea757610ea761142d565b6020026020010151610f30565b9150600101610e88565b5090505b92915050565b6000610edd6001600160a01b03841683610f5c565b90508051600014158015610f02575080806020019051810190610f009190611328565b155b15610e7e57604051635274afe760e01b81526001600160a01b03841660048201526024015b60405180910390fd5b6000818310610f4c576000828152602084905260409020610e25565b5060009182526020526040902090565b6060610e258383600084600080856001600160a01b03168486604051610f829190611517565b60006040518083038185875af1925050503d8060008114610fbf576040519150601f19603f3d011682016040523d82523d6000602084013e610fc4565b606091505b5091509150610fd4868383610fde565b9695505050505050565b606082610ff357610fee8261103a565b610e25565b815115801561100a57506001600160a01b0384163b155b1561103357604051639996b31560e01b81526001600160a01b0385166004820152602401610f27565b5080610e25565b80511561104a5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b60006020828403121561107857600080fd5b5035919050565b6001600160a01b038116811461106357600080fd5b60008083601f8401126110a657600080fd5b50813567ffffffffffffffff8111156110be57600080fd5b6020830191508360208260051b85010111156110d957600080fd5b9250929050565b60008060008060008060008060a0898b0312156110fc57600080fd5b88356111078161107f565b975060208901359650604089013567ffffffffffffffff8082111561112b57600080fd5b6111378c838d01611094565b909850965060608b013591508082111561115057600080fd5b61115c8c838d01611094565b909650945060808b013591508082111561117557600080fd5b506111828b828c01611094565b999c989b5096995094979396929594505050565b600080600080600080600080600060a08a8c0312156111b457600080fd5b89356111bf8161107f565b985060208a013567ffffffffffffffff808211156111dc57600080fd5b6111e88d838e01611094565b909a50985060408c013591508082111561120157600080fd5b61120d8d838e01611094565b909850965060608c013591508082111561122657600080fd5b6112328d838e01611094565b909650945060808c013591508082111561124b57600080fd5b506112588c828d01611094565b915080935050809150509295985092959850929598565b6000806000806040858703121561128557600080fd5b843567ffffffffffffffff8082111561129d57600080fd5b6112a988838901611094565b909650945060208701359150808211156112c257600080fd5b506112cf87828801611094565b95989497509550505050565b600080604083850312156112ee57600080fd5b8235915060208301356113008161107f565b809150509250929050565b60006020828403121561131d57600080fd5b8151610e258161107f565b60006020828403121561133a57600080fd5b81518015158114610e2557600080fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016113725761137261134a565b5060010190565b8183526000602080850194508260005b858110156113b757813561139c8161107f565b6001600160a01b031687529582019590820190600101611389565b509495945050505050565b81835260006001600160fb1b038311156113db57600080fd5b8260051b80836020870137939093016020019392505050565b85815260606020820152600061140e606083018688611379565b82810360408401526114218185876113c2565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261145a57600080fd5b83018035915067ffffffffffffffff82111561147557600080fd5b6020019150600581901b36038213156110d957600080fd5b80820180821115610ec257610ec261134a565b60018060a01b038816815286602082015260a0604082015260006114c860a083018789611379565b82810360608401526114db8186886113c2565b91505067ffffffffffffffff8316608083015298975050505050505050565b60006020828403121561150c57600080fd5b8135610e258161107f565b6000825160005b81811015611538576020818601810151858301520161151e565b50600092019182525091905056fea2646970667358221220241b9e92ed55f629d54163ec0fea64e8fedbdff5a64305db9bcb257e674f828764736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514
-----Decoded View---------------
Arg [0] : superRegistry_ (address): 0x17A332dC7B40aE701485023b219E9D6f493a2514
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000017a332dc7b40ae701485023b219e9d6f493a2514
Loading...
Loading
Loading...
Loading
Net Worth in USD
$269,274.37
Net Worth in ETH
92.869738
Token Allocations
MORPHO
61.12%
USD₮0
9.85%
REUL
8.71%
Others
20.32%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 41.28% | $1.24 | 89,652.3391 | $111,168.9 | |
| ETH | 8.31% | $1.8 | 12,396.0048 | $22,368.28 | |
| ETH | 4.32% | $0.327554 | 35,549.4027 | $11,644.35 | |
| ETH | 1.49% | $3,081.26 | 1.3047 | $4,020.11 | |
| ETH | 0.58% | $0.999608 | 1,563.0115 | $1,562.4 | |
| ETH | 0.16% | $3,551.22 | 0.1207 | $428.69 | |
| ETH | 0.14% | $0.074966 | 5,033.1045 | $377.31 | |
| ETH | 0.06% | $23.77 | 6.4565 | $153.47 | |
| ETH | 0.05% | $0.025638 | 5,609.7825 | $143.82 | |
| ETH | 0.05% | $0.165376 | 841.8286 | $139.22 | |
| ETH | 0.01% | $2,899.48 | 0.0139 | $40.21 | |
| ETH | 0.01% | $0.16531 | 186.8382 | $30.89 | |
| ETH | <0.01% | $0.998987 | 8.4149 | $8.41 | |
| ETH | <0.01% | $0.002287 | 1,960.7381 | $4.48 | |
| ETH | <0.01% | $0.999003 | 1.7013 | $1.7 | |
| ETH | <0.01% | $0.014107 | 31.0067 | $0.4374 | |
| ETH | <0.01% | $0.009797 | 32.7939 | $0.3212 | |
| ETH | <0.01% | $0.049237 | 3.8843 | $0.1912 | |
| BASE | 19.84% | $1.24 | 43,077.0086 | $53,415.49 | |
| BASE | 1.61% | $0.125392 | 34,628.2515 | $4,342.11 | |
| BASE | 1.31% | $0.00609 | 577,879.0164 | $3,518.99 | |
| BASE | 0.90% | $2,895.82 | 0.8333 | $2,412.96 | |
| BASE | 0.40% | $1.8 | 596.4325 | $1,073.58 | |
| BASE | 0.37% | $0.999607 | 999.9788 | $999.59 | |
| BASE | 0.17% | $0.076489 | 6,019.2863 | $460.41 | |
| BASE | 0.03% | $0.011382 | 6,972.1848 | $79.36 | |
| BASE | <0.01% | $0.058112 | 206.7771 | $12.02 | |
| BASE | <0.01% | $0.000554 | 11,826.9189 | $6.55 | |
| BASE | <0.01% | $0.019895 | 320 | $6.37 | |
| BASE | <0.01% | $0.593127 | 8.5403 | $5.07 | |
| BASE | <0.01% | $0.00 | 4.1602 | $0.00 | |
| BASE | <0.01% | $1.18 | 2.2557 | $2.66 | |
| BASE | <0.01% | $0.000065 | 13,309.465 | $0.864 | |
| BASE | <0.01% | $0.000001 | 740,000 | $0.851 | |
| BASE | <0.01% | $0.00 | 149.1099 | $0.00 | |
| ARB | 9.85% | $0.998504 | 26,559.8147 | $26,520.08 | |
| ARB | 5.20% | $2,894.9 | 4.8403 | $14,012.2 | |
| ARB | 0.76% | $87,528 | 0.0235 | $2,057.94 | |
| ARB | 0.53% | $0.170709 | 8,326.4801 | $1,421.41 | |
| ARB | 0.33% | $3,549.82 | 0.2493 | $884.8 | |
| ARB | 0.14% | $0.999032 | 387.6865 | $387.31 | |
| ARB | 0.03% | $3,252.42 | 0.0274 | $89.03 | |
| ARB | 0.02% | $0.992384 | 63.3803 | $62.9 | |
| ARB | 0.01% | $3,354.08 | 0.00911321 | $30.57 | |
| ARB | <0.01% | $1.24 | 6.061 | $7.52 | |
| ARB | <0.01% | $0.076489 | 61.0505 | $4.67 | |
| OP | 0.76% | $0.295281 | 6,974.2944 | $2,059.37 | |
| OP | 0.49% | $2,898.38 | 0.4594 | $1,331.39 | |
| OP | 0.19% | $0.076906 | 6,558.7897 | $504.41 | |
| OP | <0.01% | $0.999564 | 1.5817 | $1.58 | |
| OP | <0.01% | $0.999564 | 0.1355 | $0.1354 | |
| BLAST | 0.34% | $2,895.82 | 0.3149 | $911.84 | |
| AVAX | 0.18% | $11.65 | 41.92 | $488.16 | |
| POL | 0.02% | $0.121891 | 371.9352 | $45.34 | |
| POL | <0.01% | $23.31 | 0.8166 | $19.04 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.