YieldBasisFallbackHandler

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/utils/YieldBasisFallbackHandler.sol": {
      "content": "// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity 0.8.28;

import "@safe-global/safe-smart-account/contracts/handler/HandlerContext.sol";
import "@safe-global/safe-smart-account/contracts/handler/TokenCallbackHandler.sol";

interface IYieldBasisReceiver {
    function onYieldBasisVeReceived(address from) external;
}

/// @title YieldBasisFallbackHandler
/// @notice Token callback handler extended to notify the Yield Basis depositor when the Safe receives a veNFT.
contract YieldBasisFallbackHandler is TokenCallbackHandler, HandlerContext {
    /// @notice Thrown when the depositor callback reverts.
    error DepositorCallFailed(bytes revertData);

    /// @notice Thrown when a zero address is provided.
    error ZeroAddress();

    /// @notice Thrown when the caller is not the Safe.
    error NotSafe();

    /// @notice Thrown when the appended caller is not the ve token contract.
    error NotVeToken();

    /// @notice Address of the Safe contract.
    address public immutable SAFE;

    /// @notice Address of the depositor that should be called on veNFT receptions.
    address public immutable DEPOSITOR;

    /// @notice Address of the Yield Basis voting escrow contract.
    address public immutable VE_TOKEN;

    constructor(address depositor, address veToken, address safe) {
        require(depositor != address(0) && veToken != address(0) && safe != address(0), ZeroAddress());

        DEPOSITOR = depositor;
        VE_TOKEN = veToken;
        SAFE = safe;
    }

    /// @inheritdoc ERC721TokenReceiver
    function onERC721Received(address, address from, uint, bytes calldata)
        external
        override
        returns (bytes4)
    {
        require(msg.sender == SAFE, NotSafe());
        require(_msgSender() == VE_TOKEN, NotVeToken());

        IYieldBasisReceiver(DEPOSITOR).onYieldBasisVeReceived(from);

        return 0x150b7a02;
    }
}
"
    },
    "node_modules/@safe-global/safe-smart-account/contracts/handler/HandlerContext.sol": {
      "content": "// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

/**
 * @title Handler Context - Allows the fallback handler to extract addition context from the calldata
 * @dev The fallback manager appends the following context to the calldata:
 *      1. Fallback manager caller address (non-padded)
 * based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/f8cc8b844a9f92f63dc55aa581f7d643a1bc5ac1/contracts/metatx/ERC2771Context.sol
 * @author Richard Meissner - @rmeissner
 */
abstract contract HandlerContext {
    /**
     * @notice Allows fetching the original caller address.
     * @dev This is only reliable in combination with a FallbackManager that supports this (e.g. Safe contract >=1.3.0).
     *      When using this functionality make sure that the linked _manager (aka msg.sender) supports this.
     *      This function does not rely on a trusted forwarder. Use the returned value only to
     *      check information against the calling manager.
     * @return sender Original caller address.
     */
    function _msgSender() internal pure returns (address sender) {
        // The assembly code is more direct than the Solidity version using `abi.decode`.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            sender := shr(96, calldataload(sub(calldatasize(), 20)))
        }
    }

    /**
     * @notice Returns the FallbackManager address
     * @return Fallback manager address
     */
    function _manager() internal view returns (address) {
        return msg.sender;
    }
}
"
    },
    "node_modules/@safe-global/safe-smart-account/contracts/handler/TokenCallbackHandler.sol": {
      "content": "// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

import "../interfaces/ERC1155TokenReceiver.sol";
import "../interfaces/ERC721TokenReceiver.sol";
import "../interfaces/ERC777TokensRecipient.sol";
import "../interfaces/IERC165.sol";

/**
 * @title Default Callback Handler - Handles supported tokens' callbacks, allowing Safes receiving these tokens.
 * @author Richard Meissner - @rmeissner
 */
contract TokenCallbackHandler is ERC1155TokenReceiver, ERC777TokensRecipient, ERC721TokenReceiver, IERC165 {
    /**
     * @notice Handles ERC1155 Token callback.
     * return Standardized onERC1155Received return value.
     */
    function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure override returns (bytes4) {
        return 0xf23a6e61;
    }

    /**
     * @notice Handles ERC1155 Token batch callback.
     * return Standardized onERC1155BatchReceived return value.
     */
    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) external pure override returns (bytes4) {
        return 0xbc197c81;
    }

    /**
     * @notice Handles ERC721 Token callback.
     *  return Standardized onERC721Received return value.
     */
    function onERC721Received(address, address, uint256, bytes calldata)
        external
        virtual
        override
        returns (bytes4)
    {
        return 0x150b7a02;
    }

    /**
     * @notice Handles ERC777 Token callback.
     * return nothing (not standardized)
     */
    function tokensReceived(address, address, address, uint256, bytes calldata, bytes calldata) external pure override {
        // We implement this for completeness, doesn't really have any value
    }

    /**
     * @notice Implements ERC165 interface support for ERC1155TokenReceiver, ERC721TokenReceiver and IERC165.
     * @param interfaceId Id of the interface.
     * @return if the interface is supported.
     */
    function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {
        return
            interfaceId == type(ERC1155TokenReceiver).interfaceId ||
            interfaceId == type(ERC721TokenReceiver).interfaceId ||
            interfaceId == type(IERC165).interfaceId;
    }
}
"
    },
    "node_modules/@safe-global/safe-smart-account/contracts/interfaces/ERC1155TokenReceiver.sol": {
      "content": "// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

// Note: The ERC-165 identifier for this interface is 0x4e2312e0.
interface ERC1155TokenReceiver {
    /**
     * @notice Handle the receipt of a single ERC1155 token type.
     * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.
     *      This function MUST return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61) if it accepts the transfer.
     *      This function MUST revert if it rejects the transfer.
     *      Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
     * @param _operator  The address which initiated the transfer (i.e. msg.sender).
     * @param _from      The address which previously owned the token.
     * @param _id        The ID of the token being transferred.
     * @param _value     The amount of tokens being transferred.
     * @param _data      Additional data with no specified format.
     * @return           `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`.
     */
    function onERC1155Received(
        address _operator,
        address _from,
        uint256 _id,
        uint256 _value,
        bytes calldata _data
    ) external returns (bytes4);

    /**
     * @notice Handle the receipt of multiple ERC1155 token types.
     * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.
     *      This function MUST return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81) if it accepts the transfer(s).
     *      This function MUST revert if it rejects the transfer(s).
     *      Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
     * @param _operator  The address which initiated the batch transfer (i.e. msg.sender).
     * @param _from      The address which previously owned the token.
     * @param _ids       An array containing ids of each token being transferred (order and length must match _values array).
     * @param _values    An array containing amounts of each token being transferred (order and length must match _ids array).
     * @param _data      Additional data with no specified format.
     * @return           `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`.
     */
    function onERC1155BatchReceived(
        address _operator,
        address _from,
        uint256[] calldata _ids,
        uint256[] calldata _values,
        bytes calldata _data
    ) external returns (bytes4);
}
"
    },
    "node_modules/@safe-global/safe-smart-account/contracts/interfaces/ERC721TokenReceiver.sol": {
      "content": "// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface ERC721TokenReceiver {
    /**
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     *  after a `transfer`. This function MAY throw to revert and reject the
     *  transfer. Return of other than the magic value MUST result in the
     *  transaction being reverted.
     *  Note: the contract address is always the message sender.
     * @param _operator The address which called `safeTransferFrom` function.
     * @param _from The address which previously owned the token.
     * @param _tokenId The NFT identifier which is being transferred.
     * @param _data Additional data with no specified format.
     * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
     *  unless throwing
     */
    function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns (bytes4);
}
"
    },
    "node_modules/@safe-global/safe-smart-account/contracts/interfaces/ERC777TokensRecipient.sol": {
      "content": "// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

/**
 * @title ERC777TokensRecipient
 * @dev Interface for contracts that will be called with the ERC777 token's `tokensReceived` method.
 * The contract receiving the tokens must implement this interface in order to receive the tokens.
 */
interface ERC777TokensRecipient {
    /**
     * @dev Called by the ERC777 token contract after a successful transfer or a minting operation.
     * @param operator The address of the operator performing the transfer or minting operation.
     * @param from The address of the sender.
     * @param to The address of the recipient.
     * @param amount The amount of tokens that were transferred or minted.
     * @param data Additional data that was passed during the transfer or minting operation.
     * @param operatorData Additional data that was passed by the operator during the transfer or minting operation.
     */
    function tokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;
}
"
    },
    "node_modules/@safe-global/safe-smart-account/contracts/interfaces/IERC165.sol": {
      "content": "// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

/// @notice More details at https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by `interfaceId`.
     * See the corresponding EIP section
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
"
    }
  },
  "settings": {
    "remappings": [
      "forge-std/=node_modules/forge-std/",
      "@common/=node_modules/@stake-dao/interfaces/src/",
      "@address-book/=node_modules/@stake-dao/address-book/",
      "@interfaces/=node_modules/@stake-dao/interfaces/src/interfaces/",
      "@shared/=node_modules/@stake-dao/shared/",
      "solady/=node_modules/@solady/",
      "@safe/=node_modules/@safe-global/safe-smart-account/",
      "@layerzerolabs/oapp-evm/=node_modules/@layerzerolabs/oapp-evm/",
      "@layerzerolabs/lz-evm-protocol-v2/=node_modules/@layerzerolabs/lz-evm-protocol-v2/",
      "@layerzerolabs/oft-evm/=node_modules/@layerzerolabs/oft-evm/",
      "@pendle/v2-sy/=node_modules/@pendle/v2-sy/contracts/core/",
      "node_modules/@pendle/v2-sy/:@openzeppelin/contracts/=node_modules/@openzeppelin/contracts-v4/",
      "node_modules/@pendle/v2-sy/:@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable-v4/",
      "@aladdin/=node_modules/aladdin-v3-contracts/contracts/",
      "node_modules/aladdin-v3-contracts:@openzeppelin/contracts-upgradeable-v4/=node_modules/@openzeppelin/contracts-upgradeable-v4/",
      "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
      "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/",
      "@safe-global/=node_modules/@safe-global/",
      "@solady/=node_modules/@solady/",
      "aladdin-v3-contracts/=node_modules/aladdin-v3-contracts/",
      "murky/=node_modules/murky/"
    ],
    "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
  }
}}

Tags:
ERC165, Proxy, Yield, Upgradeable, Factory|addr:0x325229508513d484a90f3618e6aca8a9fb808ea9|verified:true|block:23726390|tx:0x88c3331c93f97a3ef20e35c88549474eef89e355e9df6ad06762230e037ed580|first_check:1762268217

Submitted on: 2025-11-04 15:56:59

Comments

Log in to comment.

No comments yet.