ETH Price: $1,963.63 (-4.64%)
 

Overview

ETH Balance

0 ETH

ETH 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

Parent Transaction Hash Block From To
308343572025-05-28 18:47:41263 days ago1748458061  Contract Creation0 ETH

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TransferBlacklistHook

Compiler Version
v0.8.29+commit.ab55807c

Optimization Enabled:
Yes with 100000 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.29;

import { IChainalysisSanctionsOracle } from "src/dependencies/chainalysis/IChainalysisSanctionsOracle.sol";

import { AbstractTransferHook } from "src/periphery/hooks/transfer/AbstractTransferHook.sol";

import { IBeforeTransferHook } from "src/core/interfaces/IBeforeTransferHook.sol";
import { ITransferBlacklistHook } from "src/periphery/interfaces/hooks/transfer/ITransferBlacklistHook.sol";

/// @title TransferBlacklistHook
/// @notice Blocks users on a blacklist from transfering vault units in multi-depositor vaults
contract TransferBlacklistHook is AbstractTransferHook, ITransferBlacklistHook {
    ////////////////////////////////////////////////////////////
    //                       Immutables                       //
    ////////////////////////////////////////////////////////////

    /// @notice The blacklist oracle (using Chainalysis sanctions oracle interface)
    IChainalysisSanctionsOracle public immutable BLACKLIST_ORACLE;

    constructor(IChainalysisSanctionsOracle oracle_) {
        // Requirements: check that the oracle is not the zero address
        require(address(oracle_) != address(0), AeraPeriphery__ZeroAddressBlacklistOracle());

        // Effects: set the blacklist oracle
        BLACKLIST_ORACLE = oracle_;
    }

    ////////////////////////////////////////////////////////////
    //              Public / External Functions               //
    ////////////////////////////////////////////////////////////

    /// @inheritdoc IBeforeTransferHook
    function beforeTransfer(address from, address to, address transferAgent)
        public
        view
        override(AbstractTransferHook, IBeforeTransferHook)
    {
        super.beforeTransfer(from, to, transferAgent);

        // Check that the `from` and `to` addresses are not sanctioned
        require(from == address(0) || !BLACKLIST_ORACLE.isSanctioned(from), AeraPeriphery__BlacklistedAddress(from));
        require(to == address(0) || !BLACKLIST_ORACLE.isSanctioned(to), AeraPeriphery__BlacklistedAddress(to));
    }
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.29;

interface IChainalysisSanctionsOracle {
    ////////////////////////////////////////////////////////////
    //                       Functions                        //
    ////////////////////////////////////////////////////////////

    /// @notice Check if an account is sanctioned
    /// @param account The account to check
    /// @return True if the account is sanctioned, false otherwise
    function isSanctioned(address account) external view returns (bool);
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.29;

import { VaultAuth } from "src/core/VaultAuth.sol";

import { IBeforeTransferHook } from "src/core/interfaces/IBeforeTransferHook.sol";

/// @title IBeforeTransferHook
/// @notice Used in multi-depositor vaults to control whether vault units can be transfered
/// Provides default functionality to disable unit transfers all together for all implementations
abstract contract AbstractTransferHook is IBeforeTransferHook, VaultAuth {
    ////////////////////////////////////////////////////////////
    //                        Storage                         //
    ////////////////////////////////////////////////////////////

    /// @notice Whether the vault units are transferable
    mapping(address vault => bool isVaultUnitTransferable) public isVaultUnitTransferable;

    ////////////////////////////////////////////////////////////
    //              Public / External Functions               //
    ////////////////////////////////////////////////////////////

    /// @inheritdoc IBeforeTransferHook
    function setIsVaultUnitsTransferable(address vault, bool isTransferable) external requiresVaultAuth(vault) {
        _setIsVaultUnitsTransferable(vault, isTransferable);
    }

    /// @inheritdoc IBeforeTransferHook
    function beforeTransfer(address from, address to, address transferAgent) public view virtual {
        if (from != transferAgent && to != transferAgent && from != address(0) && to != address(0)) {
            // Check that the vault units are transferable, if the operation is not mint/burn
            require(isVaultUnitTransferable[msg.sender], Aera__VaultUnitsNotTransferable(msg.sender));
        }
    }

    ////////////////////////////////////////////////////////////
    //              Private / Internal Functions              //
    ////////////////////////////////////////////////////////////

    /// @notice Set the vault unit transferable status
    /// @param vault The vault to set the transferable status for
    /// @param isTransferable Whether the vault units are transferable
    function _setIsVaultUnitsTransferable(address vault, bool isTransferable) internal {
        // Effects: set the vault unit transferable status
        isVaultUnitTransferable[vault] = isTransferable;

        // Log the vault unit transferable status set
        emit VaultUnitTransferableSet(vault, isTransferable);
    }
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.29;

/// @title IBeforeTransferHook
/// @notice Interface for token transfer hooks used for vault units in multi-depositor vaults
interface IBeforeTransferHook {
    ////////////////////////////////////////////////////////////
    //                         Events                         //
    ////////////////////////////////////////////////////////////

    event VaultUnitTransferableSet(address indexed vault, bool isTransferable);

    ////////////////////////////////////////////////////////////
    //                         Errors                         //
    ////////////////////////////////////////////////////////////

    error Aera__NotVaultOwner();
    error Aera__VaultUnitsNotTransferable(address vault);

    ////////////////////////////////////////////////////////////
    //                       Functions                        //
    ////////////////////////////////////////////////////////////

    /// @notice Set whether vault units should be transferable
    /// @param vault The vault to update status for
    /// @param isTransferable Whether the vault units are transferable
    function setIsVaultUnitsTransferable(address vault, bool isTransferable) external;

    /// @notice Perform before transfer checks
    /// @param from Address that is sending the units
    /// @param to Address that is receiving the units
    /// @param transferAgent Address that is always allowed to transfer the units
    function beforeTransfer(address from, address to, address transferAgent) external view;
}

File 5 of 7 : ITransferBlacklistHook.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.29;

import { IBeforeTransferHook } from "src/core/interfaces/IBeforeTransferHook.sol";

/// @title ITransferBlacklistHook
/// @notice Errors used in the transfer blacklist hook
interface ITransferBlacklistHook is IBeforeTransferHook {
    ////////////////////////////////////////////////////////////
    //                         Errors                         //
    ////////////////////////////////////////////////////////////

    error AeraPeriphery__BlacklistedAddress(address address_);
    error AeraPeriphery__ZeroAddressBlacklistOracle();
}

File 6 of 7 : VaultAuth.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.29;

import { Auth } from "@solmate/auth/Auth.sol";

/// @title VaultAuth
/// @notice Abstract contract that provides authorization check for vault operations
/// @dev Used by contracts that need to verify if a caller has permission to perform vault-specific actions. The
/// authorization can come from either being the vault owner or having explicit permission through the vault's authority
abstract contract VaultAuth {
    ////////////////////////////////////////////////////////////
    //                        Errors                          //
    ////////////////////////////////////////////////////////////

    error Aera__CallerIsNotAuthorized();

    ////////////////////////////////////////////////////////////
    //                       Modifiers                        //
    ////////////////////////////////////////////////////////////

    modifier requiresVaultAuth(address vault) {
        // Requirements: check that the caller is either the vault owner or has permission to call the function
        require(
            msg.sender == Auth(vault).owner() || Auth(vault).authority().canCall(msg.sender, address(this), msg.sig),
            Aera__CallerIsNotAuthorized()
        );
        _;
    }
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.29;

/// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
abstract contract Auth {
    event OwnershipTransferred(address indexed user, address indexed newOwner);

    event AuthorityUpdated(address indexed user, Authority indexed newAuthority);

    address public owner;

    Authority public authority;

    constructor(address _owner, Authority _authority) {
        owner = _owner;
        authority = _authority;

        emit OwnershipTransferred(msg.sender, _owner);
        emit AuthorityUpdated(msg.sender, _authority);
    }

    modifier requiresAuth() virtual {
        require(isAuthorized(msg.sender, msg.sig), "UNAUTHORIZED");

        _;
    }

    function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) {
        Authority auth = authority; // Memoizing authority saves us a warm SLOAD, around 100 gas.

        // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be
        // aware that this makes protected functions uncallable even to the owner if the authority is out of order.
        return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) || user == owner;
    }

    function setAuthority(Authority newAuthority) public virtual {
        // We check if the caller is the owner first because we want to ensure they can
        // always swap out the authority even if it's reverting or using up a lot of gas.
        require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig));

        authority = newAuthority;

        emit AuthorityUpdated(msg.sender, newAuthority);
    }

    function transferOwnership(address newOwner) public virtual requiresAuth {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

/// @notice A generic interface for a contract which provides authorization data to an Auth instance.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
interface Authority {
    function canCall(address user, address target, bytes4 functionSig) external view returns (bool);
}

Settings
{
  "remappings": [
    "@oz/=lib/openzeppelin-contracts/contracts/",
    "@solmate/=src/dependencies/solmate/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 100000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IChainalysisSanctionsOracle","name":"oracle_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"address_","type":"address"}],"name":"AeraPeriphery__BlacklistedAddress","type":"error"},{"inputs":[],"name":"AeraPeriphery__ZeroAddressBlacklistOracle","type":"error"},{"inputs":[],"name":"Aera__CallerIsNotAuthorized","type":"error"},{"inputs":[],"name":"Aera__NotVaultOwner","type":"error"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"Aera__VaultUnitsNotTransferable","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"bool","name":"isTransferable","type":"bool"}],"name":"VaultUnitTransferableSet","type":"event"},{"inputs":[],"name":"BLACKLIST_ORACLE","outputs":[{"internalType":"contract IChainalysisSanctionsOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"transferAgent","type":"address"}],"name":"beforeTransfer","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"isVaultUnitTransferable","outputs":[{"internalType":"bool","name":"isVaultUnitTransferable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"bool","name":"isTransferable","type":"bool"}],"name":"setIsVaultUnitsTransferable","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a03461008c57601f61086938819003918201601f19168301916001600160401b038311848410176100905780849260209460405283398101031261008c57516001600160a01b03811680820361008c571561007d576080526040516107c490816100a582396080518181816095015281816101df015261029d0152f35b6308e7625f60e11b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f35908160e01c91826370598155146103b957505080638359b8d214610352578063abd626b0146100bd5763bb923cec1461004b575f80fd5b346100b9575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100b957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5f80fd5b346100b95760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100b9576100f46106c4565b60243573ffffffffffffffffffffffffffffffffffffffff8116918282036100b9576044359073ffffffffffffffffffffffffffffffffffffffff82168092036100b95773ffffffffffffffffffffffffffffffffffffffff811691808314159081610347575b508061033e575b80610335575b6102f6575b81158015610253575b610180925061076d565b81158015610195575b610193925061076d565b005b50604051917fdf592f7d000000000000000000000000000000000000000000000000000000008352600483015260208260248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa801561024857610193925f91610219575b5015610189565b61023b915060203d602011610241575b61023381836106e7565b810190610755565b83610212565b503d610229565b6040513d5f823e3d90fd5b50604051917fdf592f7d000000000000000000000000000000000000000000000000000000008352600483015260208260248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa801561024857610180925f916102d7575b5015610176565b6102f0915060203d6020116102415761023381836106e7565b856102d0565b335f525f60205260ff60405f20541661016d577f817720f8000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b50831515610168565b50811515610162565b90508414158561015b565b346100b95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100b95773ffffffffffffffffffffffffffffffffffffffff61039e6106c4565b165f525f602052602060ff60405f2054166040519015158152f35b346100b95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100b9576103f06106c4565b90602435918215158093036100b95773ffffffffffffffffffffffffffffffffffffffff16927f8da5cb5b000000000000000000000000000000000000000000000000000000008152602081600481875afa8015610248575f90610661575b73ffffffffffffffffffffffffffffffffffffffff9150163314908115610501575b50156104d95760207fce2308ee613bae165226bc87fea41850f1fd4e8c07f19e7015e46017c9cb3a8c91835f525f825260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff8316179055604051908152a2005b7f5a4f9775000000000000000000000000000000000000000000000000000000005f5260045ffd5b6040517fbf7e214f0000000000000000000000000000000000000000000000000000000081529150602082600481875afa918215610248575f926105f0575b507fffffffff00000000000000000000000000000000000000000000000000000000606460209273ffffffffffffffffffffffffffffffffffffffff60405195869485937fb7009613000000000000000000000000000000000000000000000000000000008552336004860152306024860152166044840152165afa908115610248575f916105d1575b5083610471565b6105ea915060203d6020116102415761023381836106e7565b836105ca565b9091506020813d602011610659575b8161060c602093836106e7565b810103126100b9575173ffffffffffffffffffffffffffffffffffffffff811681036100b957907fffffffff00000000000000000000000000000000000000000000000000000000610540565b3d91506105ff565b506020813d6020116106bc575b8161067b602093836106e7565b810103126100b9575173ffffffffffffffffffffffffffffffffffffffff811681036100b95773ffffffffffffffffffffffffffffffffffffffff9061044f565b3d915061066e565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036100b957565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761072857604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b908160209103126100b9575180151581036100b95790565b156107755750565b73ffffffffffffffffffffffffffffffffffffffff907f0562fa43000000000000000000000000000000000000000000000000000000005f521660045260245ffdfea164736f6c634300081d000a0000000000000000000000003a91a31cb3dc49b4db9ce721f50a9d076c8d739b

Deployed Bytecode

0x6080806040526004361015610012575f80fd5b5f35908160e01c91826370598155146103b957505080638359b8d214610352578063abd626b0146100bd5763bb923cec1461004b575f80fd5b346100b9575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100b957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003a91a31cb3dc49b4db9ce721f50a9d076c8d739b168152f35b5f80fd5b346100b95760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100b9576100f46106c4565b60243573ffffffffffffffffffffffffffffffffffffffff8116918282036100b9576044359073ffffffffffffffffffffffffffffffffffffffff82168092036100b95773ffffffffffffffffffffffffffffffffffffffff811691808314159081610347575b508061033e575b80610335575b6102f6575b81158015610253575b610180925061076d565b81158015610195575b610193925061076d565b005b50604051917fdf592f7d000000000000000000000000000000000000000000000000000000008352600483015260208260248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003a91a31cb3dc49b4db9ce721f50a9d076c8d739b165afa801561024857610193925f91610219575b5015610189565b61023b915060203d602011610241575b61023381836106e7565b810190610755565b83610212565b503d610229565b6040513d5f823e3d90fd5b50604051917fdf592f7d000000000000000000000000000000000000000000000000000000008352600483015260208260248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003a91a31cb3dc49b4db9ce721f50a9d076c8d739b165afa801561024857610180925f916102d7575b5015610176565b6102f0915060203d6020116102415761023381836106e7565b856102d0565b335f525f60205260ff60405f20541661016d577f817720f8000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b50831515610168565b50811515610162565b90508414158561015b565b346100b95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100b95773ffffffffffffffffffffffffffffffffffffffff61039e6106c4565b165f525f602052602060ff60405f2054166040519015158152f35b346100b95760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100b9576103f06106c4565b90602435918215158093036100b95773ffffffffffffffffffffffffffffffffffffffff16927f8da5cb5b000000000000000000000000000000000000000000000000000000008152602081600481875afa8015610248575f90610661575b73ffffffffffffffffffffffffffffffffffffffff9150163314908115610501575b50156104d95760207fce2308ee613bae165226bc87fea41850f1fd4e8c07f19e7015e46017c9cb3a8c91835f525f825260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541660ff8316179055604051908152a2005b7f5a4f9775000000000000000000000000000000000000000000000000000000005f5260045ffd5b6040517fbf7e214f0000000000000000000000000000000000000000000000000000000081529150602082600481875afa918215610248575f926105f0575b507fffffffff00000000000000000000000000000000000000000000000000000000606460209273ffffffffffffffffffffffffffffffffffffffff60405195869485937fb7009613000000000000000000000000000000000000000000000000000000008552336004860152306024860152166044840152165afa908115610248575f916105d1575b5083610471565b6105ea915060203d6020116102415761023381836106e7565b836105ca565b9091506020813d602011610659575b8161060c602093836106e7565b810103126100b9575173ffffffffffffffffffffffffffffffffffffffff811681036100b957907fffffffff00000000000000000000000000000000000000000000000000000000610540565b3d91506105ff565b506020813d6020116106bc575b8161067b602093836106e7565b810103126100b9575173ffffffffffffffffffffffffffffffffffffffff811681036100b95773ffffffffffffffffffffffffffffffffffffffff9061044f565b3d915061066e565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036100b957565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761072857604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b908160209103126100b9575180151581036100b95790565b156107755750565b73ffffffffffffffffffffffffffffffffffffffff907f0562fa43000000000000000000000000000000000000000000000000000000005f521660045260245ffdfea164736f6c634300081d000a

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000003a91a31cb3dc49b4db9ce721f50a9d076c8d739b

-----Decoded View---------------
Arg [0] : oracle_ (address): 0x3A91A31cB3dC49b4db9Ce721F50a9D076c8D739B

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000003a91a31cb3dc49b4db9ce721f50a9d076c8d739b


Block Transaction Difficulty 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.