Sepolia Testnet

Contract

0xC2039502aa6d154A13f1Ade7a05dBd48c962e73B

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60c0604051959632024-02-01 7:35:12478 days ago1706772912  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LS1155CloneImpl

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.23;

import {Owned} from "solmate/auth/Owned.sol";
import {ERC1155, ERC1155TokenReceiver} 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, ERC1155TokenReceiver {
    /// -----------------------------------------------------------------------
    /// 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: 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: 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: 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: GPL-3.0-or-later
pragma solidity ^0.8.23;

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: MIT
pragma solidity ^0.8.23;

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.23;

// 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);
    }
}

// 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.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: 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: GPL-3.0-or-later
pragma solidity ^0.8.23;

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.23;

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, '" ');
    }
}

Settings
{
  "remappings": [
    "forge-std/=lib/forge-std/src/",
    "solmate/=lib/solmate/src/",
    "solady/=lib/solady/src/",
    "splits-contracts/=lib/splits-contracts/contracts/",
    "ds-test/=lib/solmate/lib/ds-test/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract ABI

API
[{"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":[{"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":[],"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"}]

60c06040523480156200001157600080fd5b50604051620031653803806200316583398101604081905262000034916200008b565b600080546001600160a01b0319168155604051829190819081907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b0316608052503360a052620000bd565b6000602082840312156200009e57600080fd5b81516001600160a01b0381168114620000b657600080fd5b9392505050565b60805160a05161306d620000f860003960006108d20152600081816101cc01528181610baa01528181610cd201526117d9015261306d6000f3fe608060405234801561001057600080fd5b506004361061014c5760003560e01c80638cdf868b116100c3578063d3561ecd1161007c578063d3561ecd1461034a578063dbf32be51461035d578063e985e9c514610372578063f23a6e61146103a0578063f242432a146103c0578063f2fde38b146103d357600080fd5b80638cdf868b146102c35780638da5cb5b146102d6578063902d55a51461026d578063a12df0e7146102e9578063a22cb465146102fc578063bc197c811461030f57600080fd5b80632eb2c2d6116101155780632eb2c2d6146102195780633f26479e1461022e5780634e1273f4146102385780636e67b0fc1461025857806383c9ff311461026d57806386d90c7f1461027657600080fd5b8062fdd58e1461015157806301ffc9a71461018f57806306fdde03146101b25780630e769b2b146101c75780630e89341c14610206575b600080fd5b61017c61015f366004612033565b600260209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101a261019d366004612075565b6103e6565b6040519015158152602001610186565b6101ba610438565b60405161018691906120e2565b6101ee7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610186565b6101ba6102143660046120f5565b610467565b61022c61022736600461219c565b6104e5565b005b61017c620f424081565b61024b61024636600461225b565b610791565b60405161018691906122c7565b3660011981013560f01c90036004013561017c565b61017c6103e881565b6102ae61028436600461230b565b6001600160a01b031660009081526002602090815260408083208380529091529020546103e80290565b60405163ffffffff9091168152602001610186565b61022c6102d1366004612328565b6108c7565b6000546101ee906001600160a01b031681565b6001546101ee906001600160a01b031681565b61022c61030a3660046123ac565b610a53565b61033161031d36600461219c565b63bc197c8160e01b98975050505050505050565b6040516001600160e01b03199091168152602001610186565b61022c6103583660046123ea565b610abf565b3660011981013560f01c90033560e01c6102ae565b6101a2610380366004612452565b600360209081526000928352604080842090915290825290205460ff1681565b6103316103ae366004612480565b63f23a6e6160e01b9695505050505050565b61022c6103ce366004612480565b610d5c565b61022c6103e136600461230b565b610f52565b60006301ffc9a760e01b6001600160e01b0319831614806104175750636cdb3d1360e11b6001600160e01b03198316145b8061043257506303a24d0760e21b6001600160e01b03198316145b92915050565b606061044330610fe6565b6040516020016104539190612518565b604051602081830303815290604052905090565b60606104bf61047530610fe6565b61047e306111bf565b61048746611397565b610498610493306114ba565b611661565b6040516020016104ab949392919061254d565b604051602081830303815290604052611661565b6040516020016104cf91906126bf565b6040516020818303038152906040529050919050565b84831461052b5760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b60448201526064015b60405180910390fd5b336001600160a01b038916148061056557506001600160a01b038816600090815260036020908152604080832033845290915290205460ff165b6105a25760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610522565b60008060005b87811015610661578888828181106105c2576105c2612704565b9050602002013592508686828181106105dd576105dd612704565b6001600160a01b038e1660009081526002602090815260408083208984528252822080549390910294909401359550859392509061061c908490612730565b90915550506001600160a01b038a16600090815260026020908152604080832086845290915281208054849290610654908490612743565b90915550506001016105a8565b50886001600160a01b03168a6001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b6040516106b59493929190612788565b60405180910390a46001600160a01b0389163b1561075c5760405163bc197c8160e01b808252906001600160a01b038b169063bc197c81906107099033908f908e908e908e908e908e908e906004016127d8565b6020604051808303816000875af1158015610728573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074c919061283c565b6001600160e01b03191614610769565b6001600160a01b03891615155b6107855760405162461bcd60e51b815260040161052290612859565b50505050505050505050565b60608382146107d45760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b6044820152606401610522565b8367ffffffffffffffff8111156107ed576107ed612883565b604051908082528060200260200182016040528015610816578160200160208202803683370190505b50905060005b848110156108be576002600087878481811061083a5761083a612704565b905060200201602081019061084f919061230b565b6001600160a01b03166001600160a01b03168152602001908152602001600020600085858481811061088357610883612704565b905060200201358152602001908152602001600020548282815181106108ab576108ab612704565b602090810291909101015260010161081c565b50949350505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461090f576040516282b42960e81b815260040160405180910390fd5b838214610939576040516335389da760e11b81526004810185905260248101839052604401610522565b6000610945848461166f565b90506103e88163ffffffff161461097757604051638692155560e01b815263ffffffff82166004820152602401610522565b50600080546001600160a01b0319166001600160a01b03831690811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36109c86116bf565b8360005b81811015610a4a57610a428787838181106109e9576109e9612704565b90506020020160208101906109fe919061230b565b6000878785818110610a1257610a12612704565b9050602002016020810190610a279190612899565b63ffffffff166040518060200160405280600081525061187c565b6001016109cc565b50505050505050565b3360008181526003602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b8160008167ffffffffffffffff811115610adb57610adb612883565b604051908082528060200260200182016040528015610b04578160200160208202803683370190505b50905060005b82811015610b6b57610b3c868683818110610b2757610b27612704565b9050602002016020810190610284919061230b565b828281518110610b4e57610b4e612704565b63ffffffff90921660209283029190910190910152600101610b0a565b506001600160a01b038616610c3357600154610b90906001600160a01b0316476119c6565b6001546040516352f1c84f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263a5e3909e92610bfc9290911690899089908790600119369081013560f01c90033560e01c908b9060040161293f565b600060405180830381600087803b158015610c1657600080fd5b505af1158015610c2a573d6000803e3d6000fd5b50505050610d54565b6001546040516370a0823160e01b8152306004820152610cb8916001600160a01b0390811691908916906370a0823190602401602060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190612996565b6001600160a01b03891691906119e6565b6001546040516377b1e4e960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926377b1e4e992610d2692909116908a908a908a908890600119369081013560f01c90033560e01c908c906004016129af565b600060405180830381600087803b158015610d4057600080fd5b505af1158015610785573d6000803e3d6000fd5b505050505050565b336001600160a01b0387161480610d9657506001600160a01b038616600090815260036020908152604080832033845290915290205460ff165b610dd35760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610522565b6001600160a01b038616600090815260026020908152604080832087845290915281208054859290610e06908490612730565b90915550506001600160a01b038516600090815260026020908152604080832087845290915281208054859290610e3e908490612743565b909155505060408051858152602081018590526001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0385163b15610f295760405163f23a6e6160e01b808252906001600160a01b0387169063f23a6e6190610ed69033908b908a908a908a908a90600401612a0f565b6020604051808303816000875af1158015610ef5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f19919061283c565b6001600160e01b03191614610f36565b6001600160a01b03851615155b610d545760405162461bcd60e51b815260040161052290612859565b6000546001600160a01b03163314610f9b5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610522565b600080546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b6020820152815160068082528184019093526060926001600160a01b0385169291600091602082018180368337019050509050600360fc1b8160008151811061105257611052612704565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061108157611081612704565b60200101906001600160f81b031916908160001a90535060005b60028110156108be57826004856110b384600c612743565b602081106110c3576110c3612704565b1a60f81b6001600160f81b031916901c60f81c60ff16815181106110e9576110e9612704565b01602001516001600160f81b03191682611104836002612a56565b61110f906002612743565b8151811061111f5761111f612704565b60200101906001600160f81b031916908160001a905350828461114383600c612743565b6020811061115357611153612704565b825191901a600f1690811061116a5761116a612704565b01602001516001600160f81b03191682611185836002612a56565b611190906003612743565b815181106111a0576111a0612704565b60200101906001600160f81b031916908160001a90535060010161109b565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b0385169291600091602082018180368337019050509050600360fc1b8160008151811061122a5761122a612704565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061125957611259612704565b60200101906001600160f81b031916908160001a90535060005b60148110156108be578260048561128b84600c612743565b6020811061129b5761129b612704565b1a60f81b6001600160f81b031916901c60f81c60ff16815181106112c1576112c1612704565b01602001516001600160f81b031916826112dc836002612a56565b6112e7906002612743565b815181106112f7576112f7612704565b60200101906001600160f81b031916908160001a905350828461131b83600c612743565b6020811061132b5761132b612704565b825191901a600f1690811061134257611342612704565b01602001516001600160f81b0319168261135d836002612a56565b611368906003612743565b8151811061137857611378612704565b60200101906001600160f81b031916908160001a905350600101611273565b6060816000036113be5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156113e857806113d281612a6d565b91506113e19050600a83612a9c565b91506113c2565b60008167ffffffffffffffff81111561140357611403612883565b6040519080825280601f01601f19166020018201604052801561142d576020820181803683370190505b509050815b85156108be57611443600182612730565b90506000611452600a88612a9c565b61145d90600a612a56565b6114679088612730565b611472906030612ab0565b905060008160f81b90508084848151811061148f5761148f612704565b60200101906001600160f81b031916908160001a9053506114b1600a89612a9c565b97505050611432565b6060806001600160a01b03831660006114d282611a2a565b6040805160a08101825260058082526004602083018190526003938301939093526060820192909252608081019190915290915060006115156008610258612a9c565b611520906002612a56565b905060005b600581101561161c57600083826005811061154257611542612704565b602002015160ff16611557600e610258612a9c565b6115619190612a56565b905060005b84836005811061157857611578612704565b6020020151611588906008612ac9565b60ff168110156115f957876115aa8386896115a28c611a6c565b9b508b611a9f565b6040516020016115bb929190612ae2565b60408051601f1981840301815291905297506115da600e610258612a9c565b6115e5906002612a56565b6115ef9083612743565b9150600101611566565b506116076008610258612a9c565b6116119084612743565b925050600101611525565b50611628610258611397565b611633610258611397565b8660405160200161164693929190612b11565b60405160208183030381529060405295505050505050919050565b606061043282600080611ad7565b600081815b818110156116b75784848281811061168e5761168e612704565b90506020020160208101906116a39190612899565b6116ad9084612c26565b9250600101611674565b505092915050565b6040805160028082526060820183526000926020830190803683370190505090506000816000815181106116f5576116f5612704565b60200260200101906001600160a01b031690816001600160a01b03168152505060018160018151811061172a5761172a612704565b6001600160a01b039290921660209283029190910182015260408051600280825260608201835260009391929091830190803683370190505090506207a1208160008151811061177c5761177c612704565b602002602001019063ffffffff16908163ffffffff16815250506207a120816001815181106117ad576117ad612704565b63ffffffff90921660209283029190910190910152604051633b00fbc160e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637601f7829061181590859085906000903090600401612c4a565b6020604051808303816000875af1158015611834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118589190612cca565b600180546001600160a01b0319166001600160a01b03929092169190911790555050565b6001600160a01b0384166000908152600260209081526040808320868452909152812080548492906118af908490612743565b909155505060408051848152602081018490526001600160a01b0386169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0384163b156119975760405163f23a6e6160e01b808252906001600160a01b0386169063f23a6e6190611944903390600090899089908990600401612ce7565b6020604051808303816000875af1158015611963573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611987919061283c565b6001600160e01b031916146119a4565b6001600160a01b03841615155b6119c05760405162461bcd60e51b815260040161052290612859565b50505050565b60008060008084865af16119e25763b12d13eb6000526004601cfd5b5050565b60405163a9059cbb6000528260205281604052602060006044601c6000885af13d156001600051141716611a22576390b8ec186000526004601cfd5b604052505050565b60606000611a3a61016884612d21565b9050611a4581611397565b604051602001611a559190612d35565b604051602081830303815290604052915050919050565b600081604051602001611a8191815260200190565b60408051601f19818403018152919052805160209091012092915050565b60606000611aac83611bd6565b90506000611abd600585901c611be5565b9050611acc8787838589611c38565b979650505050505050565b606083518015611bce576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526102308515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f03603f52602083018181015b6003880197508751603f8160121c16518353603f81600c1c16516001840153603f8160061c16516002840153603f811651600384015350600482019150808210611b475760038406868015611ba757600182148215150185038752611bbf565b603d821515850353603d6001831460011b8503538487525b5050601f01601f191660405250505b509392505050565b600061043282603c601e611f23565b6000610432826064611bfa600e610258612a9c565b611c05906041612a56565b611c0f9190612a9c565b600a611c1e600e610258612a9c565b611c29906003612a56565b611c339190612a9c565b611f23565b6060806000611c50611c4b600a87612a9c565b611397565b611c5e611c4b600a88612d21565b604051602001611c6f929190612d7a565b60405160208183030381529060405290506000611c8b87611397565b611cb26064611c9d600e610258612a9c565b611ca8906041612a56565b611c4b9190612a9c565b611ccf600a611cc4600e610258612a9c565b611ca8906003612a56565b611cd88a611397565b604051602001611ceb9493929190612db6565b60408051601f198184030181528282018252600d83526c6174747269627574654e616d6560981b602084810191909152825180840190935260018352603960f91b908301529250611e4a91611d3f91611f4c565b611d6460405180604001604052806003815260200162323ab960e91b81525085611f4c565b611db36040518060400160405280600b81526020016a1c995c19585d10dbdd5b9d60aa1b8152506040518060400160405280600a815260200169696e646566696e69746560b01b815250611f4c565b611dfa6040518060400160405280600881526020016763616c634d6f646560c01b815250604051806040016040528060058152602001641c1858d95960da1b815250611f4c565b611e226040518060400160405280600681526020016576616c75657360d01b81525087611f4c565b604051602001611e36959493929190612e2f565b604051602081830303815290604052611f78565b9250611f16611e7b604051806040016040528060028152602001610c6f60f31b815250611e768c611397565b611f4c565b611ea260405180604001604052806002815260200161637960f01b815250611e768c611397565b611ec8604051806040016040528060018152602001603960f91b815250611e768c611397565b611eee60405180604001604052806004815260200163199a5b1b60e21b8152508a611f4c565b604051602001611f019493929190612e9a565b60405160208183030381529060405284611fa3565b9998505050505050505050565b600081611f308185612730565b611f3a9086612d21565b611f449190612743565b949350505050565b60608282604051602001611f61929190612ef1565b604051602081830303815290604052905092915050565b606061043260405180604001604052806007815260200166616e696d61746560c81b81525083611fd5565b6060611fce60405180604001604052806006815260200165636972636c6560d01b8152508484611fea565b9392505050565b60608282604051602001611f61929190612f46565b6060838383866040516020016120039493929190612f9e565b60405160208183030381529060405290509392505050565b6001600160a01b038116811461203057600080fd5b50565b6000806040838503121561204657600080fd5b82356120518161201b565b946020939093013593505050565b6001600160e01b03198116811461203057600080fd5b60006020828403121561208757600080fd5b8135611fce8161205f565b60005b838110156120ad578181015183820152602001612095565b50506000910152565b600081518084526120ce816020860160208601612092565b601f01601f19169290920160200192915050565b602081526000611fce60208301846120b6565b60006020828403121561210757600080fd5b5035919050565b60008083601f84011261212057600080fd5b50813567ffffffffffffffff81111561213857600080fd5b6020830191508360208260051b850101111561215357600080fd5b9250929050565b60008083601f84011261216c57600080fd5b50813567ffffffffffffffff81111561218457600080fd5b60208301915083602082850101111561215357600080fd5b60008060008060008060008060a0898b0312156121b857600080fd5b88356121c38161201b565b975060208901356121d38161201b565b9650604089013567ffffffffffffffff808211156121f057600080fd5b6121fc8c838d0161210e565b909850965060608b013591508082111561221557600080fd5b6122218c838d0161210e565b909650945060808b013591508082111561223a57600080fd5b506122478b828c0161215a565b999c989b5096995094979396929594505050565b6000806000806040858703121561227157600080fd5b843567ffffffffffffffff8082111561228957600080fd5b6122958883890161210e565b909650945060208701359150808211156122ae57600080fd5b506122bb8782880161210e565b95989497509550505050565b6020808252825182820181905260009190848201906040850190845b818110156122ff578351835292840192918401916001016122e3565b50909695505050505050565b60006020828403121561231d57600080fd5b8135611fce8161201b565b60008060008060006060868803121561234057600080fd5b853567ffffffffffffffff8082111561235857600080fd5b61236489838a0161210e565b9097509550602088013591508082111561237d57600080fd5b5061238a8882890161210e565b909450925050604086013561239e8161201b565b809150509295509295909350565b600080604083850312156123bf57600080fd5b82356123ca8161201b565b9150602083013580151581146123df57600080fd5b809150509250929050565b6000806000806060858703121561240057600080fd5b843561240b8161201b565b9350602085013567ffffffffffffffff81111561242757600080fd5b6124338782880161210e565b90945092505060408501356124478161201b565b939692955090935050565b6000806040838503121561246557600080fd5b82356124708161201b565b915060208301356123df8161201b565b60008060008060008060a0878903121561249957600080fd5b86356124a48161201b565b955060208701356124b48161201b565b94506040870135935060608701359250608087013567ffffffffffffffff8111156124de57600080fd5b6124ea89828a0161215a565b979a9699509497509295939492505050565b6000815161250e818560208601612092565b9290920192915050565b6c02634b8bab4b21029b83634ba1609d1b81526000825161254081600d850160208701612092565b91909101600d0192915050565b7f7b226e616d65223a20224c69717569642053706c697420000000000000000000815260008551612585816017850160208a01612092565b710111610113232b9b1b934b83a34b7b7111d160751b6017918401918201527f224561636820746f6b656e20726570726573656e747320302e3125206f66207460298201527303434b9902634b8bab4b21029b83634ba171116160651b60498201526f01132bc3a32b93730b62fbab936111d160851b605d8201527f2268747470733a2f2f6170702e307873706c6974732e78797a2f6163636f756e606d8201526274732f60e81b608d82015261263f60908201876124fc565b692f3f636861696e49643d60b01b8152905061265e600a8201866124fc565b6201116160ed1b815290507f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b626173600382015263194d8d0b60e21b60238201526126a960278201856124fc565b61227d60f01b8152600201979650505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516126f781601d850160208701612092565b91909101601d0192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156104325761043261271a565b808201808211156104325761043261271a565b81835260006001600160fb1b0383111561276f57600080fd5b8260051b80836020870137939093016020019392505050565b60408152600061279c604083018688612756565b8281036020840152611acc818587612756565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0389811682528816602082015260a060408201819052600090612805908301888a612756565b8281036060840152612818818789612756565b9050828103608084015261282d8185876127af565b9b9a5050505050505050505050565b60006020828403121561284e57600080fd5b8151611fce8161205f565b60208082526010908201526f155394d0519157d49150d2541251539560821b604082015260600190565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156128ab57600080fd5b813563ffffffff81168114611fce57600080fd5b8183526000602080850194508260005b858110156128fd5781356128e28161201b565b6001600160a01b0316875295820195908201906001016128cf565b509495945050505050565b60008151808452602080850194506020840160005b838110156128fd57815163ffffffff168752958201959082019060010161291d565b600060018060a01b03808916835260a0602084015261296260a08401888a6128bf565b83810360408501526129748188612908565b63ffffffff969096166060850152509290921660809091015250949350505050565b6000602082840312156129a857600080fd5b5051919050565b600060018060a01b03808a168352808916602084015260c060408401526129da60c08401888a6128bf565b83810360608501526129ec8188612908565b63ffffffff969096166080850152509290921660a0909101525095945050505050565b6001600160a01b03878116825286166020820152604081018590526060810184905260a060808201819052600090612a4a90830184866127af565b98975050505050505050565b80820281158282048414176104325761043261271a565b600060018201612a7f57612a7f61271a565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082612aab57612aab612a86565b500490565b60ff81811683821601908111156104325761043261271a565b60ff82811682821603908111156104325761043261271a565b60008351612af4818460208801612092565b835190830190612b08818360208801612092565b01949350505050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323081526e181817b9bb3391103bb4b23a341e9160891b602082015260008451612b6181602f850160208901612092565b6911103432b4b3b43a1e9160b11b602f918401918201528451612b8b816039840160208901612092565b7f22207374796c653d226261636b67726f756e643a233030303030303b666f6e74603992909101918201527f2d66616d696c793a73616e732d73657269663b66696c6c3a236661666166613b60598201526d3337b73a16b9b4bd329d1999111f60911b60798201528351612c06816087840160208801612092565b651e17b9bb339f60d11b60879290910191820152608d0195945050505050565b63ffffffff818116838216019080821115612c4357612c4361271a565b5092915050565b6080808252855190820181905260009060209060a0840190828901845b82811015612c8c5781516001600160a01b031684529284019290840190600101612c67565b5050508381036020850152612ca18188612908565b63ffffffff9690961660408501525050506001600160a01b039190911660609091015292915050565b600060208284031215612cdc57600080fd5b8151611fce8161201b565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090611acc908301846120b6565b600082612d3057612d30612a86565b500690565b640d0e6d8c2560db1b815260008251612d55816005850160208701612092565b6d2c203838252c203536252c20312960901b6005939091019283015250601301919050565b60008351612d8c818460208801612092565b601760f91b9083019081528351612daa816001840160208801612092565b01600101949350505050565b60008551612dc8818460208a01612092565b80830190506101d960f51b8082528651612de9816002850160208b01612092565b600292019182018190528551612e06816004850160208a01612092565b60049201918201528351612e21816006840160208801612092565b016006019695505050505050565b60008651612e41818460208b01612092565b865190830190612e55818360208b01612092565b8651910190612e68818360208a01612092565b8551910190612e7b818360208901612092565b8451910190612e8e818360208801612092565b01979650505050505050565b60008551612eac818460208a01612092565b855190830190612ec0818360208a01612092565b8551910190612ed3818360208901612092565b8451910190612ee6818360208801612092565b019695505050505050565b60008351612f03818460208801612092565b603d60f81b908301908152601160f91b60018201528351612f2b816002840160208801612092565b61011160f51b60029290910191820152600401949350505050565b600f60fa1b815260008351612f62816001850160208801612092565b600160fd1b6001918401918201528351612f83816002840160208801612092565b61179f60f11b60029290910191820152600401949350505050565b600f60fa1b815260008551612fba816001850160208a01612092565b600160fd1b6001918401918201528551612fdb816002840160208a01612092565b808201915050601f60f91b8060028301528551612fff816003850160208a01612092565b613c2f60f01b600393909101928301528451613022816005850160208901612092565b6005920191820152600601969550505050505056fea26469706673582212204473fcf5eeccdc66673d189d4f6f0d8687a3e3e6f9904f8ee891eafcd7fc347c64736f6c6343000817003300000000000000000000000057cbfa83f000a38c5b5881743e298819c503a559

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061014c5760003560e01c80638cdf868b116100c3578063d3561ecd1161007c578063d3561ecd1461034a578063dbf32be51461035d578063e985e9c514610372578063f23a6e61146103a0578063f242432a146103c0578063f2fde38b146103d357600080fd5b80638cdf868b146102c35780638da5cb5b146102d6578063902d55a51461026d578063a12df0e7146102e9578063a22cb465146102fc578063bc197c811461030f57600080fd5b80632eb2c2d6116101155780632eb2c2d6146102195780633f26479e1461022e5780634e1273f4146102385780636e67b0fc1461025857806383c9ff311461026d57806386d90c7f1461027657600080fd5b8062fdd58e1461015157806301ffc9a71461018f57806306fdde03146101b25780630e769b2b146101c75780630e89341c14610206575b600080fd5b61017c61015f366004612033565b600260209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101a261019d366004612075565b6103e6565b6040519015158152602001610186565b6101ba610438565b60405161018691906120e2565b6101ee7f00000000000000000000000057cbfa83f000a38c5b5881743e298819c503a55981565b6040516001600160a01b039091168152602001610186565b6101ba6102143660046120f5565b610467565b61022c61022736600461219c565b6104e5565b005b61017c620f424081565b61024b61024636600461225b565b610791565b60405161018691906122c7565b3660011981013560f01c90036004013561017c565b61017c6103e881565b6102ae61028436600461230b565b6001600160a01b031660009081526002602090815260408083208380529091529020546103e80290565b60405163ffffffff9091168152602001610186565b61022c6102d1366004612328565b6108c7565b6000546101ee906001600160a01b031681565b6001546101ee906001600160a01b031681565b61022c61030a3660046123ac565b610a53565b61033161031d36600461219c565b63bc197c8160e01b98975050505050505050565b6040516001600160e01b03199091168152602001610186565b61022c6103583660046123ea565b610abf565b3660011981013560f01c90033560e01c6102ae565b6101a2610380366004612452565b600360209081526000928352604080842090915290825290205460ff1681565b6103316103ae366004612480565b63f23a6e6160e01b9695505050505050565b61022c6103ce366004612480565b610d5c565b61022c6103e136600461230b565b610f52565b60006301ffc9a760e01b6001600160e01b0319831614806104175750636cdb3d1360e11b6001600160e01b03198316145b8061043257506303a24d0760e21b6001600160e01b03198316145b92915050565b606061044330610fe6565b6040516020016104539190612518565b604051602081830303815290604052905090565b60606104bf61047530610fe6565b61047e306111bf565b61048746611397565b610498610493306114ba565b611661565b6040516020016104ab949392919061254d565b604051602081830303815290604052611661565b6040516020016104cf91906126bf565b6040516020818303038152906040529050919050565b84831461052b5760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b60448201526064015b60405180910390fd5b336001600160a01b038916148061056557506001600160a01b038816600090815260036020908152604080832033845290915290205460ff165b6105a25760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610522565b60008060005b87811015610661578888828181106105c2576105c2612704565b9050602002013592508686828181106105dd576105dd612704565b6001600160a01b038e1660009081526002602090815260408083208984528252822080549390910294909401359550859392509061061c908490612730565b90915550506001600160a01b038a16600090815260026020908152604080832086845290915281208054849290610654908490612743565b90915550506001016105a8565b50886001600160a01b03168a6001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b6040516106b59493929190612788565b60405180910390a46001600160a01b0389163b1561075c5760405163bc197c8160e01b808252906001600160a01b038b169063bc197c81906107099033908f908e908e908e908e908e908e906004016127d8565b6020604051808303816000875af1158015610728573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074c919061283c565b6001600160e01b03191614610769565b6001600160a01b03891615155b6107855760405162461bcd60e51b815260040161052290612859565b50505050505050505050565b60608382146107d45760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b6044820152606401610522565b8367ffffffffffffffff8111156107ed576107ed612883565b604051908082528060200260200182016040528015610816578160200160208202803683370190505b50905060005b848110156108be576002600087878481811061083a5761083a612704565b905060200201602081019061084f919061230b565b6001600160a01b03166001600160a01b03168152602001908152602001600020600085858481811061088357610883612704565b905060200201358152602001908152602001600020548282815181106108ab576108ab612704565b602090810291909101015260010161081c565b50949350505050565b336001600160a01b037f000000000000000000000000f678bae6091ab6933425fe26afc20ee5f324c4ae161461090f576040516282b42960e81b815260040160405180910390fd5b838214610939576040516335389da760e11b81526004810185905260248101839052604401610522565b6000610945848461166f565b90506103e88163ffffffff161461097757604051638692155560e01b815263ffffffff82166004820152602401610522565b50600080546001600160a01b0319166001600160a01b03831690811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36109c86116bf565b8360005b81811015610a4a57610a428787838181106109e9576109e9612704565b90506020020160208101906109fe919061230b565b6000878785818110610a1257610a12612704565b9050602002016020810190610a279190612899565b63ffffffff166040518060200160405280600081525061187c565b6001016109cc565b50505050505050565b3360008181526003602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b8160008167ffffffffffffffff811115610adb57610adb612883565b604051908082528060200260200182016040528015610b04578160200160208202803683370190505b50905060005b82811015610b6b57610b3c868683818110610b2757610b27612704565b9050602002016020810190610284919061230b565b828281518110610b4e57610b4e612704565b63ffffffff90921660209283029190910190910152600101610b0a565b506001600160a01b038616610c3357600154610b90906001600160a01b0316476119c6565b6001546040516352f1c84f60e11b81526001600160a01b037f00000000000000000000000057cbfa83f000a38c5b5881743e298819c503a55981169263a5e3909e92610bfc9290911690899089908790600119369081013560f01c90033560e01c908b9060040161293f565b600060405180830381600087803b158015610c1657600080fd5b505af1158015610c2a573d6000803e3d6000fd5b50505050610d54565b6001546040516370a0823160e01b8152306004820152610cb8916001600160a01b0390811691908916906370a0823190602401602060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190612996565b6001600160a01b03891691906119e6565b6001546040516377b1e4e960e01b81526001600160a01b037f00000000000000000000000057cbfa83f000a38c5b5881743e298819c503a5598116926377b1e4e992610d2692909116908a908a908a908890600119369081013560f01c90033560e01c908c906004016129af565b600060405180830381600087803b158015610d4057600080fd5b505af1158015610785573d6000803e3d6000fd5b505050505050565b336001600160a01b0387161480610d9657506001600160a01b038616600090815260036020908152604080832033845290915290205460ff165b610dd35760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610522565b6001600160a01b038616600090815260026020908152604080832087845290915281208054859290610e06908490612730565b90915550506001600160a01b038516600090815260026020908152604080832087845290915281208054859290610e3e908490612743565b909155505060408051858152602081018590526001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0385163b15610f295760405163f23a6e6160e01b808252906001600160a01b0387169063f23a6e6190610ed69033908b908a908a908a908a90600401612a0f565b6020604051808303816000875af1158015610ef5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f19919061283c565b6001600160e01b03191614610f36565b6001600160a01b03851615155b610d545760405162461bcd60e51b815260040161052290612859565b6000546001600160a01b03163314610f9b5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610522565b600080546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b6020820152815160068082528184019093526060926001600160a01b0385169291600091602082018180368337019050509050600360fc1b8160008151811061105257611052612704565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061108157611081612704565b60200101906001600160f81b031916908160001a90535060005b60028110156108be57826004856110b384600c612743565b602081106110c3576110c3612704565b1a60f81b6001600160f81b031916901c60f81c60ff16815181106110e9576110e9612704565b01602001516001600160f81b03191682611104836002612a56565b61110f906002612743565b8151811061111f5761111f612704565b60200101906001600160f81b031916908160001a905350828461114383600c612743565b6020811061115357611153612704565b825191901a600f1690811061116a5761116a612704565b01602001516001600160f81b03191682611185836002612a56565b611190906003612743565b815181106111a0576111a0612704565b60200101906001600160f81b031916908160001a90535060010161109b565b604080518082018252601081526f181899199a1a9b1b9c1cb0b131b232b360811b60208201528151602a80825260608281019094526001600160a01b0385169291600091602082018180368337019050509050600360fc1b8160008151811061122a5761122a612704565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061125957611259612704565b60200101906001600160f81b031916908160001a90535060005b60148110156108be578260048561128b84600c612743565b6020811061129b5761129b612704565b1a60f81b6001600160f81b031916901c60f81c60ff16815181106112c1576112c1612704565b01602001516001600160f81b031916826112dc836002612a56565b6112e7906002612743565b815181106112f7576112f7612704565b60200101906001600160f81b031916908160001a905350828461131b83600c612743565b6020811061132b5761132b612704565b825191901a600f1690811061134257611342612704565b01602001516001600160f81b0319168261135d836002612a56565b611368906003612743565b8151811061137857611378612704565b60200101906001600160f81b031916908160001a905350600101611273565b6060816000036113be5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156113e857806113d281612a6d565b91506113e19050600a83612a9c565b91506113c2565b60008167ffffffffffffffff81111561140357611403612883565b6040519080825280601f01601f19166020018201604052801561142d576020820181803683370190505b509050815b85156108be57611443600182612730565b90506000611452600a88612a9c565b61145d90600a612a56565b6114679088612730565b611472906030612ab0565b905060008160f81b90508084848151811061148f5761148f612704565b60200101906001600160f81b031916908160001a9053506114b1600a89612a9c565b97505050611432565b6060806001600160a01b03831660006114d282611a2a565b6040805160a08101825260058082526004602083018190526003938301939093526060820192909252608081019190915290915060006115156008610258612a9c565b611520906002612a56565b905060005b600581101561161c57600083826005811061154257611542612704565b602002015160ff16611557600e610258612a9c565b6115619190612a56565b905060005b84836005811061157857611578612704565b6020020151611588906008612ac9565b60ff168110156115f957876115aa8386896115a28c611a6c565b9b508b611a9f565b6040516020016115bb929190612ae2565b60408051601f1981840301815291905297506115da600e610258612a9c565b6115e5906002612a56565b6115ef9083612743565b9150600101611566565b506116076008610258612a9c565b6116119084612743565b925050600101611525565b50611628610258611397565b611633610258611397565b8660405160200161164693929190612b11565b60405160208183030381529060405295505050505050919050565b606061043282600080611ad7565b600081815b818110156116b75784848281811061168e5761168e612704565b90506020020160208101906116a39190612899565b6116ad9084612c26565b9250600101611674565b505092915050565b6040805160028082526060820183526000926020830190803683370190505090506000816000815181106116f5576116f5612704565b60200260200101906001600160a01b031690816001600160a01b03168152505060018160018151811061172a5761172a612704565b6001600160a01b039290921660209283029190910182015260408051600280825260608201835260009391929091830190803683370190505090506207a1208160008151811061177c5761177c612704565b602002602001019063ffffffff16908163ffffffff16815250506207a120816001815181106117ad576117ad612704565b63ffffffff90921660209283029190910190910152604051633b00fbc160e11b81526001600160a01b037f00000000000000000000000057cbfa83f000a38c5b5881743e298819c503a5591690637601f7829061181590859085906000903090600401612c4a565b6020604051808303816000875af1158015611834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118589190612cca565b600180546001600160a01b0319166001600160a01b03929092169190911790555050565b6001600160a01b0384166000908152600260209081526040808320868452909152812080548492906118af908490612743565b909155505060408051848152602081018490526001600160a01b0386169160009133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0384163b156119975760405163f23a6e6160e01b808252906001600160a01b0386169063f23a6e6190611944903390600090899089908990600401612ce7565b6020604051808303816000875af1158015611963573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611987919061283c565b6001600160e01b031916146119a4565b6001600160a01b03841615155b6119c05760405162461bcd60e51b815260040161052290612859565b50505050565b60008060008084865af16119e25763b12d13eb6000526004601cfd5b5050565b60405163a9059cbb6000528260205281604052602060006044601c6000885af13d156001600051141716611a22576390b8ec186000526004601cfd5b604052505050565b60606000611a3a61016884612d21565b9050611a4581611397565b604051602001611a559190612d35565b604051602081830303815290604052915050919050565b600081604051602001611a8191815260200190565b60408051601f19818403018152919052805160209091012092915050565b60606000611aac83611bd6565b90506000611abd600585901c611be5565b9050611acc8787838589611c38565b979650505050505050565b606083518015611bce576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526102308515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f03603f52602083018181015b6003880197508751603f8160121c16518353603f81600c1c16516001840153603f8160061c16516002840153603f811651600384015350600482019150808210611b475760038406868015611ba757600182148215150185038752611bbf565b603d821515850353603d6001831460011b8503538487525b5050601f01601f191660405250505b509392505050565b600061043282603c601e611f23565b6000610432826064611bfa600e610258612a9c565b611c05906041612a56565b611c0f9190612a9c565b600a611c1e600e610258612a9c565b611c29906003612a56565b611c339190612a9c565b611f23565b6060806000611c50611c4b600a87612a9c565b611397565b611c5e611c4b600a88612d21565b604051602001611c6f929190612d7a565b60405160208183030381529060405290506000611c8b87611397565b611cb26064611c9d600e610258612a9c565b611ca8906041612a56565b611c4b9190612a9c565b611ccf600a611cc4600e610258612a9c565b611ca8906003612a56565b611cd88a611397565b604051602001611ceb9493929190612db6565b60408051601f198184030181528282018252600d83526c6174747269627574654e616d6560981b602084810191909152825180840190935260018352603960f91b908301529250611e4a91611d3f91611f4c565b611d6460405180604001604052806003815260200162323ab960e91b81525085611f4c565b611db36040518060400160405280600b81526020016a1c995c19585d10dbdd5b9d60aa1b8152506040518060400160405280600a815260200169696e646566696e69746560b01b815250611f4c565b611dfa6040518060400160405280600881526020016763616c634d6f646560c01b815250604051806040016040528060058152602001641c1858d95960da1b815250611f4c565b611e226040518060400160405280600681526020016576616c75657360d01b81525087611f4c565b604051602001611e36959493929190612e2f565b604051602081830303815290604052611f78565b9250611f16611e7b604051806040016040528060028152602001610c6f60f31b815250611e768c611397565b611f4c565b611ea260405180604001604052806002815260200161637960f01b815250611e768c611397565b611ec8604051806040016040528060018152602001603960f91b815250611e768c611397565b611eee60405180604001604052806004815260200163199a5b1b60e21b8152508a611f4c565b604051602001611f019493929190612e9a565b60405160208183030381529060405284611fa3565b9998505050505050505050565b600081611f308185612730565b611f3a9086612d21565b611f449190612743565b949350505050565b60608282604051602001611f61929190612ef1565b604051602081830303815290604052905092915050565b606061043260405180604001604052806007815260200166616e696d61746560c81b81525083611fd5565b6060611fce60405180604001604052806006815260200165636972636c6560d01b8152508484611fea565b9392505050565b60608282604051602001611f61929190612f46565b6060838383866040516020016120039493929190612f9e565b60405160208183030381529060405290509392505050565b6001600160a01b038116811461203057600080fd5b50565b6000806040838503121561204657600080fd5b82356120518161201b565b946020939093013593505050565b6001600160e01b03198116811461203057600080fd5b60006020828403121561208757600080fd5b8135611fce8161205f565b60005b838110156120ad578181015183820152602001612095565b50506000910152565b600081518084526120ce816020860160208601612092565b601f01601f19169290920160200192915050565b602081526000611fce60208301846120b6565b60006020828403121561210757600080fd5b5035919050565b60008083601f84011261212057600080fd5b50813567ffffffffffffffff81111561213857600080fd5b6020830191508360208260051b850101111561215357600080fd5b9250929050565b60008083601f84011261216c57600080fd5b50813567ffffffffffffffff81111561218457600080fd5b60208301915083602082850101111561215357600080fd5b60008060008060008060008060a0898b0312156121b857600080fd5b88356121c38161201b565b975060208901356121d38161201b565b9650604089013567ffffffffffffffff808211156121f057600080fd5b6121fc8c838d0161210e565b909850965060608b013591508082111561221557600080fd5b6122218c838d0161210e565b909650945060808b013591508082111561223a57600080fd5b506122478b828c0161215a565b999c989b5096995094979396929594505050565b6000806000806040858703121561227157600080fd5b843567ffffffffffffffff8082111561228957600080fd5b6122958883890161210e565b909650945060208701359150808211156122ae57600080fd5b506122bb8782880161210e565b95989497509550505050565b6020808252825182820181905260009190848201906040850190845b818110156122ff578351835292840192918401916001016122e3565b50909695505050505050565b60006020828403121561231d57600080fd5b8135611fce8161201b565b60008060008060006060868803121561234057600080fd5b853567ffffffffffffffff8082111561235857600080fd5b61236489838a0161210e565b9097509550602088013591508082111561237d57600080fd5b5061238a8882890161210e565b909450925050604086013561239e8161201b565b809150509295509295909350565b600080604083850312156123bf57600080fd5b82356123ca8161201b565b9150602083013580151581146123df57600080fd5b809150509250929050565b6000806000806060858703121561240057600080fd5b843561240b8161201b565b9350602085013567ffffffffffffffff81111561242757600080fd5b6124338782880161210e565b90945092505060408501356124478161201b565b939692955090935050565b6000806040838503121561246557600080fd5b82356124708161201b565b915060208301356123df8161201b565b60008060008060008060a0878903121561249957600080fd5b86356124a48161201b565b955060208701356124b48161201b565b94506040870135935060608701359250608087013567ffffffffffffffff8111156124de57600080fd5b6124ea89828a0161215a565b979a9699509497509295939492505050565b6000815161250e818560208601612092565b9290920192915050565b6c02634b8bab4b21029b83634ba1609d1b81526000825161254081600d850160208701612092565b91909101600d0192915050565b7f7b226e616d65223a20224c69717569642053706c697420000000000000000000815260008551612585816017850160208a01612092565b710111610113232b9b1b934b83a34b7b7111d160751b6017918401918201527f224561636820746f6b656e20726570726573656e747320302e3125206f66207460298201527303434b9902634b8bab4b21029b83634ba171116160651b60498201526f01132bc3a32b93730b62fbab936111d160851b605d8201527f2268747470733a2f2f6170702e307873706c6974732e78797a2f6163636f756e606d8201526274732f60e81b608d82015261263f60908201876124fc565b692f3f636861696e49643d60b01b8152905061265e600a8201866124fc565b6201116160ed1b815290507f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b626173600382015263194d8d0b60e21b60238201526126a960278201856124fc565b61227d60f01b8152600201979650505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516126f781601d850160208701612092565b91909101601d0192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156104325761043261271a565b808201808211156104325761043261271a565b81835260006001600160fb1b0383111561276f57600080fd5b8260051b80836020870137939093016020019392505050565b60408152600061279c604083018688612756565b8281036020840152611acc818587612756565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0389811682528816602082015260a060408201819052600090612805908301888a612756565b8281036060840152612818818789612756565b9050828103608084015261282d8185876127af565b9b9a5050505050505050505050565b60006020828403121561284e57600080fd5b8151611fce8161205f565b60208082526010908201526f155394d0519157d49150d2541251539560821b604082015260600190565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156128ab57600080fd5b813563ffffffff81168114611fce57600080fd5b8183526000602080850194508260005b858110156128fd5781356128e28161201b565b6001600160a01b0316875295820195908201906001016128cf565b509495945050505050565b60008151808452602080850194506020840160005b838110156128fd57815163ffffffff168752958201959082019060010161291d565b600060018060a01b03808916835260a0602084015261296260a08401888a6128bf565b83810360408501526129748188612908565b63ffffffff969096166060850152509290921660809091015250949350505050565b6000602082840312156129a857600080fd5b5051919050565b600060018060a01b03808a168352808916602084015260c060408401526129da60c08401888a6128bf565b83810360608501526129ec8188612908565b63ffffffff969096166080850152509290921660a0909101525095945050505050565b6001600160a01b03878116825286166020820152604081018590526060810184905260a060808201819052600090612a4a90830184866127af565b98975050505050505050565b80820281158282048414176104325761043261271a565b600060018201612a7f57612a7f61271a565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082612aab57612aab612a86565b500490565b60ff81811683821601908111156104325761043261271a565b60ff82811682821603908111156104325761043261271a565b60008351612af4818460208801612092565b835190830190612b08818360208801612092565b01949350505050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323081526e181817b9bb3391103bb4b23a341e9160891b602082015260008451612b6181602f850160208901612092565b6911103432b4b3b43a1e9160b11b602f918401918201528451612b8b816039840160208901612092565b7f22207374796c653d226261636b67726f756e643a233030303030303b666f6e74603992909101918201527f2d66616d696c793a73616e732d73657269663b66696c6c3a236661666166613b60598201526d3337b73a16b9b4bd329d1999111f60911b60798201528351612c06816087840160208801612092565b651e17b9bb339f60d11b60879290910191820152608d0195945050505050565b63ffffffff818116838216019080821115612c4357612c4361271a565b5092915050565b6080808252855190820181905260009060209060a0840190828901845b82811015612c8c5781516001600160a01b031684529284019290840190600101612c67565b5050508381036020850152612ca18188612908565b63ffffffff9690961660408501525050506001600160a01b039190911660609091015292915050565b600060208284031215612cdc57600080fd5b8151611fce8161201b565b6001600160a01b03868116825285166020820152604081018490526060810183905260a060808201819052600090611acc908301846120b6565b600082612d3057612d30612a86565b500690565b640d0e6d8c2560db1b815260008251612d55816005850160208701612092565b6d2c203838252c203536252c20312960901b6005939091019283015250601301919050565b60008351612d8c818460208801612092565b601760f91b9083019081528351612daa816001840160208801612092565b01600101949350505050565b60008551612dc8818460208a01612092565b80830190506101d960f51b8082528651612de9816002850160208b01612092565b600292019182018190528551612e06816004850160208a01612092565b60049201918201528351612e21816006840160208801612092565b016006019695505050505050565b60008651612e41818460208b01612092565b865190830190612e55818360208b01612092565b8651910190612e68818360208a01612092565b8551910190612e7b818360208901612092565b8451910190612e8e818360208801612092565b01979650505050505050565b60008551612eac818460208a01612092565b855190830190612ec0818360208a01612092565b8551910190612ed3818360208901612092565b8451910190612ee6818360208801612092565b019695505050505050565b60008351612f03818460208801612092565b603d60f81b908301908152601160f91b60018201528351612f2b816002840160208801612092565b61011160f51b60029290910191820152600401949350505050565b600f60fa1b815260008351612f62816001850160208801612092565b600160fd1b6001918401918201528351612f83816002840160208801612092565b61179f60f11b60029290910191820152600401949350505050565b600f60fa1b815260008551612fba816001850160208a01612092565b600160fd1b6001918401918201528551612fdb816002840160208a01612092565b808201915050601f60f91b8060028301528551612fff816003850160208a01612092565b613c2f60f01b600393909101928301528451613022816005850160208901612092565b6005920191820152600601969550505050505056fea26469706673582212204473fcf5eeccdc66673d189d4f6f0d8687a3e3e6f9904f8ee891eafcd7fc347c64736f6c63430008170033

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

00000000000000000000000057cbfa83f000a38c5b5881743e298819c503a559

-----Decoded View---------------
Arg [0] : _splitMain (address): 0x57CBFA83f000a38C5b5881743E298819c503A559

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000057cbfa83f000a38c5b5881743e298819c503a559


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.