S Price: $0.069549 (-1.69%)
Gas: 55 Gwei

Contract

0x8F3c161F52738354Fd6eF0dA7f1F898FDb369392

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
270293252025-05-15 17:07:33254 days ago1747328853  Contract Creation0 S
Cross-Chain Transactions
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xe91a560d...372c71441
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
SiloIncentivesControllerCL

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: GPL-2.0-or-later
pragma solidity 0.8.28;

import {
    ISiloIncentivesController,
    IDistributionManager
} from "silo-core/contracts/incentives/interfaces/ISiloIncentivesController.sol";

import {IIncentivesClaimingLogic} from "../../interfaces/IIncentivesClaimingLogic.sol";

/// @title Silo incentives controller claiming logic
contract SiloIncentivesControllerCL is IIncentivesClaimingLogic {
    /// @notice Distributes rewards to vault depositors
    ISiloIncentivesController public immutable VAULT_INCENTIVES_CONTROLLER;
    /// @notice Distributes rewards to silo depositors
    ISiloIncentivesController public immutable SILO_INCENTIVES_CONTROLLER;

    constructor(
        address _vaultIncentivesController,
        address _siloIncentivesController
    ) {
        require(_vaultIncentivesController != address(0), VaultIncentivesControllerZeroAddress());
        require(_siloIncentivesController != address(0), SiloIncentivesControllerZeroAddress());

        VAULT_INCENTIVES_CONTROLLER = ISiloIncentivesController(_vaultIncentivesController);
        SILO_INCENTIVES_CONTROLLER = ISiloIncentivesController(_siloIncentivesController);
    }

    function claimRewardsAndDistribute() external virtual {
        IDistributionManager.AccruedRewards[] memory accruedRewards =
            SILO_INCENTIVES_CONTROLLER.claimRewards(address(VAULT_INCENTIVES_CONTROLLER));

        for (uint256 i = 0; i < accruedRewards.length; i++) {
            if (accruedRewards[i].amount == 0) continue;

            VAULT_INCENTIVES_CONTROLLER.immediateDistribution(
                accruedRewards[i].rewardToken,
                uint104(accruedRewards[i].amount)
            );
        }
    }
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.8.28;

import {IDistributionManager} from "./IDistributionManager.sol";
import {DistributionTypes} from "../lib/DistributionTypes.sol";

interface ISiloIncentivesController is IDistributionManager {
    event ClaimerSet(address indexed user, address indexed claimer);
    event IncentivesProgramCreated(string name);
    event IncentivesProgramUpdated(string name);

    event RewardsAccrued(
        address indexed user,
        address indexed rewardToken,
        string indexed programName,
        uint256 amount
    );

    event RewardsClaimed(
        address indexed user,
        address indexed to,
        address indexed rewardToken,
        bytes32 programId,
        address claimer,
        uint256 amount
    );

    error InvalidDistributionEnd();
    error InvalidConfiguration();
    error IndexOverflowAtEmissionsPerSecond();
    error InvalidToAddress();
    error InvalidUserAddress();
    error ClaimerUnauthorized();
    error InvalidRewardToken();
    error IncentivesProgramAlreadyExists();
    error IncentivesProgramNotFound();
    error DifferentRewardsTokens();
    error EmissionPerSecondTooHigh();

    /**
     * @dev Silo share token event handler
     * @param _sender The address of the sender
     * @param _senderBalance The balance of the sender
     * @param _recipient The address of the recipient
     * @param _recipientBalance The balance of the recipient
     * @param _totalSupply The total supply of the asset in the lending pool
     * @param _amount The amount of the transfer
     */
    function afterTokenTransfer(
        address _sender,
        uint256 _senderBalance,
        address _recipient,
        uint256 _recipientBalance,
        uint256 _totalSupply,
        uint256 _amount
    ) external;

    /**
     * @dev Immediately distributes rewards to the incentives program
     * Expect an `_amount` to be transferred to the contract before calling this fn
     * @param _tokenToDistribute The token to distribute
     * @param _amount The amount of rewards to distribute
     */
    function immediateDistribution(address _tokenToDistribute, uint104 _amount) external;

    /// @dev It will transfer all the reward token balance to the owner.
    /// @param _rewardToken The reward token to rescue
    function rescueRewards(address _rewardToken) external;

    /**
     * @dev Whitelists an address to claim the rewards on behalf of another address
     * @param _user The address of the user
     * @param _claimer The address of the claimer
     */
    function setClaimer(address _user, address _claimer) external;

    /**
     * @dev Creates a new incentives program
     * @param _incentivesProgramInput The incentives program creation input
     */
    function createIncentivesProgram(DistributionTypes.IncentivesProgramCreationInput memory _incentivesProgramInput)
        external;

    /**
     * @dev Updates an existing incentives program
     * @param _incentivesProgram The incentives program name
     * @param _distributionEnd The distribution end
     * @param _emissionPerSecond The emission per second
     */
    function updateIncentivesProgram(
        string calldata _incentivesProgram,
        uint40 _distributionEnd,
        uint104 _emissionPerSecond
    ) external;

    /**
     * @dev Claims reward for an user to the desired address, on all the assets of the lending pool,
     * accumulating the pending rewards
     * @param _to Address that will be receiving the rewards
     * @return accruedRewards
     */
    function claimRewards(address _to) external returns (AccruedRewards[] memory accruedRewards);

    /**
     * @dev Claims reward for an user to the desired address, on all the assets of the lending pool,
     * accumulating the pending rewards
     * @param _to Address that will be receiving the rewards
     * @param _programNames The incentives program names
     * @return accruedRewards
     */
    function claimRewards(address _to, string[] calldata _programNames)
        external
        returns (AccruedRewards[] memory accruedRewards);

    /**
     * @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending
     * rewards. The caller must be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager
     * @param _user Address to check and claim rewards
     * @param _to Address that will be receiving the rewards
     * @param _programNames The incentives program names
     * @return accruedRewards
     */
    function claimRewardsOnBehalf(address _user, address _to, string[] calldata _programNames)
        external
        returns (AccruedRewards[] memory accruedRewards);

    /**
     * @dev Returns the whitelisted claimer for a certain address (0x0 if not set)
     * @param _user The address of the user
     * @return The claimer address
     */
    function getClaimer(address _user) external view returns (address);

    /**
     * @dev Returns the total of rewards of an user, already accrued + not yet accrued
     * @param _user The address of the user
     * @param _programName The incentives program name
     * @return unclaimedRewards
     */
    function getRewardsBalance(address _user, string calldata _programName)
        external
        view
        returns (uint256 unclaimedRewards);

    /**
     * @dev Returns the total of rewards of an user, already accrued + not yet accrued
     * @param _user The address of the user
     * @param _programNames The incentives program names (should have the same rewards token)
     * @return unclaimedRewards
     */
    function getRewardsBalance(address _user, string[] calldata _programNames)
        external
        view
        returns (uint256 unclaimedRewards);

    /**
     * @dev returns the unclaimed rewards of the user
     * @param _user the address of the user
     * @param _programName The incentives program name
     * @return the unclaimed user rewards
     */
    function getUserUnclaimedRewards(address _user, string calldata _programName) external view returns (uint256);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

/// @title Incentives Claiming Logic interface
interface IIncentivesClaimingLogic {
    error VaultIncentivesControllerZeroAddress();
    error SiloIncentivesControllerZeroAddress();

    /// @notice Claim and distribute rewards to the vault.
    /// @dev Can claim rewards from multiple sources and distribute them to the vault users.
    function claimRewardsAndDistribute() external;
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.8.28;

import {DistributionTypes} from "../lib/DistributionTypes.sol";

interface IDistributionManager {
    struct IncentivesProgram {
        uint256 index;
        address rewardToken; // can't be updated after creation
        uint104 emissionPerSecond; // configured by owner
        uint40 lastUpdateTimestamp;
        uint40 distributionEnd; // configured by owner
        mapping(address user => uint256 userIndex) users;
    }

    struct IncentiveProgramDetails {
        uint256 index;
        address rewardToken;
        uint104 emissionPerSecond;
        uint40 lastUpdateTimestamp;
        uint40 distributionEnd;
    }

    struct AccruedRewards {
        uint256 amount;
        bytes32 programId;
        address rewardToken;
    }

    event AssetConfigUpdated(address indexed asset, uint256 emission);
    event AssetIndexUpdated(address indexed asset, uint256 index);
    event DistributionEndUpdated(string incentivesProgram, uint256 newDistributionEnd);
    event IncentivesProgramIndexUpdated(string incentivesProgram, uint256 newIndex);
    event UserIndexUpdated(address indexed user, string incentivesProgram, uint256 newIndex);

    error OnlyNotifier();
    error TooLongProgramName();
    error CollisionWithAddress();
    error InvalidIncentivesProgramName();
    error OnlyNotifierOrOwner();
    error ZeroAddress();

    /**
     * @dev Sets the end date for the distribution
     * @param _incentivesProgram The incentives program name
     * @param _distributionEnd The end date timestamp
     */
    function setDistributionEnd(string calldata _incentivesProgram, uint40 _distributionEnd) external;

    /**
     * @dev Gets the end date for the distribution  
     * @param _incentivesProgram The incentives program name
     * @return The end of the distribution
     */
    function getDistributionEnd(string calldata _incentivesProgram) external view returns (uint256);

    /**
     * @dev Returns the data of an user on a distribution
     * @param _user Address of the user
     * @param _incentivesProgram The incentives program name
     * @return The new index
     */
    function getUserData(address _user, string calldata _incentivesProgram) external view returns (uint256);

    /**
     * @dev Returns the configuration of the distribution for a certain incentives program
     * @param _incentivesProgram The incentives program name
     * @return details The configuration of the incentives program
     */
    function incentivesProgram(string calldata _incentivesProgram)
        external
        view
        returns (IncentiveProgramDetails memory details);

    /**
     * @dev Returns the program id for the given program name.
     * This method TRUNCATES the program name to 32 bytes.
     * If provided strings only differ after the 32nd byte they would result in the same ProgramId.
     * Ensure to use inputs that will result in 32 bytes or less.
     * @param _programName The incentives program name
     * @return programId
     */
    function getProgramId(string calldata _programName) external pure returns (bytes32 programId);

    /**
     * @dev returns the names of all the incentives programs
     * @return programsNames the names of all the incentives programs
     */
    function getAllProgramsNames() external view returns (string[] memory programsNames);

    /**
     * @dev returns the name of an incentives program
     * @param _programName the name (bytes32) of the incentives program
     * @return programName the name (string) of the incentives program
     */
    function getProgramName(bytes32 _programName) external pure returns (string memory programName);
}

File 5 of 5 : DistributionTypes.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.8.28;

library DistributionTypes {
    struct IncentivesProgramCreationInput {
        string name;
        address rewardToken;
        uint104 emissionPerSecond;
        uint40 distributionEnd;
    }

    struct AssetConfigInput {
        uint104 emissionPerSecond;
        uint256 totalStaked;
        address underlyingAsset;
    }

    struct UserStakeInput {
        address underlyingAsset;
        uint256 stakedByUser;
        uint256 totalStaked;
    }
}

Settings
{
  "remappings": [
    "forge-std/=gitmodules/forge-std/src/",
    "silo-foundry-utils/=gitmodules/silo-foundry-utils/contracts/",
    "properties/=gitmodules/crytic/properties/contracts/",
    "silo-core/=silo-core/",
    "silo-oracles/=silo-oracles/",
    "silo-vaults/=silo-vaults/",
    "ve-silo/=ve-silo/",
    "@openzeppelin/=gitmodules/openzeppelin-contracts-5/",
    "morpho-blue/=gitmodules/morpho-blue/src/",
    "openzeppelin5/=gitmodules/openzeppelin-contracts-5/contracts/",
    "openzeppelin5-upgradeable/=gitmodules/openzeppelin-contracts-upgradeable-5/contracts/",
    "chainlink/=gitmodules/chainlink/contracts/src/",
    "chainlink-ccip/=gitmodules/chainlink-ccip/contracts/src/",
    "uniswap/=gitmodules/uniswap/",
    "@uniswap/v3-core/=gitmodules/uniswap/v3-core/",
    "balancer-labs/v2-solidity-utils/=external/balancer-v2-monorepo/pkg/solidity-utils/contracts/",
    "balancer-labs/v2-interfaces/=external/balancer-v2-monorepo/pkg/interfaces/contracts/",
    "balancer-labs/v2-liquidity-mining/=external/balancer-v2-monorepo/pkg/liquidity-mining/contracts/",
    "pyth-sdk-solidity/=gitmodules/pyth-sdk-solidity/target_chains/ethereum/sdk/solidity/",
    "a16z-erc4626-tests/=gitmodules/a16z-erc4626-tests/",
    "ERC4626/=gitmodules/crytic/properties/lib/ERC4626/contracts/",
    "createx/=gitmodules/pyth-sdk-solidity/lazer/contracts/evm/lib/createx/src/",
    "crytic/=gitmodules/crytic/",
    "ds-test/=gitmodules/openzeppelin-contracts-5/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=gitmodules/openzeppelin-contracts-5/lib/erc4626-tests/",
    "halmos-cheatcodes/=gitmodules/morpho-blue/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts-5/=gitmodules/openzeppelin-contracts-5/",
    "openzeppelin-contracts-upgradeable-5/=gitmodules/openzeppelin-contracts-upgradeable-5/",
    "openzeppelin-contracts-upgradeable/=gitmodules/pyth-sdk-solidity/lazer/contracts/evm/lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=gitmodules/openzeppelin-contracts-upgradeable-5/lib/openzeppelin-contracts/",
    "solady/=gitmodules/pyth-sdk-solidity/lazer/contracts/evm/lib/createx/lib/solady/",
    "solmate/=gitmodules/crytic/properties/lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_vaultIncentivesController","type":"address"},{"internalType":"address","name":"_siloIncentivesController","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"SiloIncentivesControllerZeroAddress","type":"error"},{"inputs":[],"name":"VaultIncentivesControllerZeroAddress","type":"error"},{"inputs":[],"name":"SILO_INCENTIVES_CONTROLLER","outputs":[{"internalType":"contract ISiloIncentivesController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_INCENTIVES_CONTROLLER","outputs":[{"internalType":"contract ISiloIncentivesController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewardsAndDistribute","outputs":[],"stateMutability":"nonpayable","type":"function"}]

0x60c060405234801561000f575f5ffd5b5060405161053038038061053083398101604081905261002e916100ae565b6001600160a01b038216610055576040516348a7684f60e11b815260040160405180910390fd5b6001600160a01b03811661007c5760405163130dfd7b60e21b815260040160405180910390fd5b6001600160a01b039182166080521660a0526100df565b80516001600160a01b03811681146100a9575f5ffd5b919050565b5f5f604083850312156100bf575f5ffd5b6100c883610093565b91506100d660208401610093565b90509250929050565b60805160a05161041f6101115f395f81816048015260f801525f8181608b0152818160ce0152610199015261041f5ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c8063a13659d514610043578063ab2939fb14610086578063f57a64ae146100ad575b5f5ffd5b61006a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61006a7f000000000000000000000000000000000000000000000000000000000000000081565b6100b56100b7565b005b604051633bd73ee360e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063ef5cfb8c906024015f604051808303815f875af115801561013f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261016691908101906102e5565b90505f5b815181101561027357818181518110610185576101856103d5565b60200260200101515f01515f031561026b577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632e953c218383815181106101d8576101d86103d5565b6020026020010151604001518484815181106101f6576101f66103d5565b6020908102919091010151516040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526cffffffffffffffffffffffffff1660248201526044015f604051808303815f87803b158015610254575f5ffd5b505af1158015610266573d5f5f3e3d5ffd5b505050505b60010161016a565b5050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156102ae576102ae610277565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156102dd576102dd610277565b604052919050565b5f602082840312156102f5575f5ffd5b815167ffffffffffffffff81111561030b575f5ffd5b8201601f8101841361031b575f5ffd5b805167ffffffffffffffff81111561033557610335610277565b61034460208260051b016102b4565b80828252602082019150602060608402850101925086831115610365575f5ffd5b6020840193505b828410156103cb5760608488031215610383575f5ffd5b61038b61028b565b845181526020808601519082015260408501516001600160a01b03811681146103b2575f5ffd5b604082015282526060939093019260209091019061036c565b9695505050505050565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220e3a3d5c6351a6672c40549303836f9e5e504bff16934b1fbde002ea508b2430564736f6c634300081c0033000000000000000000000000542ed7d6f2e4c25f84d9c205c139234d6a4d000d000000000000000000000000a9a145bbe1216c3a9b4b442ab40fd97f4ec2136d

Deployed Bytecode

0x608060405234801561000f575f5ffd5b506004361061003f575f3560e01c8063a13659d514610043578063ab2939fb14610086578063f57a64ae146100ad575b5f5ffd5b61006a7f000000000000000000000000a9a145bbe1216c3a9b4b442ab40fd97f4ec2136d81565b6040516001600160a01b03909116815260200160405180910390f35b61006a7f000000000000000000000000542ed7d6f2e4c25f84d9c205c139234d6a4d000d81565b6100b56100b7565b005b604051633bd73ee360e21b81526001600160a01b037f000000000000000000000000542ed7d6f2e4c25f84d9c205c139234d6a4d000d811660048301525f917f000000000000000000000000a9a145bbe1216c3a9b4b442ab40fd97f4ec2136d9091169063ef5cfb8c906024015f604051808303815f875af115801561013f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261016691908101906102e5565b90505f5b815181101561027357818181518110610185576101856103d5565b60200260200101515f01515f031561026b577f000000000000000000000000542ed7d6f2e4c25f84d9c205c139234d6a4d000d6001600160a01b0316632e953c218383815181106101d8576101d86103d5565b6020026020010151604001518484815181106101f6576101f66103d5565b6020908102919091010151516040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526cffffffffffffffffffffffffff1660248201526044015f604051808303815f87803b158015610254575f5ffd5b505af1158015610266573d5f5f3e3d5ffd5b505050505b60010161016a565b5050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156102ae576102ae610277565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156102dd576102dd610277565b604052919050565b5f602082840312156102f5575f5ffd5b815167ffffffffffffffff81111561030b575f5ffd5b8201601f8101841361031b575f5ffd5b805167ffffffffffffffff81111561033557610335610277565b61034460208260051b016102b4565b80828252602082019150602060608402850101925086831115610365575f5ffd5b6020840193505b828410156103cb5760608488031215610383575f5ffd5b61038b61028b565b845181526020808601519082015260408501516001600160a01b03811681146103b2575f5ffd5b604082015282526060939093019260209091019061036c565b9695505050505050565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220e3a3d5c6351a6672c40549303836f9e5e504bff16934b1fbde002ea508b2430564736f6c634300081c0033

Block Transaction Gas Used Reward
view all blocks ##produced##

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ 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.