### TypeScript Example: Interact with Rewards V2 Contracts using Wagmi Source: https://context7.com/symbioticfi/rewards-v2/llms.txt This snippet demonstrates how to set up viem clients for reading and writing to the blockchain, define contract addresses, and execute core Rewards V2 functionalities like depositing rewards, claiming vault snapshot rewards, and checking balances. It requires environment variables for the RPC URL and private key, and pre-generated ABIs. ```typescript import { createPublicClient, createWalletClient, http, parseEther } from 'viem'; import { mainnet } from 'viem/chains'; import { privateKeyToAccount } from 'viem/accounts'; import { iCumulativeMerkleRewardsABI, iVaultSnapshotRewardsABI, iRewardsABI } from './generated'; // Setup clients const publicClient = createPublicClient({ chain: mainnet, transport: http(process.env.ETH_RPC_URL) }); const account = privateKeyToAccount(`0x${process.env.PRIVATE_KEY}`); const walletClient = createWalletClient({ account, chain: mainnet, transport: http(process.env.ETH_RPC_URL) }); const REWARDS_ADDRESS = '0x...'; const NETWORK_ADDRESS = '0x...'; const TOKEN_ADDRESS = '0x...'; // Deposit cumulative merkle rewards async function depositRewards() { const hash = await walletClient.writeContract({ address: REWARDS_ADDRESS, abi: iCumulativeMerkleRewardsABI, functionName: 'depositCumulativeMerkleRewards', args: [NETWORK_ADDRESS, TOKEN_ADDRESS, parseEther('1000')] }); const receipt = await publicClient.waitForTransactionReceipt({ hash }); console.log('Rewards deposited:', receipt.transactionHash); } // Claim vault snapshot rewards async function claimVaultRewards() { const vaultAddress = '0x...'; // Get pending rewards const lastUnclaimed = await publicClient.readContract({ address: REWARDS_ADDRESS, abi: iVaultSnapshotRewardsABI, functionName: 'lastUnclaimedReward', args: [account.address, vaultAddress, NETWORK_ADDRESS, TOKEN_ADDRESS] }); const totalRewards = await publicClient.readContract({ address: REWARDS_ADDRESS, abi: iVaultSnapshotRewardsABI, functionName: 'rewardsLength', args: [vaultAddress, NETWORK_ADDRESS, TOKEN_ADDRESS] }); const rewardsToClaim = Number(totalRewards) - Number(lastUnclaimed); if (rewardsToClaim > 0) { const hash = await walletClient.writeContract({ address: REWARDS_ADDRESS, abi: iVaultSnapshotRewardsABI, functionName: 'claimVaultSnapshotRewards', args: [ account.address, NETWORK_ADDRESS, TOKEN_ADDRESS, vaultAddress, lastUnclaimed, lastUnclaimed, BigInt(rewardsToClaim), [] ] }); console.log('Claimed rewards:', hash); } } // Query reward balances async function checkBalances() { const balance = await publicClient.readContract({ address: REWARDS_ADDRESS, abi: iCumulativeMerkleRewardsABI, functionName: 'balance', args: [NETWORK_ADDRESS, TOKEN_ADDRESS] }); console.log('Network balance:', balance); } // Execute (async () => { await depositRewards(); await claimVaultRewards(); await checkBalances(); })(); ``` -------------------------------- ### Solidity: Emit Event After State Change Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Provides an example of emitting an event immediately after a state-changing operation, such as burning tokens. The event name typically matches the function name, ensuring consistency and clear logging. ```solidity function _burn(address who, uint256 value) internal { super._burn(who, value); emit Burn(who, value); } ``` -------------------------------- ### Manage Curator Fees: Setup, Configure, and Claim (Solidity) Source: https://context7.com/symbioticfi/rewards-v2/llms.txt Enables curators to manage fees associated with vault operations. This includes setting curators for vaults, configuring curator and operator fee percentages, setting network-specific fees, and claiming curator fees. It requires multiple interfaces: IVaultSnapshotRewards, ICuratorRegistry, and IFeeRegistry. ```solidity // SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IVaultSnapshotRewards} from "./interfaces/IVaultSnapshotRewards.sol";\nimport {ICuratorRegistry} from "./interfaces/ICuratorRegistry.sol";\nimport {IFeeRegistry} from "./interfaces/IFeeRegistry.sol";\n\ncontract CuratorManager {\n IVaultSnapshotRewards public immutable rewards;\n ICuratorRegistry public immutable curatorRegistry;\n IFeeRegistry public immutable feeRegistry;\n\n constructor(address _rewards, address _curatorRegistry, address _feeRegistry) {\n rewards = IVaultSnapshotRewards(_rewards);\n curatorRegistry = ICuratorRegistry(_curatorRegistry);\n feeRegistry = IFeeRegistry(_feeRegistry);\n }\n\n function setupCurator(address vault, address curator) external {\n curatorRegistry.setCurator(vault, curator);\n }\n\n function configureFees(\n address vault,\n uint256 curatorFeePercent,\n uint256 operatorsFeePercent\n ) external {\n require(curatorRegistry.getCurator(vault) == msg.sender, "Not curator");\n\n uint256 maxFee = feeRegistry.MAX_PARTICIPANT_FEE();\n require(curatorFeePercent <= maxFee, "Curator fee too high");\n require(operatorsFeePercent <= maxFee, "Operators fee too high");\n\n feeRegistry.setCuratorFee(vault, curatorFeePercent);\n feeRegistry.setOperatorsFee(vault, operatorsFeePercent);\n }\n\n function setNetworkSpecificFees(\n address vault,\n address network,\n uint256 curatorNetworkFee,\n uint256 operatorsNetworkFee\n ) external {\n require(curatorRegistry.getCurator(vault) == msg.sender, "Not curator");\n\n feeRegistry.setCuratorNetworkFee(vault, network, true, curatorNetworkFee);\n feeRegistry.setOperatorsNetworkFee(vault, network, true, operatorsNetworkFee);\n }\n\n function claimCuratorFees(\n address recipient,\n address vault,\n address token\n ) external {\n require(curatorRegistry.getCurator(vault) == msg.sender, "Not curator");\n\n uint256 availableFees = rewards.curatorFees(vault, token);\n require(availableFees > 0, "No fees to claim");\n\n rewards.claimCuratorFees(recipient, vault, token);\n }\n\n function getCuratorFeesAvailable(\n address vault,\n address token\n ) external view returns (uint256) {\n return rewards.curatorFees(vault, token);\n }\n} ``` -------------------------------- ### Solidity: Import Grouping and Ordering Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Demonstrates the structured approach to organizing import statements. Imports are grouped by type (contracts, libraries, interfaces, external files) and ordered alphabetically within each group. ```solidity import {NetworkManager} from "../base/NetworkManager.sol"; import {OzEIP712} from "../base/OzEIP712.sol"; import {PermissionManager} from "../base/PermissionManager.sol"; import {Checkpoints} from "../../libraries/structs/Checkpoints.sol"; import {KeyTags} from "../../libraries/utils/KeyTags.sol"; import {ISettlement} from "../interfaces/modules/settlement/ISettlement.sol"; import {ISigVerifier} from "../interfaces/modules/settlement/sig-verifiers/ISigVerifier.sol"; import {StaticDelegateCallable} from "@symbioticfi/core/src/contracts/common/StaticDelegateCallable.sol"; import {Subnetwork} from "@symbioticfi/core/src/contracts/libraries/Subnetwork.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; ``` -------------------------------- ### Solidity: Private and Internal Variable/Function Naming Convention Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Demonstrates the convention of prefixing internal or private state variables and functions with an underscore. This improves code readability and helps distinguish these members from public or external ones. ```solidity contract TestContract { uint256 private _privateVar; uint256 internal _internalVar; function _testInternal() internal { ... } function _testPrivate() private { ... } } ``` -------------------------------- ### Solidity: Explicit Version for Deployable Contracts Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Mandates the use of an explicit Solidity version (`pragma solidity 0.8.X;`) for contracts intended for deployment. This ensures predictable behavior and avoids compatibility issues. ```solidity pragma solidity 0.8.X; ``` -------------------------------- ### Solidity: Comparison with msg.sender or tx.origin Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Specifies the rule for comparing with `msg.sender` or `tx.origin`, requiring these keywords to be on the right side of the inequality. This promotes consistent and clear access control checks. ```solidity modifier onlyOwner() internal { if (owner != msg.sender) { revert NotOwner(); } } ``` -------------------------------- ### Solidity: Interface Naming Convention Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Specifies the convention for naming interfaces by prefixing them with a capital 'I'. This convention helps quickly identify interface definitions within the codebase. ```solidity interface IERC777 { ``` -------------------------------- ### Solidity: Naming Collision Avoidance with Trailing Underscore Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Illustrates how to avoid naming collisions between constructor parameters and public state variables using a single trailing underscore for the parameter name. This ensures clarity when assigning values in the constructor. ```solidity contract TestContract { uint256 public foo; constructor(uint256 foo_) { foo = foo_; } } ``` -------------------------------- ### Solidity: Caret Range Operator for Abstract Contracts and Libraries Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Recommends using the caret (`^`) range operator for specifying Solidity versions in abstract contracts, libraries, and interfaces (`pragma solidity ^0.X.0;`). This allows for broader compatibility within specified major versions. ```solidity pragma solidity ^0.X.0; ``` -------------------------------- ### Solidity: Error Declaration Alphabetical Ordering Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Instructs to order custom error declarations alphabetically in ascending order. This convention enhances the readability and maintainability of error handling logic. ```solidity error InsufficientFunds(); error NoAccess(); error NotOwner(); ``` -------------------------------- ### Protocol Fee Management (Solidity) Source: https://context7.com/symbioticfi/rewards-v2/llms.txt Manages protocol fees for reward distributions. This contract allows setting fee percentages for specific protocols, calculating fee amounts, and claiming accumulated fees. It depends on IProtocolFees and IRewards interfaces and uses OpenZeppelin's Ownable for access control. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IProtocolFees} from "./interfaces/IProtocolFees.sol"; import {IRewards} from "./interfaces/IRewards.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; contract ProtocolFeeManager is Ownable { IProtocolFees public immutable protocolFees; constructor(address _protocolFees) { protocolFees = IProtocolFees(_protocolFees); } function setProtocolFee( bytes32 protocolId, bool enabled, uint256 feePercent ) external onlyOwner { uint256 maxFee = protocolFees.MAX_FEE(); require(feePercent <= maxFee, "Fee too high"); protocolFees.setProtocolFee(protocolId, enabled, feePercent); } function calculateTotalAmount( uint64 rewardsType, address network, uint256 distributionAmount ) external view returns (uint256 totalRequired) { totalRequired = protocolFees.distributionToTotalAmount( rewardsType, network, distributionAmount ); } function calculateDistributionAmount( uint64 rewardsType, address network, uint256 totalAmount ) external view returns (uint256 netDistribution) { netDistribution = protocolFees.totalToDistributionAmount( rewardsType, network, totalAmount ); } function claimAccumulatedFees( address recipient, address token ) external onlyOwner returns (uint256 feesClaimed) { uint256 available = protocolFees.protocolFees(token); require(available > 0, "No fees available"); feesClaimed = protocolFees.claimProtocolFees(recipient, token); } function getProtocolFee( uint64 rewardsType, address network ) external view returns (uint256) { return protocolFees.protocolFee(rewardsType, network); } } ``` -------------------------------- ### Solidity: Abstract Contract Declaration Source: https://github.com/symbioticfi/rewards-v2/blob/main/CONTRIBUTING.md Shows the use of the `abstract` keyword for contracts that are not intended to be used standalone. These contracts require inheritance by other contracts to be functional. ```solidity abstract contract AccessControl is ..., { ... ``` -------------------------------- ### Unified Rewards Claiming Interface (Solidity) Source: https://context7.com/symbioticfi/rewards-v2/llms.txt Allows claiming of different reward types through a single contract interface. It supports claiming cumulative merkle rewards and vault snapshot rewards, as well as batch claiming multiple reward types. Dependencies include IRewards and ICumulativeMerkleRewards interfaces. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IRewards} from "./interfaces/IRewards.sol"; import {ICumulativeMerkleRewards} from "./interfaces/ICumulativeMerkleRewards.sol"; contract UnifiedRewardsClaimer { IRewards public immutable rewards; constructor(address _rewards) { rewards = IRewards(_rewards); } function claimCumulativeMerkle( address recipient, address token, address network, ICumulativeMerkleRewards.CumulativeDistributionLeaf calldata leaf, bytes32[] calldata proof, bytes32 merkleRoot ) external { bytes memory claimData = abi.encodePacked( uint64(IRewards.RewardsType.CUMULATIVE_MERKLE), abi.encode(network, leaf, proof, merkleRoot) ); rewards.claimRewards(recipient, token, claimData); } function claimVaultSnapshot( address recipient, address token, address network, address vault, uint256 lastUnclaimedRewards, uint256 firstRewardToClaim, uint256 rewardsToClaim, bytes[] memory activeSharesOfHints ) external { bytes memory claimData = abi.encodePacked( uint64(IRewards.RewardsType.VAULT_SNAPSHOT), abi.encode( network, vault, lastUnclaimedRewards, firstRewardToClaim, rewardsToClaim, activeSharesOfHints ) ); rewards.claimRewards(recipient, token, claimData); } function batchClaimMultipleTypes( address recipient, address[] calldata tokens, bytes[] calldata claimDataArray ) external { require(tokens.length == claimDataArray.length, "Length mismatch"); for (uint256 i = 0; i < tokens.length; i++) { rewards.claimRewards(recipient, tokens[i], claimDataArray[i]); } } } ``` -------------------------------- ### Distribute Vault Snapshot Rewards (Solidity) Source: https://context7.com/symbioticfi/rewards-v2/llms.txt Distributes on-chain rewards to vault stakers at specified timestamps. It requires authorization from network or middleware addresses and interacts with the IVaultSnapshotRewards interface for the actual distribution. Dependencies include IVaultSnapshotRewards and IERC20 interfaces. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IVaultSnapshotRewards} from "./interfaces/IVaultSnapshotRewards.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract VaultRewardDistributor { IVaultSnapshotRewards public immutable rewards; address public network; address public middleware; constructor(address _rewards, address _network, address _middleware) { rewards = IVaultSnapshotRewards(_rewards); network = _network; middleware = _middleware; } function distributeReward( bytes32 subnetwork, address token, address vault, uint256 amount, uint48 timestamp ) external { require(msg.sender == network || msg.sender == middleware, "Not authorized"); // Prepare hints for gas optimization IVaultSnapshotRewards.DistributeVaultSnapshotRewardsHints memory hints; bytes memory encodedHints = abi.encode(hints); // Transfer tokens and approve IERC20(token).transferFrom(msg.sender, address(this), amount); IERC20(token).approve(address(rewards), amount); // Distribute to vault rewards.distributeVaultSnapshotRewards( subnetwork, token, vault, amount, timestamp, encodedHints ); } function getRewardsCount( address vault, address token ) external view returns (uint256) { return rewards.rewardsLength(vault, network, token); } function getRewardDetails( address vault, address token, uint256 index ) external view returns (IVaultSnapshotRewards.RewardDistribution memory) { return rewards.rewards(vault, network, token, index); } } ``` -------------------------------- ### Claim Vault Snapshot Rewards (Solidity) Source: https://context7.com/symbioticfi/rewards-v2/llms.txt Allows stakers to claim vault snapshot rewards with support for batch processing. This contract interacts with the IVaultSnapshotRewards interface to facilitate reward claims. It calculates the number of rewards to claim based on the staker's last unclaimed reward index and the total available rewards. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IVaultSnapshotRewards} from "./interfaces/IVaultSnapshotRewards.sol"; contract StakerRewardClaimer { IVaultSnapshotRewards public immutable rewards; constructor(address _rewards) { rewards = IVaultSnapshotRewards(_rewards); } function claimStakerRewards( address recipient, address network, address token, address vault, uint256 maxRewardsToClaim ) external returns (uint256 claimed) { uint256 lastUnclaimed = rewards.lastUnclaimedReward( msg.sender, vault, network, token ); uint256 totalRewards = rewards.rewardsLength(vault, network, token); uint256 rewardsToClaim = totalRewards - lastUnclaimed; if (rewardsToClaim > maxRewardsToClaim) { rewardsToClaim = maxRewardsToClaim; } require(rewardsToClaim > 0, "No rewards to claim"); bytes[] memory activeSharesOfHints = new bytes[](rewardsToClaim); rewards.claimVaultSnapshotRewards( recipient, network, token, vault, lastUnclaimed, lastUnclaimed, // firstRewardToClaim rewardsToClaim, activeSharesOfHints ); } function getPendingRewards( address staker, address network, address token, address vault ) external view returns (uint256 pendingCount) { uint256 lastUnclaimed = rewards.lastUnclaimedReward(staker, vault, network, token); uint256 totalRewards = rewards.rewardsLength(vault, network, token); pendingCount = totalRewards > lastUnclaimed ? totalRewards - lastUnclaimed : 0; } } ``` -------------------------------- ### Claim Operator Fees from Vault Snapshot Reward Distributions (Solidity) Source: https://context7.com/symbioticfi/rewards-v2/llms.txt Allows an operator to claim their fees from vault snapshot reward distributions. It requires the IVaultSnapshotRewards interface and calculates the pending fees based on last unclaimed rewards and total rewards. The function returns the number of claimed rewards. ```solidity // SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IVaultSnapshotRewards} from "./interfaces/IVaultSnapshotRewards.sol";\n\ncontract OperatorFeeClaimer {\n IVaultSnapshotRewards public immutable rewards;\n\n constructor(address _rewards) {\n rewards = IVaultSnapshotRewards(_rewards);\n }\n\n function claimOperatorFees(\n address recipient,\n address network,\n address token,\n address vault,\n uint256 maxRewardsToClaim,\n bytes calldata operatorExtraData\n ) external returns (uint256 claimed) {\n uint256 lastUnclaimed = rewards.lastUnclaimedOperatorReward(\n msg.sender,\n vault,\n network,\n token\n );\n\n uint256 totalRewards = rewards.rewardsLength(vault, network, token);\n uint256 rewardsToClaim = totalRewards - lastUnclaimed;\n\n if (rewardsToClaim > maxRewardsToClaim) {\n rewardsToClaim = maxRewardsToClaim;\n }\n\n require(rewardsToClaim > 0, "No operator fees to claim");\n\n rewards.claimOperatorFees(\n recipient,\n network,\n token,\n vault,\n lastUnclaimed,\n lastUnclaimed, // firstRewardToClaim\n rewardsToClaim,\n operatorExtraData\n );\n }\n\n function checkPendingOperatorFees(\n address operator,\n address network,\n address token,\n address vault\n ) external view returns (uint256 pendingCount) {\n uint256 lastUnclaimed = rewards.lastUnclaimedOperatorReward(\n operator,\n vault,\n network,\n token\n );\n uint256 totalRewards = rewards.rewardsLength(vault, network, token);\n pendingCount = totalRewards > lastUnclaimed ? totalRewards - lastUnclaimed : 0;\n }\n} ``` -------------------------------- ### Solidity: Fund and Distribute Cumulative Merkle Rewards Source: https://context7.com/symbioticfi/rewards-v2/llms.txt Contracts for funding rewards and distributing them using the Cumulative Merkle Rewards mechanism. It handles token transfers, approvals, and calls the core distribution logic. Requires ICumulativeMerkleRewards and IERC20 interfaces. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ICumulativeMerkleRewards} from "./interfaces/ICumulativeMerkleRewards.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract NetworkRewardDistributor { ICumulativeMerkleRewards public immutable rewards; address public immutable network; address rewarder; constructor(address _rewards, address _network) { rewards = ICumulativeMerkleRewards(_rewards); network = _network; } function setupRewarder(address _rewarder) external { rewarder = _rewarder; rewards.setRewarder(_rewarder); } function fundRewards(address token, uint256 amount) external { IERC20(token).transferFrom(msg.sender, address(this), amount); IERC20(token).approve(address(rewards), amount); rewards.depositCumulativeMerkleRewards(network, token, amount); } function distribute( ICumulativeMerkleRewards.CumulativeDistribution calldata distribution, ICumulativeMerkleRewards.TokenAmount[] calldata totalAmounts, bytes calldata protocolSignature, bytes calldata rewarderSignature ) external { rewards.distributeCumulativeMerkleRewards( network, distribution, totalAmounts, protocolSignature, rewarderSignature ); } } ``` -------------------------------- ### Solidity: Claim Cumulative Merkle Rewards Source: https://context7.com/symbioticfi/rewards-v2/llms.txt A contract for claiming cumulative rewards using Merkle proofs. It facilitates the process of users claiming their allocated rewards by verifying their proof against a Merkle root. Includes a function to check claimable amounts. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ICumulativeMerkleRewards} from "./interfaces/ICumulativeMerkleRewards.sol"; contract RewardClaimer { ICumulativeMerkleRewards public immutable rewards; constructor(address _rewards) { rewards = ICumulativeMerkleRewards(_rewards); } function claimRewards( address recipient, address network, address token, uint256 rewardeeType, uint256 cumulativeAmount, bytes32 rewardeeDataHash, bytes32[] calldata proof, bytes32 merkleRoot ) external returns (uint256 claimedAmount) { ICumulativeMerkleRewards.CumulativeDistributionLeaf memory leaf = ICumulativeMerkleRewards.CumulativeDistributionLeaf({ token: token, rewardeeType: rewardeeType, amount: cumulativeAmount, rewardeeDataHash: rewardeeDataHash }); uint256 beforeBalance = rewards.claimed(network, token, msg.sender, rewardeeType); rewards.claimCumulativeMerkleRewards( recipient, network, leaf, proof, merkleRoot ); uint256 afterBalance = rewards.claimed(network, token, msg.sender, rewardeeType); claimedAmount = afterBalance - beforeBalance; } function checkClaimable( address network, address token, address rewardee, uint256 rewardeeType, uint256 cumulativeAmount ) external view returns (uint256 claimable) { uint256 alreadyClaimed = rewards.claimed(network, token, rewardee, rewardeeType); claimable = cumulativeAmount > alreadyClaimed ? cumulativeAmount - alreadyClaimed : 0; } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.