Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
17841588 | 461 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Minimal Proxy Contract for 0xfe87400c401c0cb61ec3a923a5d9873090e8dafc
Contract Name:
PassThroughWalletImpl
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {PausableImpl} from "splits-utils/PausableImpl.sol"; import {TokenUtils} from "splits-utils/TokenUtils.sol"; import {WalletImpl} from "splits-utils/WalletImpl.sol"; /// @title Pass-Through Wallet Implementation /// @author 0xSplits /// @notice A clone-implementation of a pass-through wallet. /// Please be aware, owner has _FULL CONTROL_ of the deployment. /// @dev This contract uses token = address(0) to refer to ETH. contract PassThroughWalletImpl is WalletImpl, PausableImpl { /// ----------------------------------------------------------------------- /// libraries /// ----------------------------------------------------------------------- using TokenUtils for address; /// ----------------------------------------------------------------------- /// structs /// ----------------------------------------------------------------------- struct InitParams { address owner; bool paused; address passThrough; } /// ----------------------------------------------------------------------- /// events /// ----------------------------------------------------------------------- event SetPassThrough(address passThrough); event PassThrough(address indexed passThrough, address[] tokens, uint256[] amounts); // emitted in clone bytecode event ReceiveETH(uint256 amount); /// ----------------------------------------------------------------------- /// storage /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// storage - constants & immutables /// ----------------------------------------------------------------------- address public immutable passThroughWalletFactory; /// ----------------------------------------------------------------------- /// storage - mutables /// ----------------------------------------------------------------------- /// slot 0 - 11 bytes free /// OwnableImpl storage /// address internal $owner; /// 20 bytes /// PausableImpl storage /// bool internal $paused; /// 1 byte /// slot 1 - 12 bytes free /// address to pass-through funds to address internal $passThrough; /// 20 bytes /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- constructor() { passThroughWalletFactory = msg.sender; } function initializer(InitParams calldata params_) external { // only passThroughWalletFactory may call `initializer` if (msg.sender != passThroughWalletFactory) revert Unauthorized(); // don't need to init wallet separately __initPausable({owner_: params_.owner, paused_: params_.paused}); $passThrough = params_.passThrough; } /// ----------------------------------------------------------------------- /// functions /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// functions - public & external - onlyOwner /// ----------------------------------------------------------------------- /// set passThrough function setPassThrough(address passThrough_) external onlyOwner { $passThrough = passThrough_; emit SetPassThrough(passThrough_); } /// ----------------------------------------------------------------------- /// functions - public & external - view /// ----------------------------------------------------------------------- function passThrough() external view returns (address) { return $passThrough; } /// ----------------------------------------------------------------------- /// functions - public & external - permissionless /// ----------------------------------------------------------------------- /// emit event when receiving ETH /// @dev implemented w/i clone bytecode /* receive() external payable { */ /* emit ReceiveETH(msg.value); */ /* } */ /// send `tokens_` to `$passThrough` function passThroughTokens(address[] calldata tokens_) external pausable returns (uint256[] memory amounts) { address _passThrough = $passThrough; uint256 length = tokens_.length; amounts = new uint256[](length); for (uint256 i; i < length;) { address token = tokens_[i]; uint256 amount = token._balanceOf(address(this)); amounts[i] = amount; token._safeTransfer(_passThrough, amount); unchecked { ++i; } } emit PassThrough(_passThrough, tokens_, amounts); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {OwnableImpl} from "./OwnableImpl.sol"; /// @title Pausable Implementation /// @author 0xSplits /// @notice Pausable clone-implementation abstract contract PausableImpl is OwnableImpl { error Paused(); event SetPaused(bool paused); /// ----------------------------------------------------------------------- /// storage - mutables /// ----------------------------------------------------------------------- /// slot 0 - 11 bytes free /// OwnableImpl storage /// address internal $owner; /// 20 bytes bool internal $paused; /// 1 byte /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- constructor() {} function __initPausable(address owner_, bool paused_) internal virtual { OwnableImpl.__initOwnable(owner_); $paused = paused_; } /// ----------------------------------------------------------------------- /// modifiers /// ----------------------------------------------------------------------- modifier pausable() virtual { if (paused()) revert Paused(); _; } /// ----------------------------------------------------------------------- /// functions - public & external - onlyOwner /// ----------------------------------------------------------------------- function setPaused(bool paused_) public virtual onlyOwner { $paused = paused_; emit SetPaused(paused_); } /// ----------------------------------------------------------------------- /// functions - public & external - view /// ----------------------------------------------------------------------- function paused() public view virtual returns (bool) { return $paused; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol"; /// Library to handle basic token functions for ERC20s & ETH (represented by 0x0) library TokenUtils { using SafeTransferLib for address; address internal constant ETH_ADDRESS = address(0); function _isETH(address token) internal pure returns (bool) { return (token == ETH_ADDRESS); } function _decimals(address token) internal view returns (uint8) { return _isETH(token) ? 18 : ERC20(token).decimals(); } function _balanceOf(address token, address addr) internal view returns (uint256) { return _isETH(token) ? addr.balance : ERC20(token).balanceOf(addr); } function _safeTransfer(address token, address addr, uint256 amount) internal { if (_isETH(token)) addr.safeTransferETH(amount); else token.safeTransfer(addr, amount); } } interface ERC20 { function decimals() external view returns (uint8); function balanceOf(address addr) external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {ERC1155TokenReceiver} from "solmate/tokens/ERC1155.sol"; import {ERC721TokenReceiver} from "solmate/tokens/ERC721.sol"; import {OwnableImpl} from "./OwnableImpl.sol"; /// @title Wallet Implementation /// @author 0xSplits /// @notice Minimal smart wallet clone-implementation abstract contract WalletImpl is OwnableImpl, ERC721TokenReceiver, ERC1155TokenReceiver { struct Call { address to; uint256 value; bytes data; } event ExecCalls(Call[] calls); /// ----------------------------------------------------------------------- /// storage - mutables /// ----------------------------------------------------------------------- /// slot 0 - 12 bytes free /// OwnableImpl storage /// address internal $owner; /// 20 bytes /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- constructor() {} function __initWallet(address owner_) internal { OwnableImpl.__initOwnable(owner_); } /// ----------------------------------------------------------------------- /// functions - external & public - onlyOwner /// ----------------------------------------------------------------------- /// allow owner to execute arbitrary calls function execCalls(Call[] calldata calls_) external payable onlyOwner returns (uint256 blockNumber, bytes[] memory returnData) { blockNumber = block.number; uint256 length = calls_.length; returnData = new bytes[](length); bool success; for (uint256 i; i < length;) { Call calldata calli = calls_[i]; (success, returnData[i]) = calli.to.call{value: calli.value}(calli.data); require(success, string(returnData[i])); unchecked { ++i; } } emit ExecCalls(calls_); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; /// @title Ownable Implementation /// @author 0xSplits /// @notice Ownable clone-implementation abstract contract OwnableImpl { error Unauthorized(); event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// ----------------------------------------------------------------------- /// storage - mutables /// ----------------------------------------------------------------------- /// slot 0 - 12 bytes free address internal $owner; /// 20 bytes /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- constructor() {} function __initOwnable(address owner_) internal virtual { emit OwnershipTransferred(address(0), owner_); $owner = owner_; } /// ----------------------------------------------------------------------- /// modifiers /// ----------------------------------------------------------------------- modifier onlyOwner() virtual { if (msg.sender != owner()) revert Unauthorized(); _; } /// ----------------------------------------------------------------------- /// functions - public & external - onlyOwner /// ----------------------------------------------------------------------- function transferOwnership(address owner_) public virtual onlyOwner { $owner = owner_; emit OwnershipTransferred(msg.sender, owner_); } /// ----------------------------------------------------------------------- /// functions - public & external - view /// ----------------------------------------------------------------------- function owner() public view virtual returns (address) { return $owner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller. library SafeTransferLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Suggested gas stipend for contract receiving ETH /// that disallows any storage writes. uint256 internal constant _GAS_STIPEND_NO_STORAGE_WRITES = 2300; /// @dev Suggested gas stipend for contract receiving ETH to perform a few /// storage reads and writes, but low enough to prevent griefing. /// Multiply by a small constant (e.g. 2), if needed. uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` (in wei) ETH to `to`. /// Reverts upon failure. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { // Transfer the ETH and check if it succeeded or not. if iszero(call(gas(), to, amount, 0, 0, 0, 0)) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. /// The `gasStipend` can be set to a low enough value to prevent /// storage writes or gas griefing. /// /// If sending via the normal procedure fails, force sends the ETH by /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH. /// /// Reverts if the current contract has insufficient balance. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { // If insufficient balance, revert. if lt(selfbalance(), amount) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } // Transfer the ETH and check if it succeeded or not. if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. // We can directly use `SELFDESTRUCT` in the contract creation. // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758 if iszero(create(amount, 0x0b, 0x16)) { revert(0, 0) } // For better gas estimation. } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend /// equal to `_GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default /// for 99% of cases and can be overriden with the three-argument version of this /// function if necessary. /// /// If sending via the normal procedure fails, force sends the ETH by /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH. /// /// Reverts if the current contract has insufficient balance. function forceSafeTransferETH(address to, uint256 amount) internal { // Manually inlined because the compiler doesn't inline functions with branches. /// @solidity memory-safe-assembly assembly { // If insufficient balance, revert. if lt(selfbalance(), amount) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } // Transfer the ETH and check if it succeeded or not. if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. // We can directly use `SELFDESTRUCT` in the contract creation. // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758 if iszero(create(amount, 0x0b, 0x16)) { revert(0, 0) } // For better gas estimation. } } } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. /// The `gasStipend` can be set to a low enough value to prevent /// storage writes or gas griefing. /// /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend. /// /// Note: Does NOT revert upon failure. /// Returns whether the transfer of ETH is successful instead. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { // Transfer the ETH and check if it succeeded or not. success := call(gasStipend, to, amount, 0, 0, 0, 0) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. // Store the function selector of `transferFrom(address,address,uint256)`. mstore(0x00, 0x23b872dd) mstore(0x20, from) // Store the `from` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x60, amount) // Store the `amount` argument. if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends all of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, from) // Store the `from` argument. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } // Store the function selector of `transferFrom(address,address,uint256)`. mstore(0x00, 0x23b872dd) mstore(0x40, to) // Store the `to` argument. // The `amount` argument is already written to the memory word at 0x6a. amount := mload(0x60) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransfer(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x1a, to) // Store the `to` argument. mstore(0x3a, amount) // Store the `amount` argument. // Store the function selector of `transfer(address,uint256)`, // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer). // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL). mstore(0x00, 0xa9059cbb000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, if less than 8tb of memory is used. mstore(0x3a, 0) } } /// @dev Sends all of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransferAll(address token, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, address()) // Store the address of the current contract. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x3a, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x1a, to) // Store the `to` argument. // The `amount` argument is already written to the memory word at 0x3a. amount := mload(0x3a) // Store the function selector of `transfer(address,uint256)`, // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer). // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL). mstore(0x00, 0xa9059cbb000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, if less than 8tb of memory is used. mstore(0x3a, 0) } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// Reverts upon failure. function safeApprove(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x1a, to) // Store the `to` argument. mstore(0x3a, amount) // Store the `amount` argument. // Store the function selector of `approve(address,uint256)`, // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer). // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL). mstore(0x00, 0x095ea7b3000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `ApproveFailed()`. mstore(0x00, 0x3e3f8f73) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, if less than 8tb of memory is used. mstore(0x3a, 0) } } /// @dev Returns the amount of ERC20 `token` owned by `account`. /// Returns zero if the `token` does not exist. function balanceOf(address token, address account) internal view returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, account) // Store the `account` argument. amount := mul( mload(0x20), and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x20, 0x20) ) ) } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Minimalist and gas efficient standard ERC1155 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); /*////////////////////////////////////////////////////////////// ERC1155 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// METADATA LOGIC //////////////////////////////////////////////////////////////*/ function uri(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC1155 LOGIC //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; for (uint256 i = 0; i < ids.length; ) { id = ids[i]; amount = amounts[i]; balanceOf[from][id] -= amount; balanceOf[to][id] += amount; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { require(owners.length == ids.length, "LENGTH_MISMATCH"); balances = new uint256[](owners.length); // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < owners.length; ++i) { balances[i] = balanceOf[owners[i]][ids[i]]; } } } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[to][ids[i]] += amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, address(0), to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function _batchBurn( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[from][ids[i]] -= amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, address(0), ids, amounts); } function _burn( address from, uint256 id, uint256 amount ) internal virtual { balanceOf[from][id] -= amount; emit TransferSingle(msg.sender, from, address(0), id, amount); } } /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155TokenReceiver { function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solady/=lib/splits-utils/lib/solady/src/", "solmate/=lib/splits-utils/lib/solmate/src/", "splits-tests/=lib/splits-utils/test/", "splits-utils/=lib/splits-utils/src/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct WalletImpl.Call[]","name":"calls","type":"tuple[]"}],"name":"ExecCalls","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"passThrough","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"PassThrough","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReceiveETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"passThrough","type":"address"}],"name":"SetPassThrough","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"SetPaused","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct WalletImpl.Call[]","name":"calls_","type":"tuple[]"}],"name":"execCalls","outputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bytes[]","name":"returnData","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"address","name":"passThrough","type":"address"}],"internalType":"struct PassThroughWalletImpl.InitParams","name":"params_","type":"tuple"}],"name":"initializer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"passThrough","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens_","type":"address[]"}],"name":"passThroughTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"passThroughWalletFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"passThrough_","type":"address"}],"name":"setPassThrough","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"paused_","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.