Feature Tip: Add private address tag to any address under My Name Tag !
ERC-1155
Overview
Max Total Supply
1,000
Holders
3
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Minimal Proxy Contract for 0xb7d1fd59f072509ae4e2eb0628805524b2476371
Contract Name:
LS1155CloneImpl
Compiler Version
v0.8.17+commit.8df45f5f
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.4; /// @notice Library to encode strings in Base64. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Base64.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Base64.sol) /// @author Modified from (https://github.com/Brechtpd/base64/blob/main/base64.sol) by Brecht Devos - <[email protected]>. library Base64 { /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// See: https://datatracker.ietf.org/doc/html/rfc4648 /// @param fileSafe Whether to replace '+' with '-' and '/' with '_'. /// @param noPadding Whether to strip away the padding. function encode( bytes memory data, bool fileSafe, bool noPadding ) internal pure returns (string memory result) { assembly { let dataLength := mload(data) if dataLength { // Multiply by 4/3 rounded up. // The `shl(2, ...)` is equivalent to multiplying by 4. let encodedLength := shl(2, div(add(dataLength, 2), 3)) // Set `result` to point to the start of the free memory. result := mload(0x40) // Store the table into the scratch space. // Offsetted by -1 byte so that the `mload` will load the character. // We will rewrite the free memory pointer at `0x40` later with // the allocated size. // The magic constant 0x0230 will translate "-_" + "+/". mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef") mstore(0x3f, sub("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0230))) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) let end := add(ptr, encodedLength) // Run over the input, 3 bytes at a time. // prettier-ignore for {} 1 {} { data := add(data, 3) // Advance 3 bytes. let input := mload(data) // Write 4 bytes. Optimized for fewer stack operations. mstore8( ptr , mload(and(shr(18, input), 0x3F))) mstore8(add(ptr, 1), mload(and(shr(12, input), 0x3F))) mstore8(add(ptr, 2), mload(and(shr( 6, input), 0x3F))) mstore8(add(ptr, 3), mload(and( input , 0x3F))) ptr := add(ptr, 4) // Advance 4 bytes. // prettier-ignore if iszero(lt(ptr, end)) { break } } let r := mod(dataLength, 3) switch noPadding case 0 { // Offset `ptr` and pad with '='. We can simply write over the end. mstore8(sub(ptr, iszero(iszero(r))), 0x3d) // Pad at `ptr - 1` if `r > 0`. mstore8(sub(ptr, shl(1, eq(r, 1))), 0x3d) // Pad at `ptr - 2` if `r == 1`. // Write the length of the string. mstore(result, encodedLength) } default { // Write the length of the string. mstore(result, sub(encodedLength, add(iszero(iszero(r)), eq(r, 1)))) } // Allocate the memory for the string. // Add 31 and mask with `not(31)` to round the // free memory pointer up the next multiple of 32. mstore(0x40, and(add(end, 31), not(31))) } } } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, false, false)`. function encode(bytes memory data) internal pure returns (string memory result) { result = encode(data, false, false); } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, fileSafe, false)`. function encode(bytes memory data, bool fileSafe) internal pure returns (string memory result) { result = encode(data, fileSafe, false); } /// @dev Encodes base64 encoded `data`. /// /// Supports: /// - RFC 4648 (both standard and file-safe mode). /// - RFC 3501 (63: ','). /// /// Does not support: /// - Line breaks. /// /// Note: For performance reasons, /// this function will NOT revert on invalid `data` inputs. /// Outputs for invalid inputs will simply be undefined behaviour. /// It is the user's responsibility to ensure that the `data` /// is a valid base64 encoded string. function decode(string memory data) internal pure returns (bytes memory result) { assembly { let dataLength := mload(data) if dataLength { let end := add(data, dataLength) let decodedLength := mul(shr(2, dataLength), 3) switch and(dataLength, 3) case 0 { // If padded. decodedLength := sub( decodedLength, add(eq(and(mload(end), 0xFF), 0x3d), eq(and(mload(end), 0xFFFF), 0x3d3d)) ) } default { // If non-padded. decodedLength := add(decodedLength, sub(and(dataLength, 3), 1)) } result := mload(0x40) // Write the length of the string. mstore(result, decodedLength) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) // Load the table into the scratch space. // Constants are optimized for smaller bytecode with zero gas overhead. // `m` also doubles as the mask of the upper 6 bits. let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc mstore(0x5b, m) mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064) mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4) // prettier-ignore for {} 1 {} { // Read 4 bytes. data := add(data, 4) let input := mload(data) // Write 3 bytes. mstore(ptr, or( and(m, mload(byte(28, input))), shr(6, or( and(m, mload(byte(29, input))), shr(6, or( and(m, mload(byte(30, input))), shr(6, mload(byte(31, input))) )) )) )) ptr := add(ptr, 3) // prettier-ignore if iszero(lt(data, end)) { break } } // Allocate the memory for the string. // Add 32 + 31 and mask with `not(31)` to round the // free memory pointer up the next multiple of 32. mstore(0x40, and(add(add(result, decodedLength), 63), not(31))) // Restore the zero slot. mstore(0x60, 0) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Class with helper read functions for clone with immutable args. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Clone.sol) /// @author Adapted from clones with immutable args by zefram.eth, Saw-mon & Natalie /// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args) abstract contract Clone { /// @dev Reads an immutable arg with type bytes. function _getArgBytes(uint256 argOffset, uint256 length) internal pure returns (bytes memory arg) { uint256 offset = _getImmutableArgsOffset(); assembly { // Grab the free memory pointer. arg := mload(0x40) // Store the array length. mstore(arg, length) // Copy the array. calldatacopy(add(arg, 0x20), add(offset, argOffset), length) // Allocate the memory, rounded up to the next 32 byte boudnary. mstore(0x40, and(add(add(arg, 0x3f), length), not(0x1f))) } } /// @dev Reads an immutable arg with type address. function _getArgAddress(uint256 argOffset) internal pure returns (address arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := shr(0x60, calldataload(add(offset, argOffset))) } } /// @dev Reads an immutable arg with type uint256 function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := calldataload(add(offset, argOffset)) } } /// @dev Reads a uint256 array stored in the immutable args. function _getArgUint256Array(uint256 argOffset, uint256 length) internal pure returns (uint256[] memory arg) { uint256 offset = _getImmutableArgsOffset(); assembly { // Grab the free memory pointer. arg := mload(0x40) // Store the array length. mstore(arg, length) // Copy the array. calldatacopy(add(arg, 0x20), add(offset, argOffset), shl(5, length)) // Allocate the memory. mstore(0x40, add(add(arg, 0x20), shl(5, length))) } } /// @dev Reads an immutable arg with type uint64. function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := shr(0xc0, calldataload(add(offset, argOffset))) } } /// @dev Reads an immutable arg with type uint8. function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := shr(0xf8, calldataload(add(offset, argOffset))) } } /// @return offset The offset of the packed immutable args in calldata. function _getImmutableArgsOffset() internal pure returns (uint256 offset) { assembly { offset := sub(calldatasize(), shr(0xf0, calldataload(sub(calldatasize(), 2)))) } } }
// 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 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ error ETHTransferFailed(); error TransferFromFailed(); error TransferFailed(); error ApproveFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function safeTransferETH(address to, uint256 amount) internal { 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) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function safeTransferFrom( address token, address from, address to, uint256 amount ) internal { assembly { // We'll write our calldata to this slot below, but restore it later. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0x00, 0x23b872dd) mstore(0x20, from) // Append the "from" argument. mstore(0x40, to) // Append the "to" argument. mstore(0x60, amount) // Append the "amount" argument. if iszero( and( // 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())), // We use 0x64 because that's the total length of our calldata (0x04 + 0x20 * 3) // Counterintuitively, this call() must be positioned after the or() in the // surrounding and() because and() evaluates its arguments from right to left. 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, memPointer) // Restore the memPointer. } } function safeTransfer( address token, address to, uint256 amount ) internal { assembly { // We'll write our calldata to this slot below, but restore it later. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0x00, 0xa9059cbb) mstore(0x20, to) // Append the "to" argument. mstore(0x40, amount) // Append the "amount" argument. if iszero( and( // 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())), // We use 0x44 because that's the total length of our calldata (0x04 + 0x20 * 2) // Counterintuitively, this call() must be positioned after the or() in the // surrounding and() because and() evaluates its arguments from right to left. call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x40, memPointer) // Restore the memPointer. } } function safeApprove( address token, address to, uint256 amount ) internal { assembly { // We'll write our calldata to this slot below, but restore it later. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0x00, 0x095ea7b3) mstore(0x20, to) // Append the "to" argument. mstore(0x40, amount) // Append the "amount" argument. if iszero( and( // 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())), // We use 0x44 because that's the total length of our calldata (0x04 + 0x20 * 2) // Counterintuitively, this call() must be positioned after the or() in the // surrounding and() because and() evaluates its arguments from right to left. call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `ApproveFailed()`. mstore(0x00, 0x3e3f8f73) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x40, memPointer) // Restore the memPointer. } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } }
// 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 and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Efficient library for creating string representations of integers. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) /// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol) library LibString { function toString(uint256 value) internal pure returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes. let newFreeMemoryPointer := add(mload(0x40), 160) // Update the free memory pointer to avoid overriding our string. mstore(0x40, newFreeMemoryPointer) // Assign str to the end of the zone of newly allocated memory. str := sub(newFreeMemoryPointer, 32) // Clean the last word of memory it may not be overwritten. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { // Move the pointer 1 byte to the left. str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing temp until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } // Compute and cache the final total length of the string. let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 32) // Store the string's length at the start of memory allocated for our string. mstore(str, length) } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {Owned} from "solmate/auth/Owned.sol"; import {ERC1155} from "solmate/tokens/ERC1155.sol"; import {LibString} from "solmate/utils/LibString.sol"; import {Base64} from "solady/utils/Base64.sol"; import {LiquidSplitCloneImpl} from "src/CloneImpl/LiquidSplitCloneImpl.sol"; import {Renderer} from "src/libs/Renderer.sol"; import {utils} from "src/libs/Utils.sol"; /// @title 1155LiquidSplit /// @author 0xSplits /// @notice A minimal liquid split implementation designed to be used as part of a /// clones-with-immutable-args implementation. /// Ownership in a split is represented by 1155s (each = 0.1% of split) /// @dev This contract uses token = address(0) to refer to ETH. contract LS1155CloneImpl is Owned, LiquidSplitCloneImpl, ERC1155 { /// ----------------------------------------------------------------------- /// errors /// ----------------------------------------------------------------------- /// Unauthorized msg.sender error Unauthorized(); /// Array lengths of accounts & percentAllocations don't match (`accountsLength` != `allocationsLength`) /// @param accountsLength Length of accounts array /// @param allocationsLength Length of percentAllocations array error InvalidLiquidSplit__AccountsAndAllocationsMismatch(uint256 accountsLength, uint256 allocationsLength); /// Invalid initAllocations sum `allocationsSum` must equal `TOTAL_SUPPLY` /// @param allocationsSum Sum of percentAllocations array error InvalidLiquidSplit__InvalidAllocationsSum(uint32 allocationsSum); /// ----------------------------------------------------------------------- /// libraries /// ----------------------------------------------------------------------- using LibString for uint256; /// ----------------------------------------------------------------------- /// storage /// ----------------------------------------------------------------------- uint256 internal constant TOKEN_ID = 0; uint256 public constant TOTAL_SUPPLY = 1e3; uint256 public constant SUPPLY_TO_PERCENTAGE = 1e3; // = PERCENTAGE_SCALE / TOTAL_SUPPLY = 1e6 / 1e3 /// ----------------------------------------------------------------------- /// storage - cwia /// ----------------------------------------------------------------------- // first item is uint32 distributorFee in LiquidSplitCloneImpl // 4; second item uint256 internal constant MINTED_ON_TIMESTAMP_OFFSET = 4; /// @dev equivalent to uint256 public immutable mintedOnTimestamp; function mintedOnTimestamp() public pure returns (uint256) { return _getArgUint256(MINTED_ON_TIMESTAMP_OFFSET); } /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- /// only run when implementation is deployed constructor(address _splitMain) Owned(address(0)) LiquidSplitCloneImpl(_splitMain) {} /// initializes each clone function initializer(address[] calldata accounts, uint32[] calldata initAllocations, address _owner) external { /// checks // only liquidSplitFactory may call `initializer` if (msg.sender != liquidSplitFactory) { revert Unauthorized(); } if (accounts.length != initAllocations.length) { revert InvalidLiquidSplit__AccountsAndAllocationsMismatch(accounts.length, initAllocations.length); } { uint32 sum = _getSum(initAllocations); if (sum != TOTAL_SUPPLY) { revert InvalidLiquidSplit__InvalidAllocationsSum(sum); } } /// effects owner = _owner; emit OwnershipTransferred(address(0), _owner); LiquidSplitCloneImpl.initializer(); /// interactions // mint NFTs to initial holders uint256 numAccs = accounts.length; unchecked { for (uint256 i; i < numAccs; ++i) { _mint({to: accounts[i], id: TOKEN_ID, amount: initAllocations[i], data: ""}); } } } /// ----------------------------------------------------------------------- /// functions /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// functions - public & external /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// functions - public & external - view & pure /// ----------------------------------------------------------------------- function scaledPercentBalanceOf(address account) public view override returns (uint32) { unchecked { // can't overflow; // sum(balanceOf) == TOTAL_SUPPLY = 1e3 // SUPPLY_TO_PERCENTAGE = 1e6 / 1e3 = 1e3 // => // sum(balanceOf[i] * SUPPLY_TO_PERCENTAGE) == PERCENTAGE_SCALE = 1e6 << 2^32) return uint32(balanceOf[account][TOKEN_ID] * SUPPLY_TO_PERCENTAGE); } } function name() external view returns (string memory) { return string.concat("Liquid Split ", utils.shortAddressToString(address(this))); } function uri(uint256) public view override returns (string memory) { return string.concat( "data:application/json;base64,", Base64.encode( bytes( string.concat( '{"name": "Liquid Split ', utils.shortAddressToString(address(this)), '", "description": ', '"Each token represents 0.1% of this Liquid Split.", ', '"external_url": ', '"https://app.0xsplits.xyz/accounts/', utils.addressToString(address(this)), "/?chainId=", utils.uint2str(block.chainid), '", ', '"image": "data:image/svg+xml;base64,', Base64.encode(bytes(Renderer.render(address(this)))), '"}' ) ) ) ); } /// ----------------------------------------------------------------------- /// functions - private & internal /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// functions - private & internal - pure /// ----------------------------------------------------------------------- /// Sums array of uint32s /// @param numbers Array of uint32s to sum /// @return sum Sum of `numbers` function _getSum(uint32[] calldata numbers) internal pure returns (uint32 sum) { uint256 numbersLength = numbers.length; for (uint256 i; i < numbersLength;) { sum += numbers[i]; unchecked { // overflow should be impossible in for-loop index ++i; } } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {ERC20} from "solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol"; import {Clone} from "solady/utils/Clone.sol"; import {ISplitMain} from "src/interfaces/ISplitMain.sol"; /// @title LiquidSplitCloneImpl /// @author 0xSplits /// @notice An abstract liquid split base designed to be used as part of a /// clones-with-immutable-args implementation. /// @dev This contract uses token = address(0) to refer to ETH. abstract contract LiquidSplitCloneImpl is Clone { /// ----------------------------------------------------------------------- /// libraries /// ----------------------------------------------------------------------- using SafeTransferLib for address; /// ----------------------------------------------------------------------- /// events /// ----------------------------------------------------------------------- /// Emitted after each successful ETH transfer to proxy /// @param amount Amount of ETH received /// @dev embedded in & emitted from clone bytecode event ReceiveETH(uint256 amount); /// ----------------------------------------------------------------------- /// storage /// ----------------------------------------------------------------------- address internal constant ETH_ADDRESS = address(0); uint256 public constant PERCENTAGE_SCALE = 1e6; ISplitMain public immutable splitMain; address internal immutable liquidSplitFactory; address public payoutSplit; /// ----------------------------------------------------------------------- /// storage - cwia /// ----------------------------------------------------------------------- // 0; first item uint256 internal constant DISTRIBUTOR_FEE_OFFSET = 0; /// @dev equivalent to uint32 public immutable distributorFee; function distributorFee() public pure returns (uint32) { return _getArgUint32(DISTRIBUTOR_FEE_OFFSET); } /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- constructor(address _splitMain) { splitMain = ISplitMain(_splitMain); liquidSplitFactory = msg.sender; } /// @dev cannot be called externally by default; inheriting contracts must /// be sure to properly secure any calls function initializer() internal { /// checks /// effects /// interactions // create dummy mutable split with this contract as controller; // recipients & distributorFee will be updated on first payout address[] memory recipients = new address[](2); recipients[0] = address(0); recipients[1] = address(1); uint32[] memory initPercentAllocations = new uint32[](2); initPercentAllocations[0] = uint32(500000); initPercentAllocations[1] = uint32(500000); payoutSplit = payable( splitMain.createSplit({ accounts: recipients, percentAllocations: initPercentAllocations, distributorFee: 0, controller: address(this) }) ); } /// ----------------------------------------------------------------------- /// functions /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// functions - public & external /// ----------------------------------------------------------------------- /// emit event when receiving ETH /// @dev implemented w/i clone bytecode /* receive() external virtual payable { */ /* emit ReceiveETH(msg.value); */ /* } */ /// distributes ETH & ERC20s to NFT holders /// @param token ETH (0x0) or ERC20 token to distribute /// @param accounts Ordered, unique list of NFT holders /// @param distributorAddress Address to receive distributorFee function distributeFunds(address token, address[] calldata accounts, address distributorAddress) external virtual { uint256 numRecipients = accounts.length; uint32[] memory percentAllocations = new uint32[](numRecipients); for (uint256 i; i < numRecipients;) { percentAllocations[i] = scaledPercentBalanceOf(accounts[i]); unchecked { ++i; } } // atomically deposit funds, update recipients to reflect current NFT holders, and distribute if (token == ETH_ADDRESS) { payoutSplit.safeTransferETH(address(this).balance); splitMain.updateAndDistributeETH({ split: payoutSplit, accounts: accounts, percentAllocations: percentAllocations, distributorFee: distributorFee(), distributorAddress: distributorAddress }); } else { token.safeTransfer(payoutSplit, ERC20(token).balanceOf(address(this))); splitMain.updateAndDistributeERC20({ split: payoutSplit, token: ERC20(token), accounts: accounts, percentAllocations: percentAllocations, distributorFee: distributorFee(), distributorAddress: distributorAddress }); } } /// ----------------------------------------------------------------------- /// functions - public & external - view & pure /// ----------------------------------------------------------------------- function scaledPercentBalanceOf(address account) public view virtual returns (uint32) {} /// @dev Reads an immutable arg with type uint32. function _getArgUint32(uint256 argOffset) internal pure returns (uint32 arg) { uint256 offset = _getImmutableArgsOffset(); assembly { arg := shr(0xe0, calldataload(add(offset, argOffset))) } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {ERC20} from "solmate/tokens/ERC20.sol"; interface ISplitMain { error InvalidSplit__TooFewAccounts(uint256 accountsLength); function createSplit( address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address controller ) external returns (address); function updateAndDistributeETH( address split, address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address distributorAddress ) external; function updateAndDistributeERC20( address split, ERC20 token, address[] calldata accounts, uint32[] calldata percentAllocations, uint32 distributorFee, address distributorAddress ) external; function getETHBalance(address account) external view returns (uint256); function getERC20Balance(address account, ERC20 token) external view returns (uint256); function withdraw(address account, uint256 withdrawETH, ERC20[] calldata tokens) external; }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "./SVG.sol"; import "./Utils.sol"; // adapted from https://github.com/w1nt3r-eth/hot-chain-svg library Renderer { uint256 internal constant size = 600; uint256 internal constant rowSpacing = size / 8; uint256 internal constant colSpacing = size / 14; uint256 internal constant MAX_R = colSpacing * 65 / 100; uint256 internal constant MIN_R = colSpacing * 3 / 10; uint256 internal constant maxDur = 60; uint256 internal constant minDur = 30; uint256 internal constant durRandomnessDiscord = 5; // (60 - 30) < 2^5 function render(address addr) internal pure returns (string memory) { string memory logo; uint256 seed = uint256(uint160(addr)); string memory color = utils.getHslColor(seed); uint8[5] memory xs = [5, 4, 3, 4, 5]; uint256 y = rowSpacing * 2; for (uint256 i; i < 5; i++) { uint256 x = colSpacing * xs[i]; for (uint256 j; j < (8 - xs[i]); j++) { logo = string.concat(logo, drawRandomOrb(x, y, color, seed = newSeed(seed))); x += colSpacing * 2; } y += rowSpacing; } return string.concat( '<svg xmlns="http://www.w3.org/2000/svg" width="', utils.uint2str(size), '" height="', utils.uint2str(size), '" style="background:#000000;font-family:sans-serif;fill:#fafafa;font-size:32">', logo, "</svg>" ); } function randomR(uint256 seed) internal pure returns (uint256 r) { r = utils.bound(seed, MAX_R, MIN_R); } function randomDur(uint256 seed) internal pure returns (uint256 dur) { dur = utils.bound(seed, maxDur, minDur); } function newSeed(uint256 seed) internal pure returns (uint256) { return uint256(keccak256(abi.encodePacked(seed))); } function drawRandomOrb(uint256 cx, uint256 cy, string memory color, uint256 seed) internal pure returns (string memory) { uint256 dur = randomDur(seed); uint256 r = randomR(seed >> durRandomnessDiscord); return drawOrb(cx, cy, r, dur, color); } function drawOrb(uint256 cx, uint256 cy, uint256 r, uint256 dur, string memory color) internal pure returns (string memory _values) { string memory animate; string memory durStr = string.concat(utils.uint2str(dur / 10), ".", utils.uint2str(dur % 10)); string memory valStr = string.concat( utils.uint2str(r), "; ", utils.uint2str(MAX_R), "; ", utils.uint2str(MIN_R), "; ", utils.uint2str(r) ); animate = svg.animate( string.concat( svg.prop("attributeName", "r"), svg.prop("dur", durStr), svg.prop("repeatCount", "indefinite"), svg.prop("calcMode", "paced"), svg.prop("values", valStr) ) ); _values = svg.circle( string.concat( svg.prop("cx", utils.uint2str(cx)), svg.prop("cy", utils.uint2str(cy)), svg.prop("r", utils.uint2str(r)), svg.prop("fill", color) ), animate ); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import "./Utils.sol"; // from https://github.com/w1nt3r-eth/hot-chain-svg // Core SVG utilitiy library which helps us construct // onchain SVG's with a simple, web-like API. library svg { /* MAIN ELEMENTS */ function g(string memory _props, string memory _children) internal pure returns (string memory) { return el("g", _props, _children); } function path(string memory _props, string memory _children) internal pure returns (string memory) { return el("path", _props, _children); } function text(string memory _props, string memory _children) internal pure returns (string memory) { return el("text", _props, _children); } function line(string memory _props, string memory _children) internal pure returns (string memory) { return el("line", _props, _children); } function circle(string memory _props, string memory _children) internal pure returns (string memory) { return el("circle", _props, _children); } function circle(string memory _props) internal pure returns (string memory) { return el("circle", _props); } function rect(string memory _props, string memory _children) internal pure returns (string memory) { return el("rect", _props, _children); } function rect(string memory _props) internal pure returns (string memory) { return el("rect", _props); } function filter(string memory _props, string memory _children) internal pure returns (string memory) { return el("filter", _props, _children); } function cdata(string memory _content) internal pure returns (string memory) { return string.concat("<![CDATA[", _content, "]]>"); } /* GRADIENTS */ function radialGradient(string memory _props, string memory _children) internal pure returns (string memory) { return el("radialGradient", _props, _children); } function linearGradient(string memory _props, string memory _children) internal pure returns (string memory) { return el("linearGradient", _props, _children); } function gradientStop(uint256 offset, string memory stopColor, string memory _props) internal pure returns (string memory) { return el( "stop", string.concat( prop("stop-color", stopColor), " ", prop("offset", string.concat(utils.uint2str(offset), "%")), " ", _props ) ); } function animate(string memory _props) internal pure returns (string memory) { return el("animate", _props); } function animateTransform(string memory _props) internal pure returns (string memory) { return el("animateTransform", _props); } function image(string memory _href, string memory _props) internal pure returns (string memory) { return el("image", string.concat(prop("href", _href), " ", _props)); } /* COMMON */ // A generic element, can be used to construct any SVG (or HTML) element function el(string memory _tag, string memory _props, string memory _children) internal pure returns (string memory) { return string.concat("<", _tag, " ", _props, ">", _children, "</", _tag, ">"); } // A generic element, can be used to construct any SVG (or HTML) element without children function el(string memory _tag, string memory _props) internal pure returns (string memory) { return string.concat("<", _tag, " ", _props, "/>"); } // an SVG attribute function prop(string memory _key, string memory _val) internal pure returns (string memory) { return string.concat(_key, "=", '"', _val, '" '); } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.17; // adapted from https://github.com/w1nt3r-eth/hot-chain-svg // Core utils used extensively to format CSS and numbers. library utils { // used to simulate empty strings string internal constant NULL = ""; // formats a CSS variable line. includes a semicolon for formatting. function setCssVar(string memory _key, string memory _val) internal pure returns (string memory) { return string.concat("--", _key, ":", _val, ";"); } // formats getting a css variable function getCssVar(string memory _key) internal pure returns (string memory) { return string.concat("var(--", _key, ")"); } // formats getting a def URL function getDefURL(string memory _id) internal pure returns (string memory) { return string.concat("url(#", _id, ")"); } // formats rgba white with a specified opacity / alpha function white_a(uint256 _a) internal pure returns (string memory) { return rgba(255, 255, 255, _a); } // formats rgba black with a specified opacity / alpha function black_a(uint256 _a) internal pure returns (string memory) { return rgba(0, 0, 0, _a); } // formats generic rgba color in css function rgba(uint256 _r, uint256 _g, uint256 _b, uint256 _a) internal pure returns (string memory) { string memory formattedA = _a < 100 ? string.concat("0.", utils.uint2str(_a)) : "1"; return string.concat( "rgba(", utils.uint2str(_r), ",", utils.uint2str(_g), ",", utils.uint2str(_b), ",", formattedA, ")" ); } // checks if two strings are equal function stringsEqual(string memory _a, string memory _b) internal pure returns (bool) { return keccak256(abi.encodePacked(_a)) == keccak256(abi.encodePacked(_b)); } // returns the length of a string in characters function utfStringLength(string memory _str) internal pure returns (uint256 length) { uint256 i = 0; bytes memory string_rep = bytes(_str); while (i < string_rep.length) { if (string_rep[i] >> 7 == 0) { i += 1; } else if (string_rep[i] >> 5 == bytes1(uint8(0x6))) { i += 2; } else if (string_rep[i] >> 4 == bytes1(uint8(0xE))) { i += 3; } else if (string_rep[i] >> 3 == bytes1(uint8(0x1E))) { i += 4; } //For safety else { i += 1; } length++; } } // converts an unsigned integer to a string function uint2str(uint256 _i) internal pure returns (string memory _uintAsString) { if (_i == 0) { return "0"; } uint256 j = _i; uint256 len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint256 k = len; while (_i != 0) { k = k - 1; uint8 temp = (48 + uint8(_i - (_i / 10) * 10)); bytes1 b1 = bytes1(temp); bstr[k] = b1; _i /= 10; } return string(bstr); } // generate hsla color from seed function getHslColor(uint256 seed) internal pure returns (string memory _hsla) { uint256 hue = seed % 360; _hsla = string.concat("hsla(", utils.uint2str(hue), ", 88%, 56%, 1)"); } function bound(uint256 value, uint256 max, uint256 min) internal pure returns (uint256 _value) { /* require(max >= min, "INVALID_BOUND"); */ _value = value % (max - min) + min; } function addressToString(address _address) internal pure returns (string memory) { bytes32 _bytes = bytes32(uint256(uint160(_address))); bytes memory HEX = "0123456789abcdef"; bytes memory _string = new bytes(42); _string[0] = "0"; _string[1] = "x"; for (uint256 i = 0; i < 20; i++) { _string[2 + i * 2] = HEX[uint8(_bytes[i + 12] >> 4)]; _string[3 + i * 2] = HEX[uint8(_bytes[i + 12] & 0x0f)]; } return string(_string); } function shortAddressToString(address _address) internal pure returns (string memory) { bytes32 _bytes = bytes32(uint256(uint160(_address))); bytes memory HEX = "0123456789abcdef"; bytes memory _string = new bytes(6); _string[0] = "0"; _string[1] = "x"; for (uint256 i = 0; i < 2; i++) { _string[2 + i * 2] = HEX[uint8(_bytes[i + 12] >> 4)]; _string[3 + i * 2] = HEX[uint8(_bytes[i + 12] & 0x0f)]; } return string(_string); } }
{ "remappings": [ "ds-test/=lib/solmate/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solady/=lib/solady/src/", "solmate/=lib/solmate/src/", "splits-contracts/=lib/splits-contracts/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_splitMain","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"accountsLength","type":"uint256"},{"internalType":"uint256","name":"allocationsLength","type":"uint256"}],"name":"InvalidLiquidSplit__AccountsAndAllocationsMismatch","type":"error"},{"inputs":[{"internalType":"uint32","name":"allocationsSum","type":"uint32"}],"name":"InvalidLiquidSplit__InvalidAllocationsSum","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReceiveETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"PERCENTAGE_SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUPPLY_TO_PERCENTAGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"address","name":"distributorAddress","type":"address"}],"name":"distributeFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distributorFee","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"initAllocations","type":"uint32[]"},{"internalType":"address","name":"_owner","type":"address"}],"name":"initializer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintedOnTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payoutSplit","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"scaledPercentBalanceOf","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"splitMain","outputs":[{"internalType":"contract ISplitMain","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.