Source Code
Latest 25 from a total of 6,030 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Claim | 24319586 | 9 mins ago | IN | 0 ETH | 0.00001135 | ||||
| Claim With Callb... | 24319329 | 1 hr ago | IN | 0 ETH | 0.0003182 | ||||
| Claim With Callb... | 24318660 | 3 hrs ago | IN | 0 ETH | 0.00001011 | ||||
| Claim | 24317952 | 5 hrs ago | IN | 0 ETH | 0.00000295 | ||||
| Claim With Callb... | 24317365 | 7 hrs ago | IN | 0 ETH | 0.00000735 | ||||
| Claim With Callb... | 24316229 | 11 hrs ago | IN | 0 ETH | 0.0003752 | ||||
| Claim | 24316141 | 11 hrs ago | IN | 0 ETH | 0.0000032 | ||||
| Claim | 24315724 | 13 hrs ago | IN | 0 ETH | 0.00000549 | ||||
| Claim With Callb... | 24314429 | 17 hrs ago | IN | 0 ETH | 0.00002729 | ||||
| Claim | 24314025 | 18 hrs ago | IN | 0 ETH | 0.00015225 | ||||
| Claim With Callb... | 24312635 | 23 hrs ago | IN | 0 ETH | 0.00001035 | ||||
| Claim With Callb... | 24311495 | 27 hrs ago | IN | 0 ETH | 0.0000068 | ||||
| Claim | 24310611 | 30 hrs ago | IN | 0 ETH | 0.0001389 | ||||
| Claim | 24308708 | 36 hrs ago | IN | 0 ETH | 0.00000212 | ||||
| Claim | 24308425 | 37 hrs ago | IN | 0 ETH | 0.00000244 | ||||
| Claim | 24307969 | 39 hrs ago | IN | 0 ETH | 0.00000247 | ||||
| Claim With Callb... | 24307809 | 39 hrs ago | IN | 0 ETH | 0.00000434 | ||||
| Redeem | 24307804 | 39 hrs ago | IN | 0 ETH | 0.00000186 | ||||
| Claim | 24307794 | 39 hrs ago | IN | 0 ETH | 0.00000176 | ||||
| Claim With Callb... | 24306587 | 43 hrs ago | IN | 0 ETH | 0.000272 | ||||
| Claim | 24303190 | 2 days ago | IN | 0 ETH | 0.00010387 | ||||
| Claim | 24302103 | 2 days ago | IN | 0 ETH | 0.00000472 | ||||
| Claim | 24302079 | 2 days ago | IN | 0 ETH | 0.00000518 | ||||
| Claim | 24300772 | 2 days ago | IN | 0 ETH | 0.00000329 | ||||
| Claim | 24299635 | 2 days ago | IN | 0 ETH | 0.00014525 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x61018080 | 22034863 | 319 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
VestManager
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import { VestManagerBase } from "./VestManagerBase.sol";
interface IGovToken is IERC20 {
function INITIAL_SUPPLY() external view returns (uint256);
}
contract VestManager is VestManagerBase {
uint256 constant PRECISION = 1e18;
address immutable public prisma;
address immutable public yprisma;
address immutable public cvxprisma;
uint256 public immutable INITIAL_SUPPLY;
address public immutable BURN_ADDRESS;
bool public initialized;
uint256 public redemptionRatio;
mapping(AllocationType => uint256) public allocationByType;
mapping(AllocationType => uint256) public durationByType;
mapping(AllocationType => bytes32) public merkleRootByType;
mapping(address account => mapping(AllocationType => bool hasClaimed)) public hasClaimed; // used for airdrops only
enum AllocationType {
PERMA_STAKE,
LICENSING,
TREASURY,
REDEMPTIONS,
AIRDROP_TEAM,
AIRDROP_VICTIMS,
AIRDROP_LOCK_PENALTY
}
event TokenRedeemed(address indexed token, address indexed redeemer, address indexed recipient, uint256 amount);
event MerkleRootSet(AllocationType indexed allocationType, bytes32 root);
event AirdropClaimed(AllocationType indexed allocationType, address indexed account, address indexed recipient, uint256 amount);
event InitializationParamsSet();
constructor(
address _core,
address _token,
address _burnAddress,
address[3] memory _redemptionTokens // PRISMA, yPRISMA, cvxPRISMA
) VestManagerBase(_core, _token) {
INITIAL_SUPPLY = IGovToken(_token).INITIAL_SUPPLY();
require(IERC20(_token).balanceOf(address(this)) == INITIAL_SUPPLY, "VestManager not funded");
BURN_ADDRESS = _burnAddress;
prisma = _redemptionTokens[0];
yprisma = _redemptionTokens[1];
cvxprisma = _redemptionTokens[2];
}
/**
@notice Set the initialization parameters for the vesting contract
@dev All values must be set in the same order as the AllocationType enum
@param _maxRedeemable Maximum amount of PRISMA/yPRISMA/cvxPRISMA that can be redeemed
@param _merkleRoots Merkle roots for the airdrop allocations
@param _nonUserTargets Addresses to receive the non-user allocations
@param _vestDurations Durations of the vesting periods for each type
@param _allocPercentages Percentages of the initial supply allocated to each type,
the first two values being perma-stakers, followed by all other allocation types in order of
AllocationType enum.
*/
function setInitializationParams(
uint256 _maxRedeemable,
bytes32[3] memory _merkleRoots,
address[4] memory _nonUserTargets,
uint256[8] memory _vestDurations,
uint256[8] memory _allocPercentages
) external onlyOwner {
require(!initialized, "params already set");
initialized = true;
uint256 totalPctAllocated;
uint256 airdropIndex;
require(_vestDurations[0] == _vestDurations[1], "perma-staker durations must match");
for (uint256 i = 0; i < _allocPercentages.length; i++) {
AllocationType allocType = i == 0 ? AllocationType(i) : AllocationType(i-1); // First two are same type
require(_vestDurations[i] > 0 && _vestDurations[i] <= type(uint32).max, "invalid duration");
durationByType[allocType] = uint32(_vestDurations[i]);
totalPctAllocated += _allocPercentages[i];
uint256 allocation = _allocPercentages[i] * INITIAL_SUPPLY / PRECISION;
allocationByType[allocType] += allocation;
if (i < _nonUserTargets.length) {
_createVest(
_nonUserTargets[i],
uint32(_vestDurations[i]),
uint112(allocation)
);
continue;
}
if (
allocType == AllocationType.AIRDROP_TEAM ||
allocType == AllocationType.AIRDROP_VICTIMS ||
allocType == AllocationType.AIRDROP_LOCK_PENALTY
) {
// Set merkle roots for airdrop allocations
merkleRootByType[allocType] = _merkleRoots[airdropIndex];
emit MerkleRootSet(allocType, _merkleRoots[airdropIndex++]);
}
}
// Set the redemption ratio to be used for all PRISMA/yPRISMA/cvxPRISMA redemptions
uint256 _redemptionRatio = (
allocationByType[AllocationType.REDEMPTIONS] * 1e18 / _maxRedeemable
);
redemptionRatio = _redemptionRatio;
require(_redemptionRatio != 0, "ratio is 0");
require(totalPctAllocated == PRECISION, "Total not 100%");
emit InitializationParamsSet();
}
/**
@notice Set the merkle root for the lock penalty airdrop
@dev This root must be set later after lock penalty data is finalized
@param _root Merkle root for the lock penalty airdrop
@param _allocation Allocation for the lock penalty airdrop
*/
function setLockPenaltyMerkleRoot(bytes32 _root, uint256 _allocation) external onlyOwner {
require(initialized, "init params not set");
require(merkleRootByType[AllocationType.AIRDROP_LOCK_PENALTY] == bytes32(0), "root already set");
merkleRootByType[AllocationType.AIRDROP_LOCK_PENALTY] = _root;
emit MerkleRootSet(AllocationType.AIRDROP_LOCK_PENALTY, _root);
allocationByType[AllocationType.AIRDROP_LOCK_PENALTY] = _allocation;
}
function merkleClaim(
address _account,
address _recipient,
uint256 _amount,
AllocationType _type,
bytes32[] calldata _proof,
uint256 _index
) external callerOrDelegated(_account) {
require(
_type == AllocationType.AIRDROP_TEAM ||
_type == AllocationType.AIRDROP_LOCK_PENALTY ||
_type == AllocationType.AIRDROP_VICTIMS,
"invalid type"
);
bytes32 _root = merkleRootByType[_type];
require(_root != bytes32(0), "root not set");
require(!hasClaimed[_account][_type], "already claimed");
bytes32 node = keccak256(abi.encodePacked(_account, _index, _amount));
require(MerkleProof.verifyCalldata(
_proof,
_root,
node
), "invalid proof");
_createVest(
_recipient,
uint32(durationByType[_type]),
uint112(_amount)
);
hasClaimed[_account][_type] = true;
emit AirdropClaimed(_type, _account, _recipient, _amount);
}
/**
@notice Redeem PRISMA tokens for RSUP tokens
@param _token Token to redeem (PRISMA, yPRISMA or cvxPRISMA)
@param _recipient Address to receive the RSUP tokens
@param _amount Amount of tokens to redeem
@dev This function allows users to convert their PRISMA tokens to RSUP tokens
at the redemption ratio. The input tokens are burned in the process.
*/
function redeem(address _token, address _recipient, uint256 _amount) external {
require(
_token == address(prisma) ||
_token == address(yprisma) ||
_token == address(cvxprisma),
"invalid token"
);
require(_amount > 0, "amount too low");
uint256 _ratio = redemptionRatio;
require(_ratio != 0, "ratio not set");
IERC20(_token).transferFrom(msg.sender, BURN_ADDRESS, _amount);
_createVest(
_recipient,
uint32(durationByType[AllocationType.REDEMPTIONS]),
uint112(_amount * _ratio / 1e18)
);
emit TokenRedeemed(_token, msg.sender, _recipient, _amount);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.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.1.0) (utils/cryptography/MerkleProof.sol)
// This file was procedurally generated from scripts/generate/templates/MerkleProof.js.
pragma solidity ^0.8.20;
import {Hashes} from "./Hashes.sol";
/**
* @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.
*
* IMPORTANT: Consider memory side-effects when using custom hashing functions
* that access memory in an unsafe way.
*
* NOTE: This library supports proof verification for merkle trees built using
* custom _commutative_ hashing functions (i.e. `H(a, b) == H(b, a)`). Proving
* leaf inclusion in trees built using non-commutative hashing functions requires
* additional logic that is not supported by this library.
*/
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.
*
* This version handles proofs in memory with the default hashing function.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProof(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 leaves & pre-images are assumed to be sorted.
*
* This version handles proofs in memory with the default hashing function.
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);
}
return computedHash;
}
/**
* @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.
*
* This version handles proofs in memory with a custom hashing function.
*/
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bool) {
return processProof(proof, leaf, hasher) == 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 leaves & pre-images are assumed to be sorted.
*
* This version handles proofs in memory with a custom hashing function.
*/
function processProof(
bytes32[] memory proof,
bytes32 leaf,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = hasher(computedHash, proof[i]);
}
return computedHash;
}
/**
* @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.
*
* This version handles proofs in calldata with the default hashing function.
*/
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 leaves & pre-images are assumed to be sorted.
*
* This version handles proofs in calldata with the default hashing function.
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = Hashes.commutativeKeccak256(computedHash, proof[i]);
}
return computedHash;
}
/**
* @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.
*
* This version handles proofs in calldata with a custom hashing function.
*/
function verifyCalldata(
bytes32[] calldata proof,
bytes32 root,
bytes32 leaf,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bool) {
return processProofCalldata(proof, leaf, hasher) == 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 leaves & pre-images are assumed to be sorted.
*
* This version handles proofs in calldata with a custom hashing function.
*/
function processProofCalldata(
bytes32[] calldata proof,
bytes32 leaf,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = hasher(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}.
*
* This version handles multiproofs in memory with the default hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*
* NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
* The `leaves` must be validated independently. See {processMultiProof}.
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(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.
*
* This version handles multiproofs in memory with the default hashing function.
*
* 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).
*
* NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
* and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
* validating the leaves elsewhere.
*/
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 proofFlagsLen = proofFlags.length;
// Check proof validity.
if (leavesLen + proof.length != proofFlagsLen + 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[](proofFlagsLen);
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 < proofFlagsLen; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = Hashes.commutativeKeccak256(a, b);
}
if (proofFlagsLen > 0) {
if (proofPos != proof.length) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[proofFlagsLen - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @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}.
*
* This version handles multiproofs in memory with a custom hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*
* NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
* The `leaves` must be validated independently. See {processMultiProof}.
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bool) {
return processMultiProof(proof, proofFlags, leaves, hasher) == 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.
*
* This version handles multiproofs in memory with a custom hashing function.
*
* 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).
*
* NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
* and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
* validating the leaves elsewhere.
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view 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 proofFlagsLen = proofFlags.length;
// Check proof validity.
if (leavesLen + proof.length != proofFlagsLen + 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[](proofFlagsLen);
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 < proofFlagsLen; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = hasher(a, b);
}
if (proofFlagsLen > 0) {
if (proofPos != proof.length) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[proofFlagsLen - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @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}.
*
* This version handles multiproofs in calldata with the default hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*
* NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
* The `leaves` must be validated independently. See {processMultiProofCalldata}.
*/
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.
*
* This version handles multiproofs in calldata with the default hashing function.
*
* 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).
*
* NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
* and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
* validating the leaves elsewhere.
*/
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 proofFlagsLen = proofFlags.length;
// Check proof validity.
if (leavesLen + proof.length != proofFlagsLen + 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[](proofFlagsLen);
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 < proofFlagsLen; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = Hashes.commutativeKeccak256(a, b);
}
if (proofFlagsLen > 0) {
if (proofPos != proof.length) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[proofFlagsLen - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @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}.
*
* This version handles multiproofs in calldata with a custom hashing function.
*
* CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
*
* NOTE: Consider the case where `root == proof[0] && leaves.length == 0` as it will return `true`.
* The `leaves` must be validated independently. See {processMultiProofCalldata}.
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves, hasher) == 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.
*
* This version handles multiproofs in calldata with a custom hashing function.
*
* 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).
*
* NOTE: The _empty set_ (i.e. the case where `proof.length == 1 && leaves.length == 0`) is considered a no-op,
* and therefore a valid multiproof (i.e. it returns `proof[0]`). Consider disallowing this case if you're not
* validating the leaves elsewhere.
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves,
function(bytes32, bytes32) view returns (bytes32) hasher
) internal view 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 proofFlagsLen = proofFlags.length;
// Check proof validity.
if (leavesLen + proof.length != proofFlagsLen + 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[](proofFlagsLen);
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 < proofFlagsLen; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i]
? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
: proof[proofPos++];
hashes[i] = hasher(a, b);
}
if (proofFlagsLen > 0) {
if (proofPos != proof.length) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[proofFlagsLen - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { DelegatedOps } from '../../dependencies/DelegatedOps.sol';
import { CoreOwnable } from '../../dependencies/CoreOwnable.sol';
import { IVestClaimCallback } from 'src/interfaces/IVestClaimCallback.sol';
contract VestManagerBase is CoreOwnable, DelegatedOps {
uint256 public immutable VEST_GLOBAL_START_TIME;
IERC20 public immutable token;
mapping(address => Vest[]) public userVests;
mapping(address => ClaimSettings) public claimSettings;
struct Vest {
uint32 duration; // max of ~56k days
uint112 amount;
uint112 claimed;
}
struct ClaimSettings {
bool allowPermissionlessClaims;
address recipient;
}
event VestCreated(address indexed account, uint256 indexed duration, uint256 amount);
event Claimed(address indexed account, uint256 amount);
event ClaimSettingsSet(address indexed account, bool indexed allowPermissionlessClaims, address indexed recipient);
constructor(address _core, address _token) CoreOwnable(_core) {
token = IERC20(_token);
VEST_GLOBAL_START_TIME = block.timestamp;
}
/// @notice Creates or adds to a vesting instance for an account
/// @param _account The address to create the vest for
/// @param _duration The duration of the vesting period in seconds
/// @param _amount The amount of tokens to vest
/// @return The total number of vesting instances for the account
function _createVest(
address _account,
uint32 _duration,
uint112 _amount
) internal returns (uint256) {
require(_account != address(0), "zero address");
require(_amount > 0, "Amount must be greater than zero");
uint256 length = numAccountVests(_account);
// If a vest with matching duration already exists, simply add to its amount
for (uint256 i = 0; i < length; i++) {
if (userVests[_account][i].duration == _duration) {
userVests[_account][i].amount += _amount;
return length;
}
}
// If the duration does not exist, create a new vest
userVests[_account].push(Vest(
_duration,
_amount,
0
));
emit VestCreated(_account, _duration, _amount);
return length + 1;
}
function numAccountVests(address _account) public view returns (uint256) {
return userVests[_account].length;
}
/**
* @notice Claims all available vested tokens for an account
* @param _account Address to claim tokens for
* @return _claimed Total amount of tokens claimed
* @dev Any caller can claim on behalf of an account, unless explicitly blocked via account's claimSettings
*/
function claim(address _account) external returns (uint256 _claimed) {
address recipient = _enforceClaimSettings(_account);
_claimed = _claim(_account);
if (_claimed > 0) {
token.transfer(recipient, _claimed);
emit Claimed(_account, _claimed);
}
}
/**
* @notice Claims all available vested tokens for an account, and calls a callback to handle the tokens
* @dev Important: the claimed tokens are transferred to the callback contract for handling, not the recipient
* @dev Restricted to the account or a delegated caller
* @param _account Address to claim tokens for
* @param _callback Address of the callback contract to use
* @return _claimed Total amount of tokens claimed
*/
function claimWithCallback(
address _account,
address _callback
) external callerOrDelegated(_account) returns (uint256 _claimed) {
address recipient = _enforceClaimSettings(_account);
_claimed = _claim(_account);
if (_claimed > 0) {
token.transfer(_callback, _claimed);
require(IVestClaimCallback(_callback).onClaim(_account, recipient, _claimed), "callback failed");
emit Claimed(_account, _claimed);
}
}
function _claim(address _account) internal returns (uint256 _claimed) {
Vest[] storage vests = userVests[_account];
uint256 length = vests.length;
require(length > 0, "No vests to claim");
for (uint256 i = 0; i < length; i++) {
uint112 claimable = _claimableAmount(vests[i]);
if (claimable > 0) {
vests[i].claimed += claimable;
_claimed += claimable;
}
}
}
function _enforceClaimSettings(address _account) internal view returns (address) {
ClaimSettings memory settings = claimSettings[_account];
if (!settings.allowPermissionlessClaims) {
require(msg.sender == _account, "!authorized");
}
return settings.recipient != address(0) ? settings.recipient : _account;
}
/**
* @notice Get aggregated vesting data for an account. Includes all vests for the account.
* @param _account Address of the account to query
* @return _totalAmount Total amount of tokens in all vests for the account
* @return _totalClaimable Amount of tokens that can be claimed by the account
* @return _totalClaimed Amount of tokens already claimed by the account
* @dev Iterates through all vests for the account to calculate totals
*/
function getAggregateVestData(address _account) external view returns (
uint256 _totalAmount,
uint256 _totalClaimable,
uint256 _totalClaimed
) {
uint256 length = numAccountVests(_account);
for (uint256 i = 0; i < length; i++) {
(uint256 _total, uint256 _claimable, uint256 _claimed,) = _vestData(userVests[_account][i]);
_totalAmount += _total;
_totalClaimable += _claimable;
_totalClaimed += _claimed;
}
}
/**
* @notice Get single vest data for an account
* @param _account Address of the account to query
* @param index Index of the vest to query
* @return _total Total amount of tokens in the vest
* @return _claimable Amount of tokens that can be claimed for the vest
* @return _claimed Amount of tokens already claimed for the vest
* @return _timeRemaining Time remaining until vesting is complete
*/
function getSingleVestData(address _account, uint256 index) external view returns (
uint256 _total,
uint256 _claimable,
uint256 _claimed,
uint256 _timeRemaining
) {
return _vestData(userVests[_account][index]);
}
function _vestData(Vest memory vest) internal view returns (
uint256 _total,
uint256 _claimable,
uint256 _claimed,
uint256 _timeRemaining
){
uint256 vested = _vestedAmount(vest);
_total = vest.amount;
_claimable = vested - vest.claimed;
_claimed = vest.claimed;
uint256 elapsed = block.timestamp - VEST_GLOBAL_START_TIME;
_timeRemaining = elapsed > vest.duration ? 0 : vest.duration - elapsed;
}
function _claimableAmount(Vest storage vest) internal view returns (uint112) {
return uint112(_vestedAmount(vest) - vest.claimed);
}
function _vestedAmount(Vest memory vest) internal view returns (uint256) {
if (block.timestamp < VEST_GLOBAL_START_TIME) {
return 0;
} else if (block.timestamp >= VEST_GLOBAL_START_TIME + vest.duration) {
return vest.amount;
} else {
return (vest.amount * (block.timestamp - VEST_GLOBAL_START_TIME)) / vest.duration;
}
}
function setClaimSettings(
bool _allowPermissionlessClaims,
address _recipient
) external {
claimSettings[msg.sender] = ClaimSettings(_allowPermissionlessClaims, _recipient);
emit ClaimSettingsSet(msg.sender, _allowPermissionlessClaims, _recipient);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/Hashes.sol)
pragma solidity ^0.8.20;
/**
* @dev Library of standard hash functions.
*
* _Available since v5.1._
*/
library Hashes {
/**
* @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs.
*
* NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
*/
function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) {
return a < b ? _efficientKeccak256(a, b) : _efficientKeccak256(b, a);
}
/**
* @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
*/
function _efficientKeccak256(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
assembly ("memory-safe") {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
/**
@title Delegated Operations
@author Prisma Finance (with edits by Resupply Finance)
@notice Allows delegation to specific contract functionality. Useful for creating
wrapper contracts to bundle multiple interactions into a single call.
*/
contract DelegatedOps {
event DelegateApprovalSet(address indexed account, address indexed delegate, bool isApproved);
mapping(address owner => mapping(address caller => bool isApproved)) public isApprovedDelegate;
modifier callerOrDelegated(address _account) {
require(msg.sender == _account || isApprovedDelegate[_account][msg.sender], "!CallerOrDelegated");
_;
}
function setDelegateApproval(address _delegate, bool _isApproved) external {
isApprovedDelegate[msg.sender][_delegate] = _isApproved;
emit DelegateApprovalSet(msg.sender, _delegate, _isApproved);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {ICore} from "../interfaces/ICore.sol";
/**
@title Core Ownable
@author Prisma Finance (with edits by Resupply Finance)
@notice Contracts inheriting `CoreOwnable` have the same owner as `Core`.
The ownership cannot be independently modified or renounced.
*/
contract CoreOwnable {
ICore public immutable core;
constructor(address _core) {
core = ICore(_core);
}
modifier onlyOwner() {
require(msg.sender == address(core), "!core");
_;
}
function owner() public view returns (address) {
return address(core);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { IGovStaker } from "./IGovStaker.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IVestClaimCallback {
event RecoveredERC20(address indexed token, address indexed recipient, uint256 amount);
function govStaker() external view returns (IGovStaker);
function vestManager() external view returns (address);
function token() external view returns (IERC20);
function onClaim(
address account,
address recipient,
uint256 amount
) external returns (bool success);
function recoverERC20(address token, address recipient, uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { IAuthHook } from './IAuthHook.sol';
interface ICore {
struct OperatorAuth {
bool authorized;
IAuthHook hook;
}
event VoterSet(address indexed newVoter);
event OperatorExecuted(address indexed caller, address indexed target, bytes data);
event OperatorSet(address indexed caller, address indexed target, bool authorized, bytes4 selector, IAuthHook authHook);
function execute(address target, bytes calldata data) external returns (bytes memory);
function epochLength() external view returns (uint256);
function startTime() external view returns (uint256);
function voter() external view returns (address);
function ownershipTransferDeadline() external view returns (uint256);
function pendingOwner() external view returns (address);
function setOperatorPermissions(
address caller,
address target,
bytes4 selector,
bool authorized,
IAuthHook authHook
) external;
function setVoter(address newVoter) external;
function operatorPermissions(address caller, address target, bytes4 selector) external view returns (bool authorized, IAuthHook hook);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IGovStaker {
/* ========== EVENTS ========== */
event RewardAdded(address indexed rewardToken, uint256 amount);
event RewardTokenAdded(address indexed rewardsToken, address indexed rewardsDistributor, uint256 rewardsDuration);
event Recovered(address indexed token, uint256 amount);
event RewardsDurationUpdated(address indexed rewardsToken, uint256 duration);
event RewardPaid(address indexed user, address indexed rewardToken, uint256 reward);
event Staked(address indexed account, uint indexed epoch, uint amount);
event Unstaked(address indexed account, uint amount);
event Cooldown(address indexed account, uint amount, uint end);
event CooldownEpochsUpdated(uint24 newDuration);
/* ========== STRUCTS ========== */
struct Reward {
address rewardsDistributor;
uint256 rewardsDuration;
uint256 periodFinish;
uint256 rewardRate;
uint256 lastUpdateTime;
uint256 rewardPerTokenStored;
}
struct AccountData {
uint120 realizedStake; // Amount of stake that has fully realized weight.
uint120 pendingStake; // Amount of stake that has not yet fully realized weight.
uint16 lastUpdateEpoch;
}
struct UserCooldown {
uint104 end;
uint152 amount;
}
enum ApprovalStatus {
None, // 0. Default value, indicating no approval
StakeOnly, // 1. Approved for stake only
UnstakeOnly, // 2. Approved for unstake only
StakeAndUnstake // 3. Approved for both stake and unstake
}
/* ========== STATE VARIABLES ========== */
function rewardTokens(uint256 index) external view returns (address);
function rewardData(address token) external view returns (Reward memory);
function rewards(address account, address token) external view returns (uint256);
function userRewardPerTokenPaid(address account, address token) external view returns (uint256);
function CORE() external view returns (address);
function PRECISION() external view returns (uint256);
function ESCROW() external view returns (address);
function MAX_COOLDOWN_DURATION() external view returns (uint24);
function totalPending() external view returns (uint120);
function totalLastUpdateEpoch() external view returns (uint16);
function cooldownEpochs() external view returns (uint256);
function decimals() external view returns (uint8);
function approvedCaller(address account, address caller) external view returns (ApprovalStatus);
/* ========== EXTERNAL FUNCTIONS ========== */
function accountData(address account) external view returns (AccountData memory);
function stakeToken() external view returns (address);
function balanceOf(address account) external view returns (uint256);
function totalSupply() external view returns (uint256);
function getReward() external;
function getOneReward(address rewardsToken) external;
function addReward(address rewardsToken, address rewardsDistributor, uint256 rewardsDuration) external;
function notifyRewardAmount(address rewardsToken, uint256 rewardAmount) external;
function setRewardsDistributor(address rewardsToken, address rewardsDistributor) external;
function setRewardsDuration(address rewardsToken, uint256 rewardsDuration) external;
function recoverERC20(address tokenAddress, uint256 tokenAmount) external;
function stake(address account, uint amount) external returns (uint);
function stakeFor(address account, uint amount) external returns (uint);
function cooldown(address account, uint amount) external returns (uint);
function cooldowns(address account) external view returns (UserCooldown memory);
function cooldownFor(address account, uint amount) external returns (uint);
function exit(address account) external returns (uint);
function exitFor(address account) external returns (uint);
function unstake(address account, address receiver) external returns (uint);
function unstakeFor(address account, address receiver) external returns (uint);
function checkpointAccount(address account) external returns (AccountData memory, uint weight);
function checkpointAccountWithLimit(address account, uint epoch) external returns (AccountData memory, uint weight);
function checkpointTotal() external returns (uint);
function setApprovedCaller(address caller, ApprovalStatus status) external;
function setCooldownEpochs(uint24 epochs) external;
function getAccountWeight(address account) external view returns (uint);
function getAccountWeightAt(address account, uint epoch) external view returns (uint);
function getTotalWeight() external view returns (uint);
function getTotalWeightAt(uint epoch) external view returns (uint);
function getUnstakableAmount(address account) external view returns (uint);
function isCooldownEnabled() external view returns (bool);
function rewardTokensLength() external view returns (uint256);
function earned(address account, address rewardsToken) external view returns (uint256 pending);
function earnedMulti(address account) external view returns (uint256[] memory pending);
function rewardPerToken(address rewardsToken) external view returns (uint256 rewardAmount);
function lastTimeRewardApplicable(address rewardsToken) external view returns (uint256);
function getRewardForDuration(address rewardsToken) external view returns (uint256);
function owner() external view returns (address);
function guardian() external view returns (address);
function getEpoch() external view returns (uint);
function epochLength() external view returns (uint);
function startTime() external view returns (uint);
function irreversiblyCommitAccountAsPermanentStaker(address account) external;
function onPermaStakeMigrate(address account) external;
function migrateStake() external returns (uint amount);
function setDelegateApproval(address delegate, bool approved) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IAuthHook {
function preHook(address operator, address target, bytes calldata data) external returns (bool);
function postHook(bytes memory result, address operator, address target, bytes calldata data) external returns (bool);
}{
"remappings": [
"ds-test/=node_modules/ds-test/src/",
"forge-std/=node_modules/forge-std/src/",
"frax-std/=node_modules/frax-standard-solidity/src/",
"@axelar-network/=node_modules/@axelar-network/",
"@chainlink/=node_modules/@chainlink/",
"@eth-optimism/=node_modules/@eth-optimism/",
"@layerzerolabs/=node_modules/@layerzerolabs/",
"@mean-finance/=node_modules/@mean-finance/",
"@openzeppelin/=node_modules/@openzeppelin/",
"@rari-capital/=node_modules/@rari-capital/",
"@uniswap/=node_modules/@uniswap/",
"base64-sol/=node_modules/base64-sol/",
"frax-standard-solidity/=node_modules/frax-standard-solidity/",
"hardhat-deploy/=node_modules/hardhat-deploy/",
"hardhat/=node_modules/hardhat/",
"solidity-bytes-utils/=node_modules/solidity-bytes-utils/",
"solidity-stringutils/=lib/surl/lib/solidity-stringutils/",
"surl/=lib/surl/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": true,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_core","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_burnAddress","type":"address"},{"internalType":"address[3]","name":"_redemptionTokens","type":"address[3]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum VestManager.AllocationType","name":"allocationType","type":"uint8"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AirdropClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"allowPermissionlessClaims","type":"bool"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"ClaimSettingsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"bool","name":"isApproved","type":"bool"}],"name":"DelegateApprovalSet","type":"event"},{"anonymous":false,"inputs":[],"name":"InitializationParamsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum VestManager.AllocationType","name":"allocationType","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"MerkleRootSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"redeemer","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenRedeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VestCreated","type":"event"},{"inputs":[],"name":"BURN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VEST_GLOBAL_START_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum VestManager.AllocationType","name":"","type":"uint8"}],"name":"allocationByType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"claim","outputs":[{"internalType":"uint256","name":"_claimed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimSettings","outputs":[{"internalType":"bool","name":"allowPermissionlessClaims","type":"bool"},{"internalType":"address","name":"recipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_callback","type":"address"}],"name":"claimWithCallback","outputs":[{"internalType":"uint256","name":"_claimed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"core","outputs":[{"internalType":"contract ICore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cvxprisma","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum VestManager.AllocationType","name":"","type":"uint8"}],"name":"durationByType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getAggregateVestData","outputs":[{"internalType":"uint256","name":"_totalAmount","type":"uint256"},{"internalType":"uint256","name":"_totalClaimable","type":"uint256"},{"internalType":"uint256","name":"_totalClaimed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getSingleVestData","outputs":[{"internalType":"uint256","name":"_total","type":"uint256"},{"internalType":"uint256","name":"_claimable","type":"uint256"},{"internalType":"uint256","name":"_claimed","type":"uint256"},{"internalType":"uint256","name":"_timeRemaining","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"enum VestManager.AllocationType","name":"","type":"uint8"}],"name":"hasClaimed","outputs":[{"internalType":"bool","name":"hasClaimed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"caller","type":"address"}],"name":"isApprovedDelegate","outputs":[{"internalType":"bool","name":"isApproved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"enum VestManager.AllocationType","name":"_type","type":"uint8"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"merkleClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum VestManager.AllocationType","name":"","type":"uint8"}],"name":"merkleRootByType","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"numAccountVests","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prisma","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redemptionRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_allowPermissionlessClaims","type":"bool"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"setClaimSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"},{"internalType":"bool","name":"_isApproved","type":"bool"}],"name":"setDelegateApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxRedeemable","type":"uint256"},{"internalType":"bytes32[3]","name":"_merkleRoots","type":"bytes32[3]"},{"internalType":"address[4]","name":"_nonUserTargets","type":"address[4]"},{"internalType":"uint256[8]","name":"_vestDurations","type":"uint256[8]"},{"internalType":"uint256[8]","name":"_allocPercentages","type":"uint256[8]"}],"name":"setInitializationParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"uint256","name":"_allocation","type":"uint256"}],"name":"setLockPenaltyMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userVests","outputs":[{"internalType":"uint32","name":"duration","type":"uint32"},{"internalType":"uint112","name":"amount","type":"uint112"},{"internalType":"uint112","name":"claimed","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yprisma","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
610180806040523461024a57612176803803809161001d82856102c0565b8339810160c08282031261024a57610034826102e3565b610040602084016102e3565b9061004d604085016102e3565b9280607f8601121561024a5760405194606086016001600160401b038111878210176102ac57604052859060c0810192831161024a57606001905b828210610294575050506001600160a01b039081166080521660c08190524260a052604051630bfcba7760e21b8152602081600481855afa908115610256575f91610261575b50610140526040516370a0823160e01b815230600482015290602090829060249082905afa908115610256575f91610220575b5061014051036101db576101605280516001600160a01b0390811660e0526020820151811661010052604091820151166101205251611e7e90816102f882396080518181816101fc01528181610ad80152611237015260a0518181816109d801528181611da50152611de7015260c0518181816101b8015281816102c0015261110d015260e0518181816113d201526116680152610100518181816115e0015261162401526101205181818161106f01526115ae015261014051818181610b330152611037015261016051818181610170015261142b0152f35b60405162461bcd60e51b815260206004820152601660248201527f566573744d616e61676572206e6f742066756e646564000000000000000000006044820152606490fd5b90506020813d60201161024e575b8161023b602093836102c0565b8101031261024a57515f610101565b5f80fd5b3d915061022e565b6040513d5f823e3d90fd5b90506020813d60201161028c575b8161027c602093836102c0565b8101031261024a575160246100ce565b3d915061026f565b602080916102a1846102e3565b815201910190610088565b634e487b7160e01b5f52604160045260245ffd5b601f909101601f19168101906001600160401b038211908210176102ac57604052565b51906001600160a01b038216820361024a5756fe6080806040526004361015610012575f80fd5b5f3560e01c9081630449c4ab14611697575080630a3266b0146116535780630d4b95161461160f5780630e6dfcd51461139e578063158ef93e1461137c5780631633ec361461121d5780631930e825146111c757806319c21b0a1461119f5780631e83409a1461109e5780632abb7e661461105a5780632ff2e9dc1461102057806348f5eaf914610fac5780634b7b8ef714610f845780634e47d71414610f4c5780638156145d146109fb578063826160fc146109c157806384063c6c146109905780638da5cb5b146101e7578063a42a29a614610938578063c3c854b6146108a4578063c9ea23031461059f578063d338edf31461054e578063d698715514610501578063dc9b52b414610459578063de987d501461043c578063f10549f61461022b578063f2f4eb26146101e7578063fc0c546a146101a35763fccc28131461015b575f80fd5b3461019f575f36600319011261019f576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5f80fd5b3461019f575f36600319011261019f576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461019f575f36600319011261019f576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461019f57604036600319011261019f5761024461175e565b61024c611748565b6001600160a01b03821691338314801561041c575b61026a90611940565b61027381611bb8565b9061027d81611c5e565b928361028f575b602084604051908152f35b60405163a9059cbb60e01b81526001600160a01b03821660048201526024810185905290602082806044810103815f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af19384156103f6575f602094879461033b97610401575b50604051631005f04960e21b81526001600160a01b039182166004820152921660248301526044820193909352938492839182906064820190565b03926001600160a01b03165af19081156103f6575f916103c7575b5015610390576020917fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a83604051848152a2828080610284565b60405162461bcd60e51b815260206004820152600f60248201526e18d85b1b189858dac819985a5b1959608a1b6044820152606490fd5b6103e9915060203d6020116103ef575b6103e18183611830565b810190611852565b83610356565b503d6103d7565b6040513d5f823e3d90fd5b61041790873d89116103ef576103e18183611830565b610300565b505f8381526020818152604080832033845290915290205460ff16610261565b3461019f575f36600319011261019f576020600454604051908152f35b3461019f57602036600319011261019f5761047261175e565b5f5f5f9260018060a01b0316805f52600160205260405f20545f915b8183106104ac57606085878660405192835260208301526040820152f35b909192936104f76104eb6104f1600193855f52846020526104e16104dc6104d68a60405f206117cf565b5061190b565b611d64565b50949190926118ed565b986118ed565b976118ed565b959301919061048e565b3461019f57602036600319011261019f576001600160a01b0361052261175e565b165f5260026020526040805f205481519060ff81161515825260018060a01b039060081c166020820152f35b3461019f57604036600319011261019f5761056761175e565b602435600781101561019f5761059360ff9160209360018060a01b03165f526008845260405f206117b9565b54166040519015158152f35b3461019f5760c036600319011261019f576105b861175e565b6105c0611748565b60643590604435600783101561019f576084359167ffffffffffffffff831161019f573660238401121561019f5782600401359367ffffffffffffffff851161019f573660248660051b8601011161019f576001600160a01b038616913383148015610884575b61063090611940565b5f600483148015610878575b818115610868575b5015610834576106538361178b565b5497881561080057845f52600860205260ff6106728560405f206117b9565b54166107c95760405160208101916bffffffffffffffffffffffff199060601b16825260a4356034820152866054820152605481526106b2607482611830565b519020975f985b888a10156106fa5760248a60051b89010135908181105f146106e9575f52602052600160405f205b9901986106b9565b905f52602052600160405f206106e1565b036107945761072363ffffffff61071085611774565b54166001600160701b03871690846119a1565b50835f5260086020526107398360405f206117b9565b805460ff19166001179055610780576040519384526001600160a01b0316927f55230c7d73ba193bcb70f278e7f5657a2520e8112f3bed52e55ce7eb93982bcc90602090a4005b634e487b7160e01b5f52602160045260245ffd5b60405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b6044820152606490fd5b60405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818db185a5b5959608a1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600c60248201526b1c9bdbdd081b9bdd081cd95d60a21b6044820152606490fd5b60405162461bcd60e51b815260206004820152600c60248201526b696e76616c6964207479706560a01b6044820152606490fd5b9050610780576005831481610644565b50505f6006831461063c565b505f8381526020818152604080832033845290915290205460ff16610627565b3461019f57604036600319011261019f576108bd61175e565b602435908115159182810361019f576108fe90335f525f60205260405f2060018060a01b0384165f5260205260405f209060ff801983541691151516179055565b6040519182526001600160a01b03169033907f92d241afb0a1a9b3441bf1bd6bea0f9164cf5a2562cbe4bcc34ab943b246560890602090a3005b3461019f57604036600319011261019f576001600160a01b0361095961175e565b165f52600160205260806109786104dc6104d660243560405f206117cf565b91604051938452602084015260408301526060820152f35b3461019f57602036600319011261019f57600435600781101561019f576109b86020916117a2565b54604051908152f35b3461019f575f36600319011261019f5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461019f5761030036600319011261019f57366043121561019f57604051610a24606082611830565b803660841161019f576024905b60848210610f3c57823660a3121561019f5760405190610a52608083611830565b81366101041161019f576084905b6101048210610f1c57505036610123121561019f5760405191610100610a868185611830565b83366102041161019f57610104905b6102048210610f0c57505036610223121561019f57610ab76040519182611830565b80366103041161019f57610204905b6103048210610efc5750610b069050337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461189b565b60035460ff8116610ec25760019060ff1916176003555f935f908051602082015103610e73579392905f947f0000000000000000000000000000000000000000000000000000000000000000925b60088710610c52578760035f52600560205260405f2054670de0b6b3a7640000810290808204670de0b6b3a76400001490151715610c3e57610b99906004359061187d565b8060045515610c0c57670de0b6b3a764000003610bd6577fc4af3af2e2df2bca7e41e8da8c822b5e33dab57063450f96219db777481efabb5f80a1005b60405162461bcd60e51b815260206004820152600e60248201526d546f74616c206e6f74203130302560901b6044820152606490fd5b60405162461bcd60e51b815260206004820152600a6024820152690726174696f20697320360b41b6044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b9091929394959687155f14610e595760078810156107805787905b610c7789856118cf565b51151580610e41575b15610e0957610cb59063ffffffff610c988b876118cf565b5116610ca384611774565b55610cae8a896118cf565b51906118ed565b97670de0b6b3a7640000610cd387610ccd848b6118cf565b5161186a565b04610cdd836117a2565b610ce88282546118ed565b90556004821080610dad5750506007821015918261078057600481148015610da0575b838115610d90575b50610d2b575b50600191505b01959493929190610b54565b610d35868a6118fa565b51610d3f8261178b565b55855f198114610c3e576001610d579101968a6118fa565b5192610780577fc1e85192bb4dc49db867f1ac46b02d377f7e2bd38caacd2c19ff453935ebd4c06020600194604051908152a289610d19565b9050610780576006811483610d13565b505f925060058114610d0b565b90925015610df557600581901b830151600192610def916001600160a01b0316906001600160701b0363ffffffff610de5868a6118cf565b51169116916119a1565b50610d1f565b634e487b7160e01b5f52603260045260245ffd5b60405162461bcd60e51b815260206004820152601060248201526f34b73b30b634b210323ab930ba34b7b760811b6044820152606490fd5b5063ffffffff610e518a866118cf565b511115610c80565b5f198801888111610c3e5760078110156107805790610c6d565b60405162461bcd60e51b815260206004820152602160248201527f7065726d612d7374616b6572206475726174696f6e73206d757374206d6174636044820152600d60fb1b6064820152608490fd5b60405162461bcd60e51b81526020600482015260126024820152711c185c985b5cc8185b1c9958591e481cd95d60721b6044820152606490fd5b8135815260209182019101610ac6565b8135815260209182019101610a95565b81356001600160a01b038116810361019f57815260209182019101610a60565b8135815260209182019101610a31565b3461019f57602036600319011261019f576001600160a01b03610f6d61175e565b165f526001602052602060405f2054604051908152f35b3461019f57602036600319011261019f57600435600781101561019f576109b860209161178b565b3461019f57604036600319011261019f57610fc561175e565b6001600160a01b03165f9081526001602052604090208054602435919082101561019f57606091610ff5916117cf565b50546040519063ffffffff811682526001600160701b038160201c16602083015260901c6040820152f35b3461019f575f36600319011261019f5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461019f575f36600319011261019f576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461019f57602036600319011261019f576110b761175e565b6110c081611bb8565b906110ca81611c5e565b90816110dc575b602082604051908152f35b60405163a9059cbb60e01b81526001600160a01b03909316600484015260248301829052602083806044810103815f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af19283156103f657602093611184575b506040518281526001600160a01b03909116907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a908490a2826110d1565b61119a90843d86116103ef576103e18183611830565b611146565b3461019f57602036600319011261019f57600435600781101561019f576109b8602091611774565b3461019f57604036600319011261019f576111e061175e565b6111e8611748565b9060018060a01b03165f525f60205260405f209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b3461019f57604036600319011261019f57600435611265337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461189b565b60ff60035416156113415760065f5260076020527f55c5b153ab560fcde54a63b18c7f53d75501706907cef8767fbded79ab9997c754611309577fc1e85192bb4dc49db867f1ac46b02d377f7e2bd38caacd2c19ff453935ebd4c06020600692835f52600782528060405f2055604051908152a260065f5260056020526024357f069400f22b28c6c362558d92f66163cec5671cba50b61abd2eecfcd0eaeac51855005b60405162461bcd60e51b815260206004820152601060248201526f1c9bdbdd08185b1c9958591e481cd95d60821b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152721a5b9a5d081c185c985b5cc81b9bdd081cd95d606a1b6044820152606490fd5b3461019f575f36600319011261019f57602060ff600354166040519015158152f35b3461019f57606036600319011261019f576113b761175e565b6113bf611748565b6001600160a01b039182169160443591907f000000000000000000000000000000000000000000000000000000000000000016831480156115dd575b80156115ab575b1561157657811561154057600454801561150b576040516323b872dd60e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316602482015260448101849052906020826064815f895af19182156103f6576114b3926114ee575b5060035f5260066020526001600160701b03670de0b6b3a76400006114aa63ffffffff60405f205416938761186a565b041690836119a1565b506040519182526001600160a01b03169133917f0c139059c3dc33b2bf39a13d853d8f16f0ee4c6d4076eef665b063b44518e59490602090a4005b6115069060203d6020116103ef576103e18183611830565b61147a565b60405162461bcd60e51b815260206004820152600d60248201526c1c985d1a5bc81b9bdd081cd95d609a1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d616d6f756e7420746f6f206c6f7760901b6044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b2103a37b5b2b760991b6044820152606490fd5b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168314611402565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031683146113fb565b3461019f575f36600319011261019f576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461019f575f36600319011261019f576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461019f57604036600319011261019f5760043580151580910361019f576116bd611748565b916116c7816117e4565b818152602081019260018060a01b031692838152335f52600260205261170060405f2092511515839060ff801983541691151516179055565b518154610100600160a81b03191660089190911b610100600160a81b0316179055337fd600d35401e5ac794858fa031a56d9a11286fb0577b9d560b781b91b4984766c5f80a4005b602435906001600160a01b038216820361019f57565b600435906001600160a01b038216820361019f57565b6007811015610780575f52600660205260405f2090565b6007811015610780575f52600760205260405f2090565b6007811015610780575f52600560205260405f2090565b906007811015610780575f5260205260405f2090565b8054821015610df5575f5260205f2001905f90565b6040810190811067ffffffffffffffff82111761180057604052565b634e487b7160e01b5f52604160045260245ffd5b6060810190811067ffffffffffffffff82111761180057604052565b90601f8019910116810190811067ffffffffffffffff82111761180057604052565b9081602091031261019f5751801515810361019f5790565b81810292918115918404141715610c3e57565b8115611887570490565b634e487b7160e01b5f52601260045260245ffd5b156118a257565b60405162461bcd60e51b815260206004820152600560248201526421636f726560d81b6044820152606490fd5b906008811015610df55760051b0190565b91908203918211610c3e57565b91908201809211610c3e57565b906003811015610df55760051b0190565b9060405161191881611814565b604081935463ffffffff811683526001600160701b038160201c16602084015260901c910152565b1561194757565b60405162461bcd60e51b81526020600482015260126024820152710850d85b1b195c93dc91195b1959d85d195960721b6044820152606490fd5b906001600160701b03809116911601906001600160701b038211610c3e57565b6001600160a01b03168015611b84576001600160701b038316918215611b4057815f52600160205260405f2054935f5b858110611ab1575050815f52600160205260405f2063ffffffff604051926119f884611814565b16938483526020830181815260408401925f845280546801000000000000000081101561180057611a2e916001820181556117cf565b611a9e5793519051925160901b6001600160901b031916640100000000600160901b03602094851b1663ffffffff90921691909117179092557f941051f5740326e2299731cca609f60c53e8302c775962e529bb902465620ddc91604051908152a360018101809111610c3e5790565b634e487b7160e01b5f525f60045260245ffd5b835f52600160205263ffffffff611acb8260405f206117cf565b50541663ffffffff841614611ae2576001016119d1565b611b3d9450611b169250611b0191935f52600160205260405f206117cf565b50916001600160701b03835460201c16611981565b640100000000600160901b0382549160201b1690640100000000600160901b031916179055565b90565b606460405162461bcd60e51b815260206004820152602060248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152fd5b60405162461bcd60e51b815260206004820152600c60248201526b7a65726f206164647265737360a01b6044820152606490fd5b6001600160a01b0381165f818152600260205260409081902090519190611bde836117e4565b5460ff8116158015845260089190911c6001600160a01b03166020909301928352611c1f575b50516001600160a01b0316908115611c1a575090565b905090565b3303611c2b575f611c04565b60405162461bcd60e51b815260206004820152600b60248201526a08585d5d1a1bdc9a5e995960aa1b6044820152606490fd5b6001600160a01b03165f9081526001602052604081208054919291908115611d2b575f5b828110611c8e57505050565b6001600160701b03611cc0611ca383856117cf565b50611cb5611cb08261190b565b611de5565b905460901c906118e0565b1680611cd0575b50600101611c82565b611d24908296611d1f611ce5600195876117cf565b50611cf484825460901c611981565b815471ffffffffffffffffffffffffffffffffffff1660909190911b6001600160901b031916179055565b6118ed565b9490611cc7565b60405162461bcd60e51b81526020600482015260116024820152704e6f20766573747320746f20636c61696d60781b6044820152606490fd5b611d6d81611de5565b906001600160701b03602082015116926001600160701b03611d97604084019482865116906118e0565b9351169163ffffffff611dca7f0000000000000000000000000000000000000000000000000000000000000000426118e0565b9151169081811115611ddc5750505f90565b611b3d916118e0565b7f00000000000000000000000000000000000000000000000000000000000000008042105f14611e155750505f90565b611e2663ffffffff835116826118ed565b4210611e3d5750602001516001600160701b031690565b9063ffffffff611e68611b3d93611e626001600160701b0360208601511691426118e0565b9061186a565b9151169061187d56fea164736f6c634300081c000a000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d000000000000000000000000419905009e4656fdc02418c7df35b1e61ed5f726000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000da47862a83dac0c112ba89c6abc2159b95afd71c000000000000000000000000e3668873d944e4a949da05fc8bde419eff54388200000000000000000000000034635280737b5bfe6c7dc2fc3065d60d66e78185
Deployed Bytecode
0x6080806040526004361015610012575f80fd5b5f3560e01c9081630449c4ab14611697575080630a3266b0146116535780630d4b95161461160f5780630e6dfcd51461139e578063158ef93e1461137c5780631633ec361461121d5780631930e825146111c757806319c21b0a1461119f5780631e83409a1461109e5780632abb7e661461105a5780632ff2e9dc1461102057806348f5eaf914610fac5780634b7b8ef714610f845780634e47d71414610f4c5780638156145d146109fb578063826160fc146109c157806384063c6c146109905780638da5cb5b146101e7578063a42a29a614610938578063c3c854b6146108a4578063c9ea23031461059f578063d338edf31461054e578063d698715514610501578063dc9b52b414610459578063de987d501461043c578063f10549f61461022b578063f2f4eb26146101e7578063fc0c546a146101a35763fccc28131461015b575f80fd5b3461019f575f36600319011261019f576040517f000000000000000000000000000000000000000000000000000000000000dead6001600160a01b03168152602090f35b5f80fd5b3461019f575f36600319011261019f576040517f000000000000000000000000419905009e4656fdc02418c7df35b1e61ed5f7266001600160a01b03168152602090f35b3461019f575f36600319011261019f576040517f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b03168152602090f35b3461019f57604036600319011261019f5761024461175e565b61024c611748565b6001600160a01b03821691338314801561041c575b61026a90611940565b61027381611bb8565b9061027d81611c5e565b928361028f575b602084604051908152f35b60405163a9059cbb60e01b81526001600160a01b03821660048201526024810185905290602082806044810103815f7f000000000000000000000000419905009e4656fdc02418c7df35b1e61ed5f7266001600160a01b03165af19384156103f6575f602094879461033b97610401575b50604051631005f04960e21b81526001600160a01b039182166004820152921660248301526044820193909352938492839182906064820190565b03926001600160a01b03165af19081156103f6575f916103c7575b5015610390576020917fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a83604051848152a2828080610284565b60405162461bcd60e51b815260206004820152600f60248201526e18d85b1b189858dac819985a5b1959608a1b6044820152606490fd5b6103e9915060203d6020116103ef575b6103e18183611830565b810190611852565b83610356565b503d6103d7565b6040513d5f823e3d90fd5b61041790873d89116103ef576103e18183611830565b610300565b505f8381526020818152604080832033845290915290205460ff16610261565b3461019f575f36600319011261019f576020600454604051908152f35b3461019f57602036600319011261019f5761047261175e565b5f5f5f9260018060a01b0316805f52600160205260405f20545f915b8183106104ac57606085878660405192835260208301526040820152f35b909192936104f76104eb6104f1600193855f52846020526104e16104dc6104d68a60405f206117cf565b5061190b565b611d64565b50949190926118ed565b986118ed565b976118ed565b959301919061048e565b3461019f57602036600319011261019f576001600160a01b0361052261175e565b165f5260026020526040805f205481519060ff81161515825260018060a01b039060081c166020820152f35b3461019f57604036600319011261019f5761056761175e565b602435600781101561019f5761059360ff9160209360018060a01b03165f526008845260405f206117b9565b54166040519015158152f35b3461019f5760c036600319011261019f576105b861175e565b6105c0611748565b60643590604435600783101561019f576084359167ffffffffffffffff831161019f573660238401121561019f5782600401359367ffffffffffffffff851161019f573660248660051b8601011161019f576001600160a01b038616913383148015610884575b61063090611940565b5f600483148015610878575b818115610868575b5015610834576106538361178b565b5497881561080057845f52600860205260ff6106728560405f206117b9565b54166107c95760405160208101916bffffffffffffffffffffffff199060601b16825260a4356034820152866054820152605481526106b2607482611830565b519020975f985b888a10156106fa5760248a60051b89010135908181105f146106e9575f52602052600160405f205b9901986106b9565b905f52602052600160405f206106e1565b036107945761072363ffffffff61071085611774565b54166001600160701b03871690846119a1565b50835f5260086020526107398360405f206117b9565b805460ff19166001179055610780576040519384526001600160a01b0316927f55230c7d73ba193bcb70f278e7f5657a2520e8112f3bed52e55ce7eb93982bcc90602090a4005b634e487b7160e01b5f52602160045260245ffd5b60405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b6044820152606490fd5b60405162461bcd60e51b815260206004820152600f60248201526e185b1c9958591e4818db185a5b5959608a1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600c60248201526b1c9bdbdd081b9bdd081cd95d60a21b6044820152606490fd5b60405162461bcd60e51b815260206004820152600c60248201526b696e76616c6964207479706560a01b6044820152606490fd5b9050610780576005831481610644565b50505f6006831461063c565b505f8381526020818152604080832033845290915290205460ff16610627565b3461019f57604036600319011261019f576108bd61175e565b602435908115159182810361019f576108fe90335f525f60205260405f2060018060a01b0384165f5260205260405f209060ff801983541691151516179055565b6040519182526001600160a01b03169033907f92d241afb0a1a9b3441bf1bd6bea0f9164cf5a2562cbe4bcc34ab943b246560890602090a3005b3461019f57604036600319011261019f576001600160a01b0361095961175e565b165f52600160205260806109786104dc6104d660243560405f206117cf565b91604051938452602084015260408301526060820152f35b3461019f57602036600319011261019f57600435600781101561019f576109b86020916117a2565b54604051908152f35b3461019f575f36600319011261019f5760206040517f0000000000000000000000000000000000000000000000000000000067d23e0b8152f35b3461019f5761030036600319011261019f57366043121561019f57604051610a24606082611830565b803660841161019f576024905b60848210610f3c57823660a3121561019f5760405190610a52608083611830565b81366101041161019f576084905b6101048210610f1c57505036610123121561019f5760405191610100610a868185611830565b83366102041161019f57610104905b6102048210610f0c57505036610223121561019f57610ab76040519182611830565b80366103041161019f57610204905b6103048210610efc5750610b069050337f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b03161461189b565b60035460ff8116610ec25760019060ff1916176003555f935f908051602082015103610e73579392905f947f00000000000000000000000000000000000000000031a17e847807b1bc000000925b60088710610c52578760035f52600560205260405f2054670de0b6b3a7640000810290808204670de0b6b3a76400001490151715610c3e57610b99906004359061187d565b8060045515610c0c57670de0b6b3a764000003610bd6577fc4af3af2e2df2bca7e41e8da8c822b5e33dab57063450f96219db777481efabb5f80a1005b60405162461bcd60e51b815260206004820152600e60248201526d546f74616c206e6f74203130302560901b6044820152606490fd5b60405162461bcd60e51b815260206004820152600a6024820152690726174696f20697320360b41b6044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b9091929394959687155f14610e595760078810156107805787905b610c7789856118cf565b51151580610e41575b15610e0957610cb59063ffffffff610c988b876118cf565b5116610ca384611774565b55610cae8a896118cf565b51906118ed565b97670de0b6b3a7640000610cd387610ccd848b6118cf565b5161186a565b04610cdd836117a2565b610ce88282546118ed565b90556004821080610dad5750506007821015918261078057600481148015610da0575b838115610d90575b50610d2b575b50600191505b01959493929190610b54565b610d35868a6118fa565b51610d3f8261178b565b55855f198114610c3e576001610d579101968a6118fa565b5192610780577fc1e85192bb4dc49db867f1ac46b02d377f7e2bd38caacd2c19ff453935ebd4c06020600194604051908152a289610d19565b9050610780576006811483610d13565b505f925060058114610d0b565b90925015610df557600581901b830151600192610def916001600160a01b0316906001600160701b0363ffffffff610de5868a6118cf565b51169116916119a1565b50610d1f565b634e487b7160e01b5f52603260045260245ffd5b60405162461bcd60e51b815260206004820152601060248201526f34b73b30b634b210323ab930ba34b7b760811b6044820152606490fd5b5063ffffffff610e518a866118cf565b511115610c80565b5f198801888111610c3e5760078110156107805790610c6d565b60405162461bcd60e51b815260206004820152602160248201527f7065726d612d7374616b6572206475726174696f6e73206d757374206d6174636044820152600d60fb1b6064820152608490fd5b60405162461bcd60e51b81526020600482015260126024820152711c185c985b5cc8185b1c9958591e481cd95d60721b6044820152606490fd5b8135815260209182019101610ac6565b8135815260209182019101610a95565b81356001600160a01b038116810361019f57815260209182019101610a60565b8135815260209182019101610a31565b3461019f57602036600319011261019f576001600160a01b03610f6d61175e565b165f526001602052602060405f2054604051908152f35b3461019f57602036600319011261019f57600435600781101561019f576109b860209161178b565b3461019f57604036600319011261019f57610fc561175e565b6001600160a01b03165f9081526001602052604090208054602435919082101561019f57606091610ff5916117cf565b50546040519063ffffffff811682526001600160701b038160201c16602083015260901c6040820152f35b3461019f575f36600319011261019f5760206040517f00000000000000000000000000000000000000000031a17e847807b1bc0000008152f35b3461019f575f36600319011261019f576040517f00000000000000000000000034635280737b5bfe6c7dc2fc3065d60d66e781856001600160a01b03168152602090f35b3461019f57602036600319011261019f576110b761175e565b6110c081611bb8565b906110ca81611c5e565b90816110dc575b602082604051908152f35b60405163a9059cbb60e01b81526001600160a01b03909316600484015260248301829052602083806044810103815f7f000000000000000000000000419905009e4656fdc02418c7df35b1e61ed5f7266001600160a01b03165af19283156103f657602093611184575b506040518281526001600160a01b03909116907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a908490a2826110d1565b61119a90843d86116103ef576103e18183611830565b611146565b3461019f57602036600319011261019f57600435600781101561019f576109b8602091611774565b3461019f57604036600319011261019f576111e061175e565b6111e8611748565b9060018060a01b03165f525f60205260405f209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b3461019f57604036600319011261019f57600435611265337f000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d6001600160a01b03161461189b565b60ff60035416156113415760065f5260076020527f55c5b153ab560fcde54a63b18c7f53d75501706907cef8767fbded79ab9997c754611309577fc1e85192bb4dc49db867f1ac46b02d377f7e2bd38caacd2c19ff453935ebd4c06020600692835f52600782528060405f2055604051908152a260065f5260056020526024357f069400f22b28c6c362558d92f66163cec5671cba50b61abd2eecfcd0eaeac51855005b60405162461bcd60e51b815260206004820152601060248201526f1c9bdbdd08185b1c9958591e481cd95d60821b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152721a5b9a5d081c185c985b5cc81b9bdd081cd95d606a1b6044820152606490fd5b3461019f575f36600319011261019f57602060ff600354166040519015158152f35b3461019f57606036600319011261019f576113b761175e565b6113bf611748565b6001600160a01b039182169160443591907f000000000000000000000000da47862a83dac0c112ba89c6abc2159b95afd71c16831480156115dd575b80156115ab575b1561157657811561154057600454801561150b576040516323b872dd60e01b81523360048201527f000000000000000000000000000000000000000000000000000000000000dead6001600160a01b0316602482015260448101849052906020826064815f895af19182156103f6576114b3926114ee575b5060035f5260066020526001600160701b03670de0b6b3a76400006114aa63ffffffff60405f205416938761186a565b041690836119a1565b506040519182526001600160a01b03169133917f0c139059c3dc33b2bf39a13d853d8f16f0ee4c6d4076eef665b063b44518e59490602090a4005b6115069060203d6020116103ef576103e18183611830565b61147a565b60405162461bcd60e51b815260206004820152600d60248201526c1c985d1a5bc81b9bdd081cd95d609a1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d616d6f756e7420746f6f206c6f7760901b6044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b2103a37b5b2b760991b6044820152606490fd5b507f00000000000000000000000034635280737b5bfe6c7dc2fc3065d60d66e781856001600160a01b03168314611402565b507f000000000000000000000000e3668873d944e4a949da05fc8bde419eff5438826001600160a01b031683146113fb565b3461019f575f36600319011261019f576040517f000000000000000000000000e3668873d944e4a949da05fc8bde419eff5438826001600160a01b03168152602090f35b3461019f575f36600319011261019f576040517f000000000000000000000000da47862a83dac0c112ba89c6abc2159b95afd71c6001600160a01b03168152602090f35b3461019f57604036600319011261019f5760043580151580910361019f576116bd611748565b916116c7816117e4565b818152602081019260018060a01b031692838152335f52600260205261170060405f2092511515839060ff801983541691151516179055565b518154610100600160a81b03191660089190911b610100600160a81b0316179055337fd600d35401e5ac794858fa031a56d9a11286fb0577b9d560b781b91b4984766c5f80a4005b602435906001600160a01b038216820361019f57565b600435906001600160a01b038216820361019f57565b6007811015610780575f52600660205260405f2090565b6007811015610780575f52600760205260405f2090565b6007811015610780575f52600560205260405f2090565b906007811015610780575f5260205260405f2090565b8054821015610df5575f5260205f2001905f90565b6040810190811067ffffffffffffffff82111761180057604052565b634e487b7160e01b5f52604160045260245ffd5b6060810190811067ffffffffffffffff82111761180057604052565b90601f8019910116810190811067ffffffffffffffff82111761180057604052565b9081602091031261019f5751801515810361019f5790565b81810292918115918404141715610c3e57565b8115611887570490565b634e487b7160e01b5f52601260045260245ffd5b156118a257565b60405162461bcd60e51b815260206004820152600560248201526421636f726560d81b6044820152606490fd5b906008811015610df55760051b0190565b91908203918211610c3e57565b91908201809211610c3e57565b906003811015610df55760051b0190565b9060405161191881611814565b604081935463ffffffff811683526001600160701b038160201c16602084015260901c910152565b1561194757565b60405162461bcd60e51b81526020600482015260126024820152710850d85b1b195c93dc91195b1959d85d195960721b6044820152606490fd5b906001600160701b03809116911601906001600160701b038211610c3e57565b6001600160a01b03168015611b84576001600160701b038316918215611b4057815f52600160205260405f2054935f5b858110611ab1575050815f52600160205260405f2063ffffffff604051926119f884611814565b16938483526020830181815260408401925f845280546801000000000000000081101561180057611a2e916001820181556117cf565b611a9e5793519051925160901b6001600160901b031916640100000000600160901b03602094851b1663ffffffff90921691909117179092557f941051f5740326e2299731cca609f60c53e8302c775962e529bb902465620ddc91604051908152a360018101809111610c3e5790565b634e487b7160e01b5f525f60045260245ffd5b835f52600160205263ffffffff611acb8260405f206117cf565b50541663ffffffff841614611ae2576001016119d1565b611b3d9450611b169250611b0191935f52600160205260405f206117cf565b50916001600160701b03835460201c16611981565b640100000000600160901b0382549160201b1690640100000000600160901b031916179055565b90565b606460405162461bcd60e51b815260206004820152602060248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152fd5b60405162461bcd60e51b815260206004820152600c60248201526b7a65726f206164647265737360a01b6044820152606490fd5b6001600160a01b0381165f818152600260205260409081902090519190611bde836117e4565b5460ff8116158015845260089190911c6001600160a01b03166020909301928352611c1f575b50516001600160a01b0316908115611c1a575090565b905090565b3303611c2b575f611c04565b60405162461bcd60e51b815260206004820152600b60248201526a08585d5d1a1bdc9a5e995960aa1b6044820152606490fd5b6001600160a01b03165f9081526001602052604081208054919291908115611d2b575f5b828110611c8e57505050565b6001600160701b03611cc0611ca383856117cf565b50611cb5611cb08261190b565b611de5565b905460901c906118e0565b1680611cd0575b50600101611c82565b611d24908296611d1f611ce5600195876117cf565b50611cf484825460901c611981565b815471ffffffffffffffffffffffffffffffffffff1660909190911b6001600160901b031916179055565b6118ed565b9490611cc7565b60405162461bcd60e51b81526020600482015260116024820152704e6f20766573747320746f20636c61696d60781b6044820152606490fd5b611d6d81611de5565b906001600160701b03602082015116926001600160701b03611d97604084019482865116906118e0565b9351169163ffffffff611dca7f0000000000000000000000000000000000000000000000000000000067d23e0b426118e0565b9151169081811115611ddc5750505f90565b611b3d916118e0565b7f0000000000000000000000000000000000000000000000000000000067d23e0b8042105f14611e155750505f90565b611e2663ffffffff835116826118ed565b4210611e3d5750602001516001600160701b031690565b9063ffffffff611e68611b3d93611e626001600160701b0360208601511691426118e0565b9061186a565b9151169061187d56fea164736f6c634300081c000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d000000000000000000000000419905009e4656fdc02418c7df35b1e61ed5f726000000000000000000000000000000000000000000000000000000000000dead000000000000000000000000da47862a83dac0c112ba89c6abc2159b95afd71c000000000000000000000000e3668873d944e4a949da05fc8bde419eff54388200000000000000000000000034635280737b5bfe6c7dc2fc3065d60d66e78185
-----Decoded View---------------
Arg [0] : _core (address): 0xc07e000044F95655c11fda4cD37F70A94d7e0a7d
Arg [1] : _token (address): 0x419905009e4656fdC02418C7Df35B1E61Ed5F726
Arg [2] : _burnAddress (address): 0x000000000000000000000000000000000000dEaD
Arg [3] : _redemptionTokens (address[3]): 0xdA47862a83dac0c112BA89c6abC2159b95afd71C,0xe3668873D944E4A949DA05fc8bDE419eFF543882,0x34635280737b5BFe6c7DC2FC3065D60d66e78185
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000c07e000044f95655c11fda4cd37f70a94d7e0a7d
Arg [1] : 000000000000000000000000419905009e4656fdc02418c7df35b1e61ed5f726
Arg [2] : 000000000000000000000000000000000000000000000000000000000000dead
Arg [3] : 000000000000000000000000da47862a83dac0c112ba89c6abc2159b95afd71c
Arg [4] : 000000000000000000000000e3668873d944e4a949da05fc8bde419eff543882
Arg [5] : 00000000000000000000000034635280737b5bfe6c7dc2fc3065d60d66e78185
Loading...
Loading
Loading...
Loading
Net Worth in USD
$13,305,470.09
Net Worth in ETH
4,616.785471
Token Allocations
RSUP
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.270724 | 49,147,730.1257 | $13,305,470.09 |
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.