| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x3d602d80 | 23699122 | 118 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Minimal Proxy Contract for 0x6e55562d9c3b122f2a17a2179ef22b54ee625c83
Contract Name:
EtfVault
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import "hopium/common/interface/imDirectory.sol";
import "hopium/etf/interface/imEtfRouter.sol";
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function balanceOf(address account) external view returns (uint256);
}
contract TransferHelpers {
error ZeroAmount();
error EthSendFailed();
function _sendEth(address to, uint256 amount) internal {
if (amount == 0) revert ZeroAmount();
(bool ok, ) = payable(to).call{value: amount}("");
if (!ok) revert EthSendFailed();
}
function _sendToken(address tokenAddress, address toAddress, uint256 amount) internal {
if (amount == 0) revert ZeroAmount();
IERC20(tokenAddress).transfer(toAddress, amount);
}
function _sendEthOrToken(address tokenAddress, address toAddress) internal {
if (tokenAddress == address(0)) {
_sendEth(toAddress, address(this).balance);
} else {
_sendToken(tokenAddress, toAddress, IERC20(tokenAddress).balanceOf(address(this)));
}
}
function _recoverAsset(address tokenAddress, address toAddress) internal {
_sendEthOrToken(tokenAddress, toAddress);
}
}
/// @notice Etf Vault implementation (logic). Clones delegatecall into this.
/// @dev Assumes ImEtfRouter -> ImDirectory for access control & Directory wiring.
contract EtfVault is ImEtfRouter, TransferHelpers {
bool private _initialized;
/// @notice Constructor runs once for the implementation only.
/// @dev You can pass an existing Directory here; clones still call initialize().
constructor(address _directory) ImDirectory(_directory) {}
error AlreadyInitialized();
/// @notice One-time initializer for clones (constructors don't run for proxies)
function initialize(address _directory) external {
if (_initialized) revert AlreadyInitialized();
_initialized = true;
_setDirectory(_directory); // from ImDirectory (no modifier)
}
/// @notice Redeem underlying tokens to receiver; callable only by EtfRouter
function redeem(address tokenAddress, uint256 amount, address receiver) external onlyEtfRouter {
_sendToken(tokenAddress, receiver, amount);
}
/// @notice Owner (Directory.owner()) can recover stuck ETH/ERC20
function recoverAsset(address tokenAddress, address toAddress) external onlyOwner {
_recoverAsset(tokenAddress, toAddress);
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import "hopium/common/interface/imDirectory.sol";
interface IEtfRouter {
function mintEtfTokens(uint256 etfId, address receiver, string calldata affiliateCode) external payable;
}
abstract contract ImEtfRouter is ImDirectory {
function getEtfRouter() internal view virtual returns (IEtfRouter) {
return IEtfRouter(fetchFromDirectory("etf-router"));
}
modifier onlyEtfRouter() {
require(msg.sender == fetchFromDirectory("etf-router"), "msg.sender is not etf router");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
/// @notice Interface used by the registry to talk to the external directory.
interface IDirectory {
function owner() external view returns (address);
function fetchFromDirectory(string memory _key) external view returns (address);
}
abstract contract ImDirectory {
IDirectory public Directory;
constructor(address _directory) {
_setDirectory(_directory); // no modifier here
}
function changeDirectoryAddress(address _directory) external onlyOwner {
_setDirectory(_directory);
}
function _setDirectory(address _directory) internal {
require(_directory != address(0), "Directory cannot be zero address");
require(_directory.code.length > 0, "Directory must be a contract");
// Sanity check the interface
try IDirectory(_directory).owner() returns (address) {
Directory = IDirectory(_directory);
} catch {
revert("Directory address does not implement owner()");
}
}
modifier onlyOwner() {
require(msg.sender == Directory.owner(), "Caller is not the owner");
_;
}
function owner() public view returns (address) {
return Directory.owner();
}
function fetchFromDirectory(string memory _key) public view returns (address) {
return Directory.fetchFromDirectory(_key);
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": []
}Contract ABI
API[{"inputs":[{"internalType":"address","name":"_directory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"EthSendFailed","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"inputs":[],"name":"Directory","outputs":[{"internalType":"contract IDirectory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_directory","type":"address"}],"name":"changeDirectoryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_key","type":"string"}],"name":"fetchFromDirectory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_directory","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"toAddress","type":"address"}],"name":"recoverAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.54
Net Worth in ETH
0.000266
Token Allocations
WBTC
38.03%
WETH
32.95%
SOL
29.02%
Multichain Portfolio | 33 Chains
Loading...
Loading
Loading...
Loading
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.