{
  "address": "0xb28Ad73ebCE83861105B4354bB8F241040533026",
  "abi": [
    {
      "inputs": [],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "inputs": [],
      "name": "Create2Error",
      "type": "error"
    },
    {
      "inputs": [],
      "name": "CreateError",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newController",
          "type": "address"
        }
      ],
      "name": "InvalidNewController",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "accountsLength",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "allocationsLength",
          "type": "uint256"
        }
      ],
      "name": "InvalidSplit__AccountsAndAllocationsMismatch",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "index",
          "type": "uint256"
        }
      ],
      "name": "InvalidSplit__AccountsOutOfOrder",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "index",
          "type": "uint256"
        }
      ],
      "name": "InvalidSplit__AllocationMustBePositive",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint32",
          "name": "allocationsSum",
          "type": "uint32"
        }
      ],
      "name": "InvalidSplit__InvalidAllocationsSum",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint32",
          "name": "distributorFee",
          "type": "uint32"
        }
      ],
      "name": "InvalidSplit__InvalidDistributorFee",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "hash",
          "type": "bytes32"
        }
      ],
      "name": "InvalidSplit__InvalidHash",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "accountsLength",
          "type": "uint256"
        }
      ],
      "name": "InvalidSplit__TooFewAccounts",
      "type": "error"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "sender",
          "type": "address"
        }
      ],
      "name": "Unauthorized",
      "type": "error"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "name": "CancelControlTransfer",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "previousController",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "newController",
          "type": "address"
        }
      ],
      "name": "ControlTransfer",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "name": "CreateSplit",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "contract ERC20",
          "name": "token",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "distributorAddress",
          "type": "address"
        }
      ],
      "name": "DistributeERC20",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "distributorAddress",
          "type": "address"
        }
      ],
      "name": "DistributeETH",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "newPotentialController",
          "type": "address"
        }
      ],
      "name": "InitiateControlTransfer",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "name": "UpdateSplit",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "ethAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "contract ERC20[]",
          "name": "tokens",
          "type": "address[]"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "tokenAmounts",
          "type": "uint256[]"
        }
      ],
      "name": "Withdrawal",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "PERCENTAGE_SCALE",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "name": "acceptControl",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "name": "cancelControlTransfer",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "accounts",
          "type": "address[]"
        },
        {
          "internalType": "uint32[]",
          "name": "percentAllocations",
          "type": "uint32[]"
        },
        {
          "internalType": "uint32",
          "name": "distributorFee",
          "type": "uint32"
        },
        {
          "internalType": "address",
          "name": "controller",
          "type": "address"
        }
      ],
      "name": "createSplit",
      "outputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "internalType": "contract ERC20",
          "name": "token",
          "type": "address"
        },
        {
          "internalType": "address[]",
          "name": "accounts",
          "type": "address[]"
        },
        {
          "internalType": "uint32[]",
          "name": "percentAllocations",
          "type": "uint32[]"
        },
        {
          "internalType": "uint32",
          "name": "distributorFee",
          "type": "uint32"
        },
        {
          "internalType": "address",
          "name": "distributorAddress",
          "type": "address"
        }
      ],
      "name": "distributeERC20",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "internalType": "address[]",
          "name": "accounts",
          "type": "address[]"
        },
        {
          "internalType": "uint32[]",
          "name": "percentAllocations",
          "type": "uint32[]"
        },
        {
          "internalType": "uint32",
          "name": "distributorFee",
          "type": "uint32"
        },
        {
          "internalType": "address",
          "name": "distributorAddress",
          "type": "address"
        }
      ],
      "name": "distributeETH",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "name": "getController",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "contract ERC20",
          "name": "token",
          "type": "address"
        }
      ],
      "name": "getERC20Balance",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "getETHBalance",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "name": "getHash",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "name": "getNewPotentialController",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "name": "makeSplitImmutable",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "accounts",
          "type": "address[]"
        },
        {
          "internalType": "uint32[]",
          "name": "percentAllocations",
          "type": "uint32[]"
        },
        {
          "internalType": "uint32",
          "name": "distributorFee",
          "type": "uint32"
        }
      ],
      "name": "predictImmutableSplitAddress",
      "outputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "newController",
          "type": "address"
        }
      ],
      "name": "transferControl",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "internalType": "contract ERC20",
          "name": "token",
          "type": "address"
        },
        {
          "internalType": "address[]",
          "name": "accounts",
          "type": "address[]"
        },
        {
          "internalType": "uint32[]",
          "name": "percentAllocations",
          "type": "uint32[]"
        },
        {
          "internalType": "uint32",
          "name": "distributorFee",
          "type": "uint32"
        },
        {
          "internalType": "address",
          "name": "distributorAddress",
          "type": "address"
        }
      ],
      "name": "updateAndDistributeERC20",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "internalType": "address[]",
          "name": "accounts",
          "type": "address[]"
        },
        {
          "internalType": "uint32[]",
          "name": "percentAllocations",
          "type": "uint32[]"
        },
        {
          "internalType": "uint32",
          "name": "distributorFee",
          "type": "uint32"
        },
        {
          "internalType": "address",
          "name": "distributorAddress",
          "type": "address"
        }
      ],
      "name": "updateAndDistributeETH",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "split",
          "type": "address"
        },
        {
          "internalType": "address[]",
          "name": "accounts",
          "type": "address[]"
        },
        {
          "internalType": "uint32[]",
          "name": "percentAllocations",
          "type": "uint32[]"
        },
        {
          "internalType": "uint32",
          "name": "distributorFee",
          "type": "uint32"
        }
      ],
      "name": "updateSplit",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "walletImplementation",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "withdrawETH",
          "type": "uint256"
        },
        {
          "internalType": "contract ERC20[]",
          "name": "tokens",
          "type": "address[]"
        }
      ],
      "name": "withdraw",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "stateMutability": "payable",
      "type": "receive"
    }
  ],
  "transactionHash": "0x31e9e2fe08f87cd743fb266c1b4185ea953f4116a798c2e2255424c3e0106f77",
  "receipt": {
    "to": null,
    "from": "0xB0A36b3CeDf210f37a5E7BC28d4b8E91D4E3C412",
    "contractAddress": "0xb28Ad73ebCE83861105B4354bB8F241040533026",
    "transactionIndex": 0,
    "gasUsed": "2940451",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x1ac088787ed3d13d1cc7895aae842be3253d665be91bd899574529ef15855d9f",
    "transactionHash": "0x31e9e2fe08f87cd743fb266c1b4185ea953f4116a798c2e2255424c3e0106f77",
    "logs": [],
    "blockNumber": 5,
    "cumulativeGasUsed": "2940451",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "numDeployments": 1,
  "solcInputHash": "c924a22d05320f8708668d5eaf8090c8",
  "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Create2Error\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CreateError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newController\",\"type\":\"address\"}],\"name\":\"InvalidNewController\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"allocationsLength\",\"type\":\"uint256\"}],\"name\":\"InvalidSplit__AccountsAndAllocationsMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"InvalidSplit__AccountsOutOfOrder\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"InvalidSplit__AllocationMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"allocationsSum\",\"type\":\"uint32\"}],\"name\":\"InvalidSplit__InvalidAllocationsSum\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"distributorFee\",\"type\":\"uint32\"}],\"name\":\"InvalidSplit__InvalidDistributorFee\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"InvalidSplit__InvalidHash\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"accountsLength\",\"type\":\"uint256\"}],\"name\":\"InvalidSplit__TooFewAccounts\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"name\":\"CancelControlTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousController\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newController\",\"type\":\"address\"}],\"name\":\"ControlTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"name\":\"CreateSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract ERC20\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"}],\"name\":\"DistributeERC20\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"}],\"name\":\"DistributeETH\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPotentialController\",\"type\":\"address\"}],\"name\":\"InitiateControlTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"name\":\"UpdateSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"ethAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract ERC20[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"tokenAmounts\",\"type\":\"uint256[]\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"PERCENTAGE_SCALE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"name\":\"acceptControl\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"name\":\"cancelControlTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint32[]\",\"name\":\"percentAllocations\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32\",\"name\":\"distributorFee\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"controller\",\"type\":\"address\"}],\"name\":\"createSplit\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"internalType\":\"contract ERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint32[]\",\"name\":\"percentAllocations\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32\",\"name\":\"distributorFee\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"}],\"name\":\"distributeERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint32[]\",\"name\":\"percentAllocations\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32\",\"name\":\"distributorFee\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"}],\"name\":\"distributeETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"name\":\"getController\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract ERC20\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getERC20Balance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getETHBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"name\":\"getHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"name\":\"getNewPotentialController\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"name\":\"makeSplitImmutable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint32[]\",\"name\":\"percentAllocations\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32\",\"name\":\"distributorFee\",\"type\":\"uint32\"}],\"name\":\"predictImmutableSplitAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newController\",\"type\":\"address\"}],\"name\":\"transferControl\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"internalType\":\"contract ERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint32[]\",\"name\":\"percentAllocations\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32\",\"name\":\"distributorFee\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"}],\"name\":\"updateAndDistributeERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint32[]\",\"name\":\"percentAllocations\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32\",\"name\":\"distributorFee\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"}],\"name\":\"updateAndDistributeETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"split\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint32[]\",\"name\":\"percentAllocations\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32\",\"name\":\"distributorFee\",\"type\":\"uint32\"}],\"name\":\"updateSplit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"walletImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawETH\",\"type\":\"uint256\"},{\"internalType\":\"contract ERC20[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"0xSplits <will@0xSplits.xyz>\",\"details\":\"Split recipients, ownerships, and keeper fees are stored onchain as calldata & re-passed as args / validated via hashing when needed. Each split gets its own address & proxy for maximum composability with other contracts onchain. For these proxies, we extended EIP-1167 Minimal Proxy Contract to avoid `DELEGATECALL` inside `receive()` to accept hard gas-capped `sends` & `transfers`.\",\"errors\":{\"InvalidNewController(address)\":[{\"params\":{\"newController\":\"Invalid new controller\"}}],\"InvalidSplit__AccountsAndAllocationsMismatch(uint256,uint256)\":[{\"params\":{\"accountsLength\":\"Length of accounts array\",\"allocationsLength\":\"Length of percentAllocations array\"}}],\"InvalidSplit__AccountsOutOfOrder(uint256)\":[{\"params\":{\"index\":\"Index of out-of-order account\"}}],\"InvalidSplit__AllocationMustBePositive(uint256)\":[{\"params\":{\"index\":\"Index of zero percentAllocation\"}}],\"InvalidSplit__InvalidAllocationsSum(uint32)\":[{\"params\":{\"allocationsSum\":\"Sum of percentAllocations array\"}}],\"InvalidSplit__InvalidDistributorFee(uint32)\":[{\"params\":{\"distributorFee\":\"Invalid distributorFee amount\"}}],\"InvalidSplit__InvalidHash(bytes32)\":[{\"params\":{\"hash\":\"Invalid hash\"}}],\"InvalidSplit__TooFewAccounts(uint256)\":[{\"params\":{\"accountsLength\":\"Length of accounts array\"}}],\"Unauthorized(address)\":[{\"params\":{\"sender\":\"Transaction sender\"}}]},\"kind\":\"dev\",\"methods\":{\"acceptControl(address)\":{\"params\":{\"split\":\"Address of mutable split to accept control transfer for\"}},\"cancelControlTransfer(address)\":{\"params\":{\"split\":\"Address of mutable split to cancel control transfer for\"}},\"createSplit(address[],uint32[],uint32,address)\":{\"params\":{\"accounts\":\"Ordered, unique list of addresses with ownership in the split\",\"controller\":\"Controlling address (0x0 if immutable)\",\"distributorFee\":\"Keeper fee paid by split to cover gas costs of distribution\",\"percentAllocations\":\"Percent allocations associated with each address\"},\"returns\":{\"split\":\"Address of newly created split\"}},\"distributeERC20(address,address,address[],uint32[],uint32,address)\":{\"details\":\"`accounts`, `percentAllocations`, and `distributorFee` are verified by hashing  & comparing to the hash in storage associated with split `split`pernicious ERC20s may cause overflow in this function inside  _scaleAmountByPercentage, but results do not affect ETH & other ERC20 balances\",\"params\":{\"accounts\":\"Ordered, unique list of addresses with ownership in the split\",\"distributorAddress\":\"Address to pay `distributorFee` to\",\"distributorFee\":\"Keeper fee paid by split to cover gas costs of distribution\",\"percentAllocations\":\"Percent allocations associated with each address\",\"split\":\"Address of split to distribute balance for\",\"token\":\"Address of ERC20 to distribute balance for\"}},\"distributeETH(address,address[],uint32[],uint32,address)\":{\"details\":\"`accounts`, `percentAllocations`, and `distributorFee` are verified by hashing  & comparing to the hash in storage associated with split `split`\",\"params\":{\"accounts\":\"Ordered, unique list of addresses with ownership in the split\",\"distributorAddress\":\"Address to pay `distributorFee` to\",\"distributorFee\":\"Keeper fee paid by split to cover gas costs of distribution\",\"percentAllocations\":\"Percent allocations associated with each address\",\"split\":\"Address of split to distribute balance for\"}},\"getController(address)\":{\"params\":{\"split\":\"Split to return controller for\"},\"returns\":{\"_0\":\"Split's controller\"}},\"getERC20Balance(address,address)\":{\"params\":{\"account\":\"Account to return ERC20 `token` balance for\",\"token\":\"Token to return balance for\"},\"returns\":{\"_0\":\"Account's balance of `token`\"}},\"getETHBalance(address)\":{\"params\":{\"account\":\"Account to return ETH balance for\"},\"returns\":{\"_0\":\"Account's balance of ETH\"}},\"getHash(address)\":{\"params\":{\"split\":\"Split to return hash for\"},\"returns\":{\"_0\":\"Split's hash\"}},\"getNewPotentialController(address)\":{\"params\":{\"split\":\"Split to return newPotentialController for\"},\"returns\":{\"_0\":\"Split's newPotentialController\"}},\"makeSplitImmutable(address)\":{\"params\":{\"split\":\"Address of mutable split to turn immutable\"}},\"predictImmutableSplitAddress(address[],uint32[],uint32)\":{\"params\":{\"accounts\":\"Ordered, unique list of addresses with ownership in the split\",\"distributorFee\":\"Keeper fee paid by split to cover gas costs of distribution\",\"percentAllocations\":\"Percent allocations associated with each address\"},\"returns\":{\"split\":\"Predicted address of such an immutable split\"}},\"transferControl(address,address)\":{\"details\":\"Two-step control transfer inspired by [dharma](https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/helpers/TwoStepOwnable.sol)\",\"params\":{\"newController\":\"Address to begin transferring control to\",\"split\":\"Address of mutable split to transfer control for\"}},\"updateAndDistributeERC20(address,address,address[],uint32[],uint32,address)\":{\"details\":\"only callable by SplitControllerpernicious ERC20s may cause overflow in this function inside  _scaleAmountByPercentage, but results do not affect ETH & other ERC20 balances\",\"params\":{\"accounts\":\"Ordered, unique list of addresses with ownership in the split\",\"distributorAddress\":\"Address to pay `distributorFee` to\",\"distributorFee\":\"Keeper fee paid by split to cover gas costs of distribution\",\"percentAllocations\":\"Percent allocations associated with each address\",\"split\":\"Address of split to distribute balance for\",\"token\":\"Address of ERC20 to distribute balance for\"}},\"updateAndDistributeETH(address,address[],uint32[],uint32,address)\":{\"details\":\"only callable by SplitController\",\"params\":{\"accounts\":\"Ordered, unique list of addresses with ownership in the split\",\"distributorAddress\":\"Address to pay `distributorFee` to\",\"distributorFee\":\"Keeper fee paid by split to cover gas costs of distribution\",\"percentAllocations\":\"Percent allocations associated with each address\",\"split\":\"Address of split to distribute balance for\"}},\"updateSplit(address,address[],uint32[],uint32)\":{\"params\":{\"accounts\":\"Ordered, unique list of addresses with ownership in the split\",\"distributorFee\":\"Keeper fee paid by split to cover gas costs of distribution\",\"percentAllocations\":\"Percent allocations associated with each address\",\"split\":\"Address of mutable split to update\"}},\"withdraw(address,uint256,address[])\":{\"params\":{\"account\":\"Address to withdraw on behalf of\",\"tokens\":\"Addresses of ERC20s to withdraw\",\"withdrawETH\":\"Withdraw all ETH if nonzero\"}}},\"title\":\"SplitMain\",\"version\":1},\"userdoc\":{\"errors\":{\"Create2Error()\":[{\"notice\":\"create2 opcode failed\"}],\"CreateError()\":[{\"notice\":\"create opcode failed\"}],\"InvalidNewController(address)\":[{\"notice\":\"Invalid new controlling address `newController` for mutable split\"}],\"InvalidSplit__AccountsAndAllocationsMismatch(uint256,uint256)\":[{\"notice\":\"Array lengths of accounts & percentAllocations don't match (`accountsLength` != `allocationsLength`)\"}],\"InvalidSplit__AccountsOutOfOrder(uint256)\":[{\"notice\":\"Invalid accounts ordering at `index`\"}],\"InvalidSplit__AllocationMustBePositive(uint256)\":[{\"notice\":\"Invalid percentAllocation of zero at `index`\"}],\"InvalidSplit__InvalidAllocationsSum(uint32)\":[{\"notice\":\"Invalid percentAllocations sum `allocationsSum` must equal `PERCENTAGE_SCALE`\"}],\"InvalidSplit__InvalidDistributorFee(uint32)\":[{\"notice\":\"Invalid distributorFee `distributorFee` cannot be greater than 10% (1e5)\"}],\"InvalidSplit__InvalidHash(bytes32)\":[{\"notice\":\"Invalid hash `hash` from split data (accounts, percentAllocations, distributorFee)\"}],\"InvalidSplit__TooFewAccounts(uint256)\":[{\"notice\":\"Invalid number of accounts `accountsLength`, must have at least 2\"}],\"Unauthorized(address)\":[{\"notice\":\"Unauthorized sender `sender`\"}]},\"events\":{\"CancelControlTransfer(address)\":{\"notice\":\"emitted after each canceled split control transfer\"},\"ControlTransfer(address,address,address)\":{\"notice\":\"emitted after each successful split control transfer\"},\"CreateSplit(address)\":{\"notice\":\"emitted after each successful split creation\"},\"DistributeERC20(address,address,uint256,address)\":{\"notice\":\"emitted after each successful ERC20 balance split\"},\"DistributeETH(address,uint256,address)\":{\"notice\":\"emitted after each successful ETH balance split\"},\"InitiateControlTransfer(address,address)\":{\"notice\":\"emitted after each initiated split control transfer\"},\"UpdateSplit(address)\":{\"notice\":\"emitted after each successful split update\"},\"Withdrawal(address,uint256,address[],uint256[])\":{\"notice\":\"emitted after each successful withdrawal\"}},\"kind\":\"user\",\"methods\":{\"PERCENTAGE_SCALE()\":{\"notice\":\"constant to scale uints into percentages (1e6 == 100%)\"},\"acceptControl(address)\":{\"notice\":\"Accepts transfer of the controlling address of mutable split `split`\"},\"cancelControlTransfer(address)\":{\"notice\":\"Cancels transfer of the controlling address of mutable split `split`\"},\"constructor\":{\"notice\":\"CONSTRUCTOR\"},\"createSplit(address[],uint32[],uint32,address)\":{\"notice\":\"Creates a new split with recipients `accounts` with ownerships `percentAllocations`, a keeper fee for splitting of `distributorFee` and the controlling address `controller`\"},\"distributeERC20(address,address,address[],uint32[],uint32,address)\":{\"notice\":\"Distributes the ERC20 `token` balance for split `split`\"},\"distributeETH(address,address[],uint32[],uint32,address)\":{\"notice\":\"Distributes the ETH balance for split `split`\"},\"getController(address)\":{\"notice\":\"Returns the current controller of split `split`\"},\"getERC20Balance(address,address)\":{\"notice\":\"Returns the ERC20 balance of token `token` for account `account`\"},\"getETHBalance(address)\":{\"notice\":\"Returns the current ETH balance of account `account`\"},\"getHash(address)\":{\"notice\":\"Returns the current hash of split `split`\"},\"getNewPotentialController(address)\":{\"notice\":\"Returns the current newPotentialController of split `split`\"},\"makeSplitImmutable(address)\":{\"notice\":\"Turns mutable split `split` immutable\"},\"predictImmutableSplitAddress(address[],uint32[],uint32)\":{\"notice\":\"Predicts the address for an immutable split created with recipients `accounts` with ownerships `percentAllocations` and a keeper fee for splitting of `distributorFee`\"},\"transferControl(address,address)\":{\"notice\":\"Begins transfer of the controlling address of mutable split `split` to `newController`\"},\"updateAndDistributeERC20(address,address,address[],uint32[],uint32,address)\":{\"notice\":\"Updates & distributes the ERC20 `token` balance for split `split`\"},\"updateAndDistributeETH(address,address[],uint32[],uint32,address)\":{\"notice\":\"Updates & distributes the ETH balance for split `split`\"},\"updateSplit(address,address[],uint32[],uint32)\":{\"notice\":\"Updates an existing split with recipients `accounts` with ownerships `percentAllocations` and a keeper fee for splitting of `distributorFee`\"},\"walletImplementation()\":{\"notice\":\"address of wallet implementation for split proxies\"},\"withdraw(address,uint256,address[])\":{\"notice\":\"Withdraw ETH &/ ERC20 balances for account `account`\"}},\"notice\":\"A composable and gas-efficient protocol for deploying splitter contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/splits/SplitMain.sol\":\"SplitMain\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@rari-capital/solmate/src/tokens/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n    /*///////////////////////////////////////////////////////////////\\n                                  EVENTS\\n    //////////////////////////////////////////////////////////////*/\\n\\n    event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n    /*///////////////////////////////////////////////////////////////\\n                             METADATA STORAGE\\n    //////////////////////////////////////////////////////////////*/\\n\\n    string public name;\\n\\n    string public symbol;\\n\\n    uint8 public immutable decimals;\\n\\n    /*///////////////////////////////////////////////////////////////\\n                              ERC20 STORAGE\\n    //////////////////////////////////////////////////////////////*/\\n\\n    uint256 public totalSupply;\\n\\n    mapping(address => uint256) public balanceOf;\\n\\n    mapping(address => mapping(address => uint256)) public allowance;\\n\\n    /*///////////////////////////////////////////////////////////////\\n                             EIP-2612 STORAGE\\n    //////////////////////////////////////////////////////////////*/\\n\\n    bytes32 public constant PERMIT_TYPEHASH =\\n        keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n\\n    uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n    mapping(address => uint256) public nonces;\\n\\n    /*///////////////////////////////////////////////////////////////\\n                               CONSTRUCTOR\\n    //////////////////////////////////////////////////////////////*/\\n\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 _decimals\\n    ) {\\n        name = _name;\\n        symbol = _symbol;\\n        decimals = _decimals;\\n\\n        INITIAL_CHAIN_ID = block.chainid;\\n        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n    }\\n\\n    /*///////////////////////////////////////////////////////////////\\n                              ERC20 LOGIC\\n    //////////////////////////////////////////////////////////////*/\\n\\n    function approve(address spender, uint256 amount) public virtual returns (bool) {\\n        allowance[msg.sender][spender] = amount;\\n\\n        emit Approval(msg.sender, spender, amount);\\n\\n        return true;\\n    }\\n\\n    function transfer(address to, uint256 amount) public virtual returns (bool) {\\n        balanceOf[msg.sender] -= amount;\\n\\n        // Cannot overflow because the sum of all user\\n        // balances can't exceed the max uint256 value.\\n        unchecked {\\n            balanceOf[to] += amount;\\n        }\\n\\n        emit Transfer(msg.sender, to, amount);\\n\\n        return true;\\n    }\\n\\n    function transferFrom(\\n        address from,\\n        address to,\\n        uint256 amount\\n    ) public virtual returns (bool) {\\n        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n        balanceOf[from] -= amount;\\n\\n        // Cannot overflow because the sum of all user\\n        // balances can't exceed the max uint256 value.\\n        unchecked {\\n            balanceOf[to] += amount;\\n        }\\n\\n        emit Transfer(from, to, amount);\\n\\n        return true;\\n    }\\n\\n    /*///////////////////////////////////////////////////////////////\\n                              EIP-2612 LOGIC\\n    //////////////////////////////////////////////////////////////*/\\n\\n    function permit(\\n        address owner,\\n        address spender,\\n        uint256 value,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) public virtual {\\n        require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n        // Unchecked because the only math done is incrementing\\n        // the owner's nonce which cannot realistically overflow.\\n        unchecked {\\n            bytes32 digest = keccak256(\\n                abi.encodePacked(\\n                    \\\"\\\\x19\\\\x01\\\",\\n                    DOMAIN_SEPARATOR(),\\n                    keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\\n                )\\n            );\\n\\n            address recoveredAddress = ecrecover(digest, v, r, s);\\n\\n            require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n            allowance[recoveredAddress][spender] = value;\\n        }\\n\\n        emit Approval(owner, spender, value);\\n    }\\n\\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n    }\\n\\n    function computeDomainSeparator() internal view virtual returns (bytes32) {\\n        return\\n            keccak256(\\n                abi.encode(\\n                    keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n                    keccak256(bytes(name)),\\n                    keccak256(\\\"1\\\"),\\n                    block.chainid,\\n                    address(this)\\n                )\\n            );\\n    }\\n\\n    /*///////////////////////////////////////////////////////////////\\n                       INTERNAL MINT/BURN LOGIC\\n    //////////////////////////////////////////////////////////////*/\\n\\n    function _mint(address to, uint256 amount) internal virtual {\\n        totalSupply += amount;\\n\\n        // Cannot overflow because the sum of all user\\n        // balances can't exceed the max uint256 value.\\n        unchecked {\\n            balanceOf[to] += amount;\\n        }\\n\\n        emit Transfer(address(0), to, amount);\\n    }\\n\\n    function _burn(address from, uint256 amount) internal virtual {\\n        balanceOf[from] -= amount;\\n\\n        // Cannot underflow because a user's balance\\n        // will never be larger than the total supply.\\n        unchecked {\\n            totalSupply -= amount;\\n        }\\n\\n        emit Transfer(from, address(0), amount);\\n    }\\n}\\n\",\"keccak256\":\"0x698cdbf614109fafc2bf00057b60715fa3aba9dad447c42f4f8b749ae16ce84f\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/utils/SafeTransferLib.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"../tokens/ERC20.sol\\\";\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @author Modified from Gnosis (https://github.com/gnosis/gp-v2-contracts/blob/main/src/contracts/libraries/GPv2SafeERC20.sol)\\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\\nlibrary SafeTransferLib {\\n    /*///////////////////////////////////////////////////////////////\\n                            ETH OPERATIONS\\n    //////////////////////////////////////////////////////////////*/\\n\\n    function safeTransferETH(address to, uint256 amount) internal {\\n        bool callStatus;\\n\\n        assembly {\\n            // Transfer the ETH and store if it succeeded or not.\\n            callStatus := call(gas(), to, amount, 0, 0, 0, 0)\\n        }\\n\\n        require(callStatus, \\\"ETH_TRANSFER_FAILED\\\");\\n    }\\n\\n    /*///////////////////////////////////////////////////////////////\\n                           ERC20 OPERATIONS\\n    //////////////////////////////////////////////////////////////*/\\n\\n    function safeTransferFrom(\\n        ERC20 token,\\n        address from,\\n        address to,\\n        uint256 amount\\n    ) internal {\\n        bool callStatus;\\n\\n        assembly {\\n            // Get a pointer to some free memory.\\n            let freeMemoryPointer := mload(0x40)\\n\\n            // Write the abi-encoded calldata to memory piece by piece:\\n            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.\\n            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the \\\"from\\\" argument.\\n            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the \\\"to\\\" argument.\\n            mstore(add(freeMemoryPointer, 68), amount) // Finally append the \\\"amount\\\" argument. No mask as it's a full 32 byte value.\\n\\n            // Call the token and store if it succeeded or not.\\n            // We use 100 because the calldata length is 4 + 32 * 3.\\n            callStatus := call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)\\n        }\\n\\n        require(didLastOptionalReturnCallSucceed(callStatus), \\\"TRANSFER_FROM_FAILED\\\");\\n    }\\n\\n    function safeTransfer(\\n        ERC20 token,\\n        address to,\\n        uint256 amount\\n    ) internal {\\n        bool callStatus;\\n\\n        assembly {\\n            // Get a pointer to some free memory.\\n            let freeMemoryPointer := mload(0x40)\\n\\n            // Write the abi-encoded calldata to memory piece by piece:\\n            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.\\n            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the \\\"to\\\" argument.\\n            mstore(add(freeMemoryPointer, 36), amount) // Finally append the \\\"amount\\\" argument. No mask as it's a full 32 byte value.\\n\\n            // Call the token and store if it succeeded or not.\\n            // We use 68 because the calldata length is 4 + 32 * 2.\\n            callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)\\n        }\\n\\n        require(didLastOptionalReturnCallSucceed(callStatus), \\\"TRANSFER_FAILED\\\");\\n    }\\n\\n    function safeApprove(\\n        ERC20 token,\\n        address to,\\n        uint256 amount\\n    ) internal {\\n        bool callStatus;\\n\\n        assembly {\\n            // Get a pointer to some free memory.\\n            let freeMemoryPointer := mload(0x40)\\n\\n            // Write the abi-encoded calldata to memory piece by piece:\\n            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) // Begin with the function selector.\\n            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the \\\"to\\\" argument.\\n            mstore(add(freeMemoryPointer, 36), amount) // Finally append the \\\"amount\\\" argument. No mask as it's a full 32 byte value.\\n\\n            // Call the token and store if it succeeded or not.\\n            // We use 68 because the calldata length is 4 + 32 * 2.\\n            callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)\\n        }\\n\\n        require(didLastOptionalReturnCallSucceed(callStatus), \\\"APPROVE_FAILED\\\");\\n    }\\n\\n    /*///////////////////////////////////////////////////////////////\\n                         INTERNAL HELPER LOGIC\\n    //////////////////////////////////////////////////////////////*/\\n\\n    function didLastOptionalReturnCallSucceed(bool callStatus) private pure returns (bool success) {\\n        assembly {\\n            // Get how many bytes the call returned.\\n            let returnDataSize := returndatasize()\\n\\n            // If the call reverted:\\n            if iszero(callStatus) {\\n                // Copy the revert message into memory.\\n                returndatacopy(0, 0, returnDataSize)\\n\\n                // Revert with the same message.\\n                revert(0, returnDataSize)\\n            }\\n\\n            switch returnDataSize\\n            case 32 {\\n                // Copy the return data into memory.\\n                returndatacopy(0, 0, returnDataSize)\\n\\n                // Set success to whether it returned true.\\n                success := iszero(iszero(mload(0)))\\n            }\\n            case 0 {\\n                // There was no return data.\\n                success := 1\\n            }\\n            default {\\n                // It returned some malformed input.\\n                success := 0\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xcc39d0f5693925ea1e8c517f7cc24211a9899c83a57e62d806180cdb056b6b75\",\"license\":\"AGPL-3.0-only\"},\"contracts/splits/SplitMain.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.4;\\n\\nimport {ISplitMain} from './interfaces/ISplitMain.sol';\\nimport {SplitWallet} from './SplitWallet.sol';\\nimport {Clones} from './libraries/Clones.sol';\\nimport {ERC20} from '@rari-capital/solmate/src/tokens/ERC20.sol';\\nimport {SafeTransferLib} from '@rari-capital/solmate/src/utils/SafeTransferLib.sol';\\n\\n/**\\n\\n                                             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                  \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                 \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                 \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                  \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n\\n                             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                 \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                  \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                       \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                       \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                       \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                   \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                 \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n\\n           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n       \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                  \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n     \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                  \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n    \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n   \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588            \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n   \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588            \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n   \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n   \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588            \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n   \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588            \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n    \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n      \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                  \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                   \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n\\n                             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                 \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                  \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                       \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                       \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                       \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588           \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                   \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                 \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n\\n                                             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                  \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                 \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588              \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                        \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                         \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588               \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                 \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                          \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588                  \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n                                             \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\n\\n */\\n\\n/**\\n * ERRORS\\n */\\n\\n/// @notice Unauthorized sender `sender`\\n/// @param sender Transaction sender\\nerror Unauthorized(address sender);\\n/// @notice Invalid number of accounts `accountsLength`, must have at least 2\\n/// @param accountsLength Length of accounts array\\nerror InvalidSplit__TooFewAccounts(uint256 accountsLength);\\n/// @notice Array lengths of accounts & percentAllocations don't match (`accountsLength` != `allocationsLength`)\\n/// @param accountsLength Length of accounts array\\n/// @param allocationsLength Length of percentAllocations array\\nerror InvalidSplit__AccountsAndAllocationsMismatch(uint256 accountsLength, uint256 allocationsLength);\\n/// @notice Invalid percentAllocations sum `allocationsSum` must equal `PERCENTAGE_SCALE`\\n/// @param allocationsSum Sum of percentAllocations array\\nerror InvalidSplit__InvalidAllocationsSum(uint32 allocationsSum);\\n/// @notice Invalid accounts ordering at `index`\\n/// @param index Index of out-of-order account\\nerror InvalidSplit__AccountsOutOfOrder(uint256 index);\\n/// @notice Invalid percentAllocation of zero at `index`\\n/// @param index Index of zero percentAllocation\\nerror InvalidSplit__AllocationMustBePositive(uint256 index);\\n/// @notice Invalid distributorFee `distributorFee` cannot be greater than 10% (1e5)\\n/// @param distributorFee Invalid distributorFee amount\\nerror InvalidSplit__InvalidDistributorFee(uint32 distributorFee);\\n/// @notice Invalid hash `hash` from split data (accounts, percentAllocations, distributorFee)\\n/// @param hash Invalid hash\\nerror InvalidSplit__InvalidHash(bytes32 hash);\\n/// @notice Invalid new controlling address `newController` for mutable split\\n/// @param newController Invalid new controller\\nerror InvalidNewController(address newController);\\n\\n/**\\n * @title SplitMain\\n * @author 0xSplits <will@0xSplits.xyz>\\n * @notice A composable and gas-efficient protocol for deploying splitter contracts.\\n * @dev Split recipients, ownerships, and keeper fees are stored onchain as calldata & re-passed as args / validated\\n * via hashing when needed. Each split gets its own address & proxy for maximum composability with other contracts onchain.\\n * For these proxies, we extended EIP-1167 Minimal Proxy Contract to avoid `DELEGATECALL` inside `receive()` to accept\\n * hard gas-capped `sends` & `transfers`.\\n */\\ncontract SplitMain is ISplitMain {\\n    using SafeTransferLib for address;\\n    using SafeTransferLib for ERC20;\\n\\n    /**\\n     * STRUCTS\\n     */\\n\\n    /// @notice holds Split metadata\\n    struct Split {\\n        bytes32 hash;\\n        address controller;\\n        address newPotentialController;\\n    }\\n\\n    /**\\n     * STORAGE\\n     */\\n\\n    /**\\n     * STORAGE - CONSTANTS & IMMUTABLES\\n     */\\n\\n    /// @notice constant to scale uints into percentages (1e6 == 100%)\\n    uint256 public constant PERCENTAGE_SCALE = 1e6;\\n    /// @notice maximum distributor fee; 1e5 = 10% * PERCENTAGE_SCALE\\n    uint256 internal constant MAX_DISTRIBUTOR_FEE = 1e5;\\n    /// @notice address of wallet implementation for split proxies\\n    address public immutable override walletImplementation;\\n\\n    /**\\n     * STORAGE - VARIABLES - PRIVATE & INTERNAL\\n     */\\n\\n    /// @notice mapping to account ETH balances\\n    mapping(address => uint256) internal ethBalances;\\n    /// @notice mapping to account ERC20 balances\\n    mapping(ERC20 => mapping(address => uint256)) internal erc20Balances;\\n    /// @notice mapping to Split metadata\\n    mapping(address => Split) internal splits;\\n\\n    /**\\n     * MODIFIERS\\n     */\\n\\n    /** @notice Reverts if the sender doesn't own the split `split`\\n     *  @param split Address to check for control\\n     */\\n    modifier onlySplitController(address split) {\\n        if (msg.sender != splits[split].controller) revert Unauthorized(msg.sender);\\n        _;\\n    }\\n\\n    /** @notice Reverts if the sender isn't the new potential controller of split `split`\\n     *  @param split Address to check for new potential control\\n     */\\n    modifier onlySplitNewPotentialController(address split) {\\n        if (msg.sender != splits[split].newPotentialController) revert Unauthorized(msg.sender);\\n        _;\\n    }\\n\\n    /** @notice Reverts if the split with recipients represented by `accounts` and `percentAllocations` is malformed\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     */\\n    modifier validSplit(\\n        address[] memory accounts,\\n        uint32[] memory percentAllocations,\\n        uint32 distributorFee\\n    ) {\\n        if (accounts.length < 2) revert InvalidSplit__TooFewAccounts(accounts.length);\\n        if (accounts.length != percentAllocations.length)\\n            revert InvalidSplit__AccountsAndAllocationsMismatch(accounts.length, percentAllocations.length);\\n        // _getSum should overflow if any percentAllocation[i] < 0\\n        if (_getSum(percentAllocations) != PERCENTAGE_SCALE)\\n            revert InvalidSplit__InvalidAllocationsSum(_getSum(percentAllocations));\\n        unchecked {\\n            // overflow should be impossible in for-loop index\\n            // cache accounts length to save gas\\n            uint256 loopLength = accounts.length - 1;\\n            for (uint256 i = 0; i < loopLength; ++i) {\\n                // overflow should be impossible in array access math\\n                if (accounts[i] >= accounts[i + 1]) revert InvalidSplit__AccountsOutOfOrder(i);\\n                if (percentAllocations[i] == uint32(0)) revert InvalidSplit__AllocationMustBePositive(i);\\n            }\\n            // overflow should be impossible in array access math with validated equal array lengths\\n            if (percentAllocations[loopLength] == uint32(0)) revert InvalidSplit__AllocationMustBePositive(loopLength);\\n        }\\n        if (distributorFee > MAX_DISTRIBUTOR_FEE) revert InvalidSplit__InvalidDistributorFee(distributorFee);\\n        _;\\n    }\\n\\n    /** @notice Reverts if `newController` is the zero address\\n     *  @param newController Proposed new controlling address\\n     */\\n    modifier validNewController(address newController) {\\n        if (newController == address(0)) revert InvalidNewController(newController);\\n        _;\\n    }\\n\\n    /**\\n     * CONSTRUCTOR\\n     */\\n\\n    constructor() {\\n        walletImplementation = address(new SplitWallet());\\n    }\\n\\n    /**\\n     * FUNCTIONS\\n     */\\n\\n    /**\\n     * FUNCTIONS - PUBLIC & EXTERNAL\\n     */\\n\\n    /** @notice Receive ETH\\n     *  @dev Used by split proxies in `distributeETH` to transfer ETH to `SplitMain`\\n     *  Funds sent outside of `distributeETH` will be unrecoverable\\n     */\\n    receive() external payable {}\\n\\n    /** @notice Creates a new split with recipients `accounts` with ownerships `percentAllocations`, a keeper fee for splitting of `distributorFee` and the controlling address `controller`\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     *  @param controller Controlling address (0x0 if immutable)\\n     *  @return split Address of newly created split\\n     */\\n    function createSplit(\\n        address[] calldata accounts,\\n        uint32[] calldata percentAllocations,\\n        uint32 distributorFee,\\n        address controller\\n    ) external override validSplit(accounts, percentAllocations, distributorFee) returns (address split) {\\n        bytes32 splitHash = _hashSplit(accounts, percentAllocations, distributorFee);\\n        if (controller == address(0)) {\\n            // create immutable split\\n            split = Clones.cloneDeterministic(walletImplementation, splitHash);\\n        } else {\\n            // create mutable split\\n            split = Clones.clone(walletImplementation);\\n            splits[split].controller = controller;\\n        }\\n        // store split's hash in storage for future verification\\n        splits[split].hash = splitHash;\\n        emit CreateSplit(split);\\n    }\\n\\n    /** @notice Predicts the address for an immutable split created with recipients `accounts` with ownerships `percentAllocations` and a keeper fee for splitting of `distributorFee`\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     *  @return split Predicted address of such an immutable split\\n     */\\n    function predictImmutableSplitAddress(\\n        address[] calldata accounts,\\n        uint32[] calldata percentAllocations,\\n        uint32 distributorFee\\n    ) external view override validSplit(accounts, percentAllocations, distributorFee) returns (address split) {\\n        bytes32 splitHash = _hashSplit(accounts, percentAllocations, distributorFee);\\n        split = Clones.predictDeterministicAddress(walletImplementation, splitHash);\\n    }\\n\\n    /** @notice Updates an existing split with recipients `accounts` with ownerships `percentAllocations` and a keeper fee for splitting of `distributorFee`\\n     *  @param split Address of mutable split to update\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     */\\n    function updateSplit(\\n        address split,\\n        address[] calldata accounts,\\n        uint32[] calldata percentAllocations,\\n        uint32 distributorFee\\n    ) external override onlySplitController(split) validSplit(accounts, percentAllocations, distributorFee) {\\n        _updateSplit(split, accounts, percentAllocations, distributorFee);\\n    }\\n\\n    /** @notice Begins transfer of the controlling address of mutable split `split` to `newController`\\n     *  @dev Two-step control transfer inspired by [dharma](https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/helpers/TwoStepOwnable.sol)\\n     *  @param split Address of mutable split to transfer control for\\n     *  @param newController Address to begin transferring control to\\n     */\\n    function transferControl(address split, address newController)\\n        external\\n        override\\n        onlySplitController(split)\\n        validNewController(newController)\\n    {\\n        splits[split].newPotentialController = newController;\\n        emit InitiateControlTransfer(split, newController);\\n    }\\n\\n    /** @notice Cancels transfer of the controlling address of mutable split `split`\\n     *  @param split Address of mutable split to cancel control transfer for\\n     */\\n    function cancelControlTransfer(address split) external override onlySplitController(split) {\\n        delete splits[split].newPotentialController;\\n        emit CancelControlTransfer(split);\\n    }\\n\\n    /** @notice Accepts transfer of the controlling address of mutable split `split`\\n     *  @param split Address of mutable split to accept control transfer for\\n     */\\n    function acceptControl(address split) external override onlySplitNewPotentialController(split) {\\n        delete splits[split].newPotentialController;\\n        emit ControlTransfer(split, splits[split].controller, msg.sender);\\n        splits[split].controller = msg.sender;\\n    }\\n\\n    /** @notice Turns mutable split `split` immutable\\n     *  @param split Address of mutable split to turn immutable\\n     */\\n    function makeSplitImmutable(address split) external override onlySplitController(split) {\\n        delete splits[split].newPotentialController;\\n        emit ControlTransfer(split, splits[split].controller, address(0));\\n        splits[split].controller = address(0);\\n    }\\n\\n    /** @notice Distributes the ETH balance for split `split`\\n     *  @dev `accounts`, `percentAllocations`, and `distributorFee` are verified by hashing\\n     *  & comparing to the hash in storage associated with split `split`\\n     *  @param split Address of split to distribute balance for\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     *  @param distributorAddress Address to pay `distributorFee` to\\n     */\\n    function distributeETH(\\n        address split,\\n        address[] calldata accounts,\\n        uint32[] calldata percentAllocations,\\n        uint32 distributorFee,\\n        address distributorAddress\\n    ) external override validSplit(accounts, percentAllocations, distributorFee) {\\n        // use internal fn instead of modifier to avoid stack depth compiler errors\\n        _validSplitHash(split, accounts, percentAllocations, distributorFee);\\n        _distributeETH(split, accounts, percentAllocations, distributorFee, distributorAddress);\\n    }\\n\\n    /** @notice Updates & distributes the ETH balance for split `split`\\n     *  @dev only callable by SplitController\\n     *  @param split Address of split to distribute balance for\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     *  @param distributorAddress Address to pay `distributorFee` to\\n     */\\n    function updateAndDistributeETH(\\n        address split,\\n        address[] calldata accounts,\\n        uint32[] calldata percentAllocations,\\n        uint32 distributorFee,\\n        address distributorAddress\\n    ) external override onlySplitController(split) validSplit(accounts, percentAllocations, distributorFee) {\\n        _updateSplit(split, accounts, percentAllocations, distributorFee);\\n        // know splitHash is valid immediately after updating; only accessible via controller\\n        _distributeETH(split, accounts, percentAllocations, distributorFee, distributorAddress);\\n    }\\n\\n    /** @notice Distributes the ERC20 `token` balance for split `split`\\n     *  @dev `accounts`, `percentAllocations`, and `distributorFee` are verified by hashing\\n     *  & comparing to the hash in storage associated with split `split`\\n     *  @dev pernicious ERC20s may cause overflow in this function inside\\n     *  _scaleAmountByPercentage, but results do not affect ETH & other ERC20 balances\\n     *  @param split Address of split to distribute balance for\\n     *  @param token Address of ERC20 to distribute balance for\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     *  @param distributorAddress Address to pay `distributorFee` to\\n     */\\n    function distributeERC20(\\n        address split,\\n        ERC20 token,\\n        address[] calldata accounts,\\n        uint32[] calldata percentAllocations,\\n        uint32 distributorFee,\\n        address distributorAddress\\n    ) external override validSplit(accounts, percentAllocations, distributorFee) {\\n        // use internal fn instead of modifier to avoid stack depth compiler errors\\n        _validSplitHash(split, accounts, percentAllocations, distributorFee);\\n        _distributeERC20(split, token, accounts, percentAllocations, distributorFee, distributorAddress);\\n    }\\n\\n    /** @notice Updates & distributes the ERC20 `token` balance for split `split`\\n     *  @dev only callable by SplitController\\n     *  @dev pernicious ERC20s may cause overflow in this function inside\\n     *  _scaleAmountByPercentage, but results do not affect ETH & other ERC20 balances\\n     *  @param split Address of split to distribute balance for\\n     *  @param token Address of ERC20 to distribute balance for\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     *  @param distributorAddress Address to pay `distributorFee` to\\n     */\\n    function updateAndDistributeERC20(\\n        address split,\\n        ERC20 token,\\n        address[] calldata accounts,\\n        uint32[] calldata percentAllocations,\\n        uint32 distributorFee,\\n        address distributorAddress\\n    ) external override onlySplitController(split) validSplit(accounts, percentAllocations, distributorFee) {\\n        _updateSplit(split, accounts, percentAllocations, distributorFee);\\n        // know splitHash is valid immediately after updating; only accessible via controller\\n        _distributeERC20(split, token, accounts, percentAllocations, distributorFee, distributorAddress);\\n    }\\n\\n    /** @notice Withdraw ETH &/ ERC20 balances for account `account`\\n     *  @param account Address to withdraw on behalf of\\n     *  @param withdrawETH Withdraw all ETH if nonzero\\n     *  @param tokens Addresses of ERC20s to withdraw\\n     */\\n    function withdraw(\\n        address account,\\n        uint256 withdrawETH,\\n        ERC20[] calldata tokens\\n    ) external override {\\n        uint256[] memory tokenAmounts = new uint256[](tokens.length);\\n        uint256 ethAmount;\\n        if (withdrawETH != 0) {\\n            ethAmount = _withdraw(account);\\n        }\\n        unchecked {\\n            // overflow should be impossible in for-loop index\\n            for (uint256 i = 0; i < tokens.length; ++i) {\\n                // overflow should be impossible in array length math\\n                tokenAmounts[i] = _withdrawERC20(account, tokens[i]);\\n            }\\n            emit Withdrawal(account, ethAmount, tokens, tokenAmounts);\\n        }\\n    }\\n\\n    /**\\n     * FUNCTIONS - VIEWS\\n     */\\n\\n    /** @notice Returns the current hash of split `split`\\n     *  @param split Split to return hash for\\n     *  @return Split's hash\\n     */\\n    function getHash(address split) external view returns (bytes32) {\\n        return splits[split].hash;\\n    }\\n\\n    /** @notice Returns the current controller of split `split`\\n     *  @param split Split to return controller for\\n     *  @return Split's controller\\n     */\\n    function getController(address split) external view returns (address) {\\n        return splits[split].controller;\\n    }\\n\\n    /** @notice Returns the current newPotentialController of split `split`\\n     *  @param split Split to return newPotentialController for\\n     *  @return Split's newPotentialController\\n     */\\n    function getNewPotentialController(address split) external view returns (address) {\\n        return splits[split].newPotentialController;\\n    }\\n\\n    /** @notice Returns the current ETH balance of account `account`\\n     *  @param account Account to return ETH balance for\\n     *  @return Account's balance of ETH\\n     */\\n    function getETHBalance(address account) external view returns (uint256) {\\n        return ethBalances[account] + (splits[account].hash != 0 ? account.balance : 0);\\n    }\\n\\n    /** @notice Returns the ERC20 balance of token `token` for account `account`\\n     *  @param account Account to return ERC20 `token` balance for\\n     *  @param token Token to return balance for\\n     *  @return Account's balance of `token`\\n     */\\n    function getERC20Balance(address account, ERC20 token) external view returns (uint256) {\\n        return erc20Balances[token][account] + (splits[account].hash != 0 ? token.balanceOf(account) : 0);\\n    }\\n\\n    /**\\n     * FUNCTIONS - PRIVATE & INTERNAL\\n     */\\n\\n    /** @notice Sums array of uint32s\\n     *  @param numbers Array of uint32s to sum\\n     *  @return sum Sum of `numbers`.\\n     */\\n    function _getSum(uint32[] memory numbers) internal pure returns (uint32 sum) {\\n        // overflow should be impossible in for-loop index\\n        uint256 numbersLength = numbers.length;\\n        for (uint256 i = 0; i < numbersLength; ) {\\n            sum += numbers[i];\\n            unchecked {\\n                // overflow should be impossible in for-loop index\\n                ++i;\\n            }\\n        }\\n    }\\n\\n    /** @notice Hashes a split\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     *  @return computedHash Hash of the split.\\n     */\\n    function _hashSplit(\\n        address[] memory accounts,\\n        uint32[] memory percentAllocations,\\n        uint32 distributorFee\\n    ) internal pure returns (bytes32) {\\n        return keccak256(abi.encodePacked(accounts, percentAllocations, distributorFee));\\n    }\\n\\n    /** @notice Updates an existing split with recipients `accounts` with ownerships `percentAllocations` and a keeper fee for splitting of `distributorFee`\\n     *  @param split Address of mutable split to update\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     */\\n    function _updateSplit(\\n        address split,\\n        address[] calldata accounts,\\n        uint32[] calldata percentAllocations,\\n        uint32 distributorFee\\n    ) internal {\\n        bytes32 splitHash = _hashSplit(accounts, percentAllocations, distributorFee);\\n        // store new hash in storage for future verification\\n        splits[split].hash = splitHash;\\n        emit UpdateSplit(split);\\n    }\\n\\n    /** @notice Checks hash from `accounts`, `percentAllocations`, and `distributorFee` against the hash stored for `split`\\n     *  @param split Address of hash to check\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     */\\n    function _validSplitHash(\\n        address split,\\n        address[] memory accounts,\\n        uint32[] memory percentAllocations,\\n        uint32 distributorFee\\n    ) internal view {\\n        bytes32 hash = _hashSplit(accounts, percentAllocations, distributorFee);\\n        if (splits[split].hash != hash) revert InvalidSplit__InvalidHash(hash);\\n    }\\n\\n    /** @notice Distributes the ETH balance for split `split`\\n     *  @dev `accounts`, `percentAllocations`, and `distributorFee` must be verified before calling\\n     *  @param split Address of split to distribute balance for\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     *  @param distributorAddress Address to pay `distributorFee` to\\n     */\\n    function _distributeETH(\\n        address split,\\n        address[] memory accounts,\\n        uint32[] memory percentAllocations,\\n        uint32 distributorFee,\\n        address distributorAddress\\n    ) internal {\\n        uint256 mainBalance = ethBalances[split];\\n        uint256 proxyBalance = split.balance;\\n        // if mainBalance is positive, leave 1 in SplitMain for gas efficiency\\n        uint256 amountToSplit;\\n        unchecked {\\n            // underflow should be impossible\\n            if (mainBalance > 0) mainBalance -= 1;\\n            // overflow should be impossible\\n            amountToSplit = mainBalance + proxyBalance;\\n        }\\n        if (mainBalance > 0) ethBalances[split] = 1;\\n        // emit event with gross amountToSplit (before deducting distributorFee)\\n        emit DistributeETH(split, amountToSplit, distributorAddress);\\n        if (distributorFee != 0) {\\n            // given `amountToSplit`, calculate keeper fee\\n            uint256 distributorFeeAmount = _scaleAmountByPercentage(amountToSplit, distributorFee);\\n            unchecked {\\n                // credit keeper with fee\\n                // overflow should be impossible with validated distributorFee\\n                ethBalances[distributorAddress != address(0) ? distributorAddress : msg.sender] += distributorFeeAmount;\\n                // given keeper fee, calculate how much to distribute to split recipients\\n                // underflow should be impossible with validated distributorFee\\n                amountToSplit -= distributorFeeAmount;\\n            }\\n        }\\n        unchecked {\\n            // distribute remaining balance\\n            // overflow should be impossible in for-loop index\\n            // cache accounts length to save gas\\n            uint256 accountsLength = accounts.length;\\n            for (uint256 i = 0; i < accountsLength; ++i) {\\n                // overflow should be impossible with validated allocations\\n                ethBalances[accounts[i]] += _scaleAmountByPercentage(amountToSplit, percentAllocations[i]);\\n            }\\n        }\\n        // flush proxy ETH balance to SplitMain\\n        // split proxy should be guaranteed to exist at this address after validating splitHash\\n        // (attacker can't deploy own contract to address with high balance & empty sendETHToMain\\n        // to drain ETH from SplitMain)\\n        // could technically check if (change in proxy balance == change in SplitMain balance)\\n        // before/after external call, but seems like extra gas for no practical benefit\\n        if (proxyBalance > 0) SplitWallet(split).sendETHToMain(proxyBalance);\\n    }\\n\\n    /** @notice Distributes the ERC20 `token` balance for split `split`\\n     *  @dev `accounts`, `percentAllocations`, and `distributorFee` must be verified before calling\\n     *  @dev pernicious ERC20s may cause overflow in this function inside\\n     *  _scaleAmountByPercentage, but results do not affect ETH & other ERC20 balances\\n     *  @param split Address of split to distribute balance for\\n     *  @param token Address of ERC20 to distribute balance for\\n     *  @param accounts Ordered, unique list of addresses with ownership in the split\\n     *  @param percentAllocations Percent allocations associated with each address\\n     *  @param distributorFee Keeper fee paid by split to cover gas costs of distribution\\n     *  @param distributorAddress Address to pay `distributorFee` to\\n     */\\n    function _distributeERC20(\\n        address split,\\n        ERC20 token,\\n        address[] memory accounts,\\n        uint32[] memory percentAllocations,\\n        uint32 distributorFee,\\n        address distributorAddress\\n    ) internal {\\n        uint256 amountToSplit;\\n        uint256 mainBalance = erc20Balances[token][split];\\n        uint256 proxyBalance = token.balanceOf(split);\\n        unchecked {\\n            // if mainBalance &/ proxyBalance are positive, leave 1 for gas efficiency\\n            // underflow should be impossible\\n            if (proxyBalance > 0) proxyBalance -= 1;\\n            // underflow should be impossible\\n            if (mainBalance > 0) {\\n                mainBalance -= 1;\\n            }\\n            // overflow should be impossible\\n            amountToSplit = mainBalance + proxyBalance;\\n        }\\n        if (mainBalance > 0) erc20Balances[token][split] = 1;\\n        // emit event with gross amountToSplit (before deducting distributorFee)\\n        emit DistributeERC20(split, token, amountToSplit, distributorAddress);\\n        if (distributorFee != 0) {\\n            // given `amountToSplit`, calculate keeper fee\\n            uint256 distributorFeeAmount = _scaleAmountByPercentage(amountToSplit, distributorFee);\\n            // overflow should be impossible with validated distributorFee\\n            unchecked {\\n                // credit keeper with fee\\n                erc20Balances[token][\\n                    distributorAddress != address(0) ? distributorAddress : msg.sender\\n                ] += distributorFeeAmount;\\n                // given keeper fee, calculate how much to distribute to split recipients\\n                amountToSplit -= distributorFeeAmount;\\n            }\\n        }\\n        // distribute remaining balance\\n        // overflows should be impossible in for-loop with validated allocations\\n        unchecked {\\n            // cache accounts length to save gas\\n            uint256 accountsLength = accounts.length;\\n            for (uint256 i = 0; i < accountsLength; ++i) {\\n                erc20Balances[token][accounts[i]] += _scaleAmountByPercentage(amountToSplit, percentAllocations[i]);\\n            }\\n        }\\n        // split proxy should be guaranteed to exist at this address after validating splitHash\\n        // (attacker can't deploy own contract to address with high ERC20 balance & empty\\n        // sendERC20ToMain to drain ERC20 from SplitMain)\\n        // doesn't support rebasing or fee-on-transfer tokens\\n        // flush extra proxy ERC20 balance to SplitMain\\n        if (proxyBalance > 0) SplitWallet(split).sendERC20ToMain(token, proxyBalance);\\n    }\\n\\n    /** @notice Multiplies an amount by a scaled percentage\\n     *  @param amount Amount to get `scaledPercentage` of\\n     *  @param scaledPercent Percent scaled by PERCENTAGE_SCALE\\n     *  @return scaledAmount Percent of `amount`.\\n     */\\n    function _scaleAmountByPercentage(uint256 amount, uint256 scaledPercent)\\n        internal\\n        pure\\n        returns (uint256 scaledAmount)\\n    {\\n        // use assembly to bypass checking for overflow & division by 0\\n        // scaledPercent has been validated to be < PERCENTAGE_SCALE)\\n        // & PERCENTAGE_SCALE will never be 0\\n        // pernicious ERC20s may cause overflow, but results do not affect ETH & other ERC20 balances\\n        assembly {\\n            /* eg (100 * 2*1e4) / (1e6) */\\n            scaledAmount := div(mul(amount, scaledPercent), PERCENTAGE_SCALE)\\n        }\\n    }\\n\\n    /** @notice Withdraw ETH for account `account`\\n     *  @param account Account to withdrawn ETH for\\n     *  @return withdrawn Amount of ETH withdrawn\\n     */\\n    function _withdraw(address account) internal returns (uint256 withdrawn) {\\n        // leave balance of 1 for gas efficiency\\n        // underflow if ethBalance is 0\\n        withdrawn = ethBalances[account] - 1;\\n        ethBalances[account] = 1;\\n        account.safeTransferETH(withdrawn);\\n    }\\n\\n    /** @notice Withdraw ERC20 `token` for account `account`\\n     *  @param account Account to withdrawn ERC20 `token` for\\n     *  @return withdrawn Amount of ERC20 `token` withdrawn\\n     */\\n    function _withdrawERC20(address account, ERC20 token) internal returns (uint256 withdrawn) {\\n        // leave balance of 1 for gas efficiency\\n        // underflow if erc20Balance is 0\\n        withdrawn = erc20Balances[token][account] - 1;\\n        erc20Balances[token][account] = 1;\\n        token.safeTransfer(account, withdrawn);\\n    }\\n}\\n\",\"keccak256\":\"0x23ab14ee2f3b556baae8fdce6cc4195faa5ba23692c5974258e7b74d14412571\",\"license\":\"GPL-3.0-or-later\"},\"contracts/splits/SplitWallet.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.4;\\n\\nimport {ISplitMain} from './interfaces/ISplitMain.sol';\\nimport {ERC20} from '@rari-capital/solmate/src/tokens/ERC20.sol';\\nimport {SafeTransferLib} from '@rari-capital/solmate/src/utils/SafeTransferLib.sol';\\n\\n/**\\n * ERRORS\\n */\\n\\n/// @notice Unauthorized sender\\nerror Unauthorized();\\n\\n/**\\n * @title SplitWallet\\n * @author 0xSplits <will@0xSplits.xyz>\\n * @notice The implementation logic for `SplitProxy`.\\n * @dev `SplitProxy` handles `receive()` itself to avoid the gas cost with `DELEGATECALL`.\\n */\\ncontract SplitWallet {\\n  using SafeTransferLib for address;\\n  using SafeTransferLib for ERC20;\\n\\n  /**\\n   * EVENTS\\n   */\\n\\n  /** @notice emitted after each successful ETH transfer to proxy\\n   *  @param split Address of the split that received ETH\\n   *  @param amount Amount of ETH received\\n   */\\n  event ReceiveETH(address indexed split, uint256 amount);\\n\\n  /**\\n   * STORAGE\\n   */\\n\\n  /**\\n   * STORAGE - CONSTANTS & IMMUTABLES\\n   */\\n\\n  /// @notice address of SplitMain for split distributions & EOA/SC withdrawals\\n  ISplitMain public immutable splitMain;\\n\\n  /**\\n   * MODIFIERS\\n   */\\n\\n  /// @notice Reverts if the sender isn't SplitMain\\n  modifier onlySplitMain() {\\n    if (msg.sender != address(splitMain)) revert Unauthorized();\\n    _;\\n  }\\n\\n  /**\\n   * CONSTRUCTOR\\n   */\\n\\n  constructor() {\\n    splitMain = ISplitMain(msg.sender);\\n  }\\n\\n  /**\\n   * FUNCTIONS - PUBLIC & EXTERNAL\\n   */\\n\\n  /** @notice Sends amount `amount` of ETH in proxy to SplitMain\\n   *  @dev payable reduces gas cost; no vulnerability to accidentally lock\\n   *  ETH introduced since fn call is restricted to SplitMain\\n   *  @param amount Amount to send\\n   */\\n  function sendETHToMain(uint256 amount) external payable onlySplitMain() {\\n    address(splitMain).safeTransferETH(amount);\\n  }\\n\\n  /** @notice Sends amount `amount` of ERC20 `token` in proxy to SplitMain\\n   *  @dev payable reduces gas cost; no vulnerability to accidentally lock\\n   *  ETH introduced since fn call is restricted to SplitMain\\n   *  @param token Token to send\\n   *  @param amount Amount to send\\n   */\\n  function sendERC20ToMain(ERC20 token, uint256 amount)\\n    external\\n    payable\\n    onlySplitMain()\\n  {\\n    token.safeTransfer(address(splitMain), amount);\\n  }\\n}\\n\",\"keccak256\":\"0xefa0f2a152fe5bc66d949ffbfa0419328b26f130856a58b5c4d77bfe887c3564\",\"license\":\"GPL-3.0-or-later\"},\"contracts/splits/interfaces/ISplitMain.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.4;\\n\\nimport {ERC20} from '@rari-capital/solmate/src/tokens/ERC20.sol';\\n\\n/**\\n * @title ISplitMain\\n * @author 0xSplits <will@0xSplits.xyz>\\n */\\ninterface ISplitMain {\\n  /**\\n   * FUNCTIONS\\n   */\\n\\n  function walletImplementation() external returns (address);\\n\\n  function createSplit(\\n    address[] calldata accounts,\\n    uint32[] calldata percentAllocations,\\n    uint32 distributorFee,\\n    address controller\\n  ) external returns (address);\\n\\n  function predictImmutableSplitAddress(\\n    address[] calldata accounts,\\n    uint32[] calldata percentAllocations,\\n    uint32 distributorFee\\n  ) external view returns (address);\\n\\n  function updateSplit(\\n    address split,\\n    address[] calldata accounts,\\n    uint32[] calldata percentAllocations,\\n    uint32 distributorFee\\n  ) external;\\n\\n  function transferControl(address split, address newController) external;\\n\\n  function cancelControlTransfer(address split) external;\\n\\n  function acceptControl(address split) external;\\n\\n  function makeSplitImmutable(address split) external;\\n\\n  function distributeETH(\\n    address split,\\n    address[] calldata accounts,\\n    uint32[] calldata percentAllocations,\\n    uint32 distributorFee,\\n    address distributorAddress\\n  ) external;\\n\\n  function updateAndDistributeETH(\\n    address split,\\n    address[] calldata accounts,\\n    uint32[] calldata percentAllocations,\\n    uint32 distributorFee,\\n    address distributorAddress\\n  ) external;\\n\\n  function distributeERC20(\\n    address split,\\n    ERC20 token,\\n    address[] calldata accounts,\\n    uint32[] calldata percentAllocations,\\n    uint32 distributorFee,\\n    address distributorAddress\\n  ) external;\\n\\n  function updateAndDistributeERC20(\\n    address split,\\n    ERC20 token,\\n    address[] calldata accounts,\\n    uint32[] calldata percentAllocations,\\n    uint32 distributorFee,\\n    address distributorAddress\\n  ) external;\\n\\n  function withdraw(\\n    address account,\\n    uint256 withdrawETH,\\n    ERC20[] calldata tokens\\n  ) external;\\n\\n  /**\\n   * EVENTS\\n   */\\n\\n  /** @notice emitted after each successful split creation\\n   *  @param split Address of the created split\\n   */\\n  event CreateSplit(address indexed split);\\n\\n  /** @notice emitted after each successful split update\\n   *  @param split Address of the updated split\\n   */\\n  event UpdateSplit(address indexed split);\\n\\n  /** @notice emitted after each initiated split control transfer\\n   *  @param split Address of the split control transfer was initiated for\\n   *  @param newPotentialController Address of the split's new potential controller\\n   */\\n  event InitiateControlTransfer(\\n    address indexed split,\\n    address indexed newPotentialController\\n  );\\n\\n  /** @notice emitted after each canceled split control transfer\\n   *  @param split Address of the split control transfer was canceled for\\n   */\\n  event CancelControlTransfer(address indexed split);\\n\\n  /** @notice emitted after each successful split control transfer\\n   *  @param split Address of the split control was transferred for\\n   *  @param previousController Address of the split's previous controller\\n   *  @param newController Address of the split's new controller\\n   */\\n  event ControlTransfer(\\n    address indexed split,\\n    address indexed previousController,\\n    address indexed newController\\n  );\\n\\n  /** @notice emitted after each successful ETH balance split\\n   *  @param split Address of the split that distributed its balance\\n   *  @param amount Amount of ETH distributed\\n   *  @param distributorAddress Address to credit distributor fee to\\n   */\\n  event DistributeETH(\\n    address indexed split,\\n    uint256 amount,\\n    address indexed distributorAddress\\n  );\\n\\n  /** @notice emitted after each successful ERC20 balance split\\n   *  @param split Address of the split that distributed its balance\\n   *  @param token Address of ERC20 distributed\\n   *  @param amount Amount of ERC20 distributed\\n   *  @param distributorAddress Address to credit distributor fee to\\n   */\\n  event DistributeERC20(\\n    address indexed split,\\n    ERC20 indexed token,\\n    uint256 amount,\\n    address indexed distributorAddress\\n  );\\n\\n  /** @notice emitted after each successful withdrawal\\n   *  @param account Address that funds were withdrawn to\\n   *  @param ethAmount Amount of ETH withdrawn\\n   *  @param tokens Addresses of ERC20s withdrawn\\n   *  @param tokenAmounts Amounts of corresponding ERC20s withdrawn\\n   */\\n  event Withdrawal(\\n    address indexed account,\\n    uint256 ethAmount,\\n    ERC20[] tokens,\\n    uint256[] tokenAmounts\\n  );\\n}\\n\",\"keccak256\":\"0xf8c3a1cf7c88874e0bde6ec12c2a44d36df9b4a135097b69f0a9c049bf2b16b1\",\"license\":\"GPL-3.0-or-later\"},\"contracts/splits/libraries/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity 0.8.4;\\n\\n/// @notice create opcode failed\\nerror CreateError();\\n/// @notice create2 opcode failed\\nerror Create2Error();\\n\\nlibrary Clones {\\n  /**\\n   * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`\\n   * except when someone calls `receive()` and then it emits an event matching\\n   * `SplitWallet.ReceiveETH(indexed address, amount)`\\n   * Inspired by OZ & 0age's minimal clone implementations based on eip 1167 found at\\n   * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.3.0/contracts/proxy/Clones.sol\\n   * and https://medium.com/coinmonks/the-more-minimal-proxy-5756ae08ee48\\n   *\\n   * This function uses the create2 opcode and a `salt` to deterministically deploy\\n   * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n   * the clones cannot be deployed twice at the same address.\\n   *\\n   * init: 0x3d605d80600a3d3981f3\\n   * 3d   returndatasize  0\\n   * 605d push1 0x5d      0x5d 0\\n   * 80   dup1            0x5d 0x5d 0\\n   * 600a push1 0x0a      0x0a 0x5d 0x5d 0\\n   * 3d   returndatasize  0 0x0a 0x5d 0x5d 0\\n   * 39   codecopy        0x5d 0                      destOffset offset length     memory[destOffset:destOffset+length] = address(this).code[offset:offset+length]       copy executing contracts bytecode\\n   * 81   dup2            0 0x5d 0\\n   * f3   return          0                           offset length                return memory[offset:offset+length]                                                   returns from this contract call\\n   *\\n   * contract: 0x36603057343d52307f830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b160203da23d3df35b3d3d3d3d363d3d37363d73bebebebebebebebebebebebebebebebebebebebe5af43d3d93803e605b57fd5bf3\\n   *     0x000     36       calldatasize      cds\\n   *     0x001     6030     push1 0x30        0x30 cds\\n   * ,=< 0x003     57       jumpi\\n   * |   0x004     34       callvalue         cv\\n   * |   0x005     3d       returndatasize    0 cv\\n   * |   0x006     52       mstore\\n   * |   0x007     30       address           addr\\n   * |   0x008     7f830d.. push32 0x830d..   id addr\\n   * |   0x029     6020     push1 0x20        0x20 id addr\\n   * |   0x02b     3d       returndatasize    0 0x20 id addr\\n   * |   0x02c     a2       log2\\n   * |   0x02d     3d       returndatasize    0\\n   * |   0x02e     3d       returndatasize    0 0\\n   * |   0x02f     f3       return\\n   * `-> 0x030     5b       jumpdest\\n   *     0x031     3d       returndatasize    0\\n   *     0x032     3d       returndatasize    0 0\\n   *     0x033     3d       returndatasize    0 0 0\\n   *     0x034     3d       returndatasize    0 0 0 0\\n   *     0x035     36       calldatasize      cds 0 0 0 0\\n   *     0x036     3d       returndatasize    0 cds 0 0 0 0\\n   *     0x037     3d       returndatasize    0 0 cds 0 0 0 0\\n   *     0x038     37       calldatacopy      0 0 0 0\\n   *     0x039     36       calldatasize      cds 0 0 0 0\\n   *     0x03a     3d       returndatasize    0 cds 0 0 0 0\\n   *     0x03b     73bebe.. push20 0xbebe..   0xbebe 0 cds 0 0 0 0\\n   *     0x050     5a       gas               gas 0xbebe 0 cds 0 0 0 0\\n   *     0x051     f4       delegatecall      suc 0 0\\n   *     0x052     3d       returndatasize    rds suc 0 0\\n   *     0x053     3d       returndatasize    rds rds suc 0 0\\n   *     0x054     93       swap4             0 rds suc 0 rds\\n   *     0x055     80       dup1              0 0 rds suc 0 rds\\n   *     0x056     3e       returndatacopy    suc 0 rds\\n   *     0x057     605b     push1 0x5b        0x5b suc 0 rds\\n   * ,=< 0x059     57       jumpi             0 rds\\n   * |   0x05a     fd       revert\\n   * `-> 0x05b     5b       jumpdest          0 rds\\n   *     0x05c     f3       return\\n   *\\n   */\\n  function clone(address implementation) internal returns (address instance) {\\n    assembly {\\n      let ptr := mload(0x40)\\n      mstore(\\n        ptr,\\n        0x3d605d80600a3d3981f336603057343d52307f00000000000000000000000000\\n      )\\n      mstore(\\n        add(ptr, 0x13),\\n        0x830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b1\\n      )\\n      mstore(\\n        add(ptr, 0x33),\\n        0x60203da23d3df35b3d3d3d3d363d3d37363d7300000000000000000000000000\\n      )\\n      mstore(add(ptr, 0x46), shl(0x60, implementation))\\n      mstore(\\n        add(ptr, 0x5a),\\n        0x5af43d3d93803e605b57fd5bf300000000000000000000000000000000000000\\n      )\\n      instance := create(0, ptr, 0x67)\\n    }\\n    if (instance == address(0)) revert CreateError();\\n  }\\n\\n  function cloneDeterministic(address implementation, bytes32 salt)\\n    internal\\n    returns (address instance)\\n  {\\n    assembly {\\n      let ptr := mload(0x40)\\n      mstore(\\n        ptr,\\n        0x3d605d80600a3d3981f336603057343d52307f00000000000000000000000000\\n      )\\n      mstore(\\n        add(ptr, 0x13),\\n        0x830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b1\\n      )\\n      mstore(\\n        add(ptr, 0x33),\\n        0x60203da23d3df35b3d3d3d3d363d3d37363d7300000000000000000000000000\\n      )\\n      mstore(add(ptr, 0x46), shl(0x60, implementation))\\n      mstore(\\n        add(ptr, 0x5a),\\n        0x5af43d3d93803e605b57fd5bf300000000000000000000000000000000000000\\n      )\\n      instance := create2(0, ptr, 0x67, salt)\\n    }\\n    if (instance == address(0)) revert Create2Error();\\n  }\\n\\n  /**\\n   * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n   */\\n  function predictDeterministicAddress(\\n    address implementation,\\n    bytes32 salt,\\n    address deployer\\n  ) internal pure returns (address predicted) {\\n    assembly {\\n      let ptr := mload(0x40)\\n      mstore(\\n        ptr,\\n        0x3d605d80600a3d3981f336603057343d52307f00000000000000000000000000\\n      )\\n      mstore(\\n        add(ptr, 0x13),\\n        0x830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b1\\n      )\\n      mstore(\\n        add(ptr, 0x33),\\n        0x60203da23d3df35b3d3d3d3d363d3d37363d7300000000000000000000000000\\n      )\\n      mstore(add(ptr, 0x46), shl(0x60, implementation))\\n      mstore(\\n        add(ptr, 0x5a),\\n        0x5af43d3d93803e605b57fd5bf3ff000000000000000000000000000000000000\\n      )\\n      mstore(add(ptr, 0x68), shl(0x60, deployer))\\n      mstore(add(ptr, 0x7c), salt)\\n      mstore(add(ptr, 0x9c), keccak256(ptr, 0x67))\\n      predicted := keccak256(add(ptr, 0x67), 0x55)\\n    }\\n  }\\n\\n  /**\\n   * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n   */\\n  function predictDeterministicAddress(address implementation, bytes32 salt)\\n    internal\\n    view\\n    returns (address predicted)\\n  {\\n    return predictDeterministicAddress(implementation, salt, address(this));\\n  }\\n}\\n\",\"keccak256\":\"0xb5dcbb1cc134cf221c67dceb9206d4b4037038bd84539073ec0ad2a365e78f81\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}",
  "bytecode": "0x60a06040523480156200001157600080fd5b50604051620000209062000054565b604051809103906000f0801580156200003d573d6000803e3d6000fd5b5060601b6001600160601b03191660805262000062565b6103a080620030e983390190565b60805160601c61305362000096600039600081816102b001528181610c1a0152818161106c015261109d01526130536000f3fe6080604052600436106101185760003560e01c806377b1e4e9116100a0578063c7de644011610064578063c7de64401461034e578063d0e4b2f41461036e578063e10e51d61461038e578063e61cb05e146103cb578063ecef0ace146103eb57600080fd5b806377b1e4e91461027e5780638117abc11461029e57806388c662aa146102d2578063a5e3909e1461030e578063c3a8962c1461032e57600080fd5b80633bb66a7b116100e75780633bb66a7b146101cf5780633f26479e146101ef57806352844dd3146102065780636e5f69191461023e5780637601f7821461025e57600080fd5b80631267c6da146101245780631581130214610146578063189cbaa0146101665780631da0b8fc1461018657600080fd5b3661011f57005b600080fd5b34801561013057600080fd5b5061014461013f366004612ab2565b61040b565b005b34801561015257600080fd5b50610144610161366004612c4c565b6104a6565b34801561017257600080fd5b50610144610181366004612ab2565b61081a565b34801561019257600080fd5b506101bc6101a1366004612ab2565b6001600160a01b031660009081526002602052604090205490565b6040519081526020015b60405180910390f35b3480156101db57600080fd5b506101bc6101ea366004612ab2565b6108e5565b3480156101fb57600080fd5b506101bc620f424081565b34801561021257600080fd5b50610226610221366004612d5d565b61093e565b6040516001600160a01b0390911681526020016101c6565b34801561024a57600080fd5b50610144610259366004612d03565b610c4d565b34801561026a57600080fd5b50610226610279366004612ddb565b610d82565b34801561028a57600080fd5b50610144610299366004612c4c565b611144565b3480156102aa57600080fd5b506102267f000000000000000000000000000000000000000000000000000000000000000081565b3480156102de57600080fd5b506102266102ed366004612ab2565b6001600160a01b039081166000908152600260205260409020600101541690565b34801561031a57600080fd5b50610144610329366004612b95565b611487565b34801561033a57600080fd5b506101bc610349366004612c3a565b6117aa565b34801561035a57600080fd5b50610144610369366004612ab2565b61187e565b34801561037a57600080fd5b50610144610389366004612ace565b61194d565b34801561039a57600080fd5b506102266103a9366004612ab2565b6001600160a01b03908116600090815260026020819052604090912001541690565b3480156103d757600080fd5b506101446103e6366004612b95565b611a1f565b3480156103f757600080fd5b50610144610406366004612b06565b611d6f565b6001600160a01b0381811660009081526002602052604090206001015482911633146104515760405163472511eb60e11b81523360048201526024015b60405180910390fd5b6001600160a01b038216600081815260026020819052604080832090910180546001600160a01b0319169055517f6c2460a415b84be3720c209fe02f2cad7a6bcba21e8637afe8957b7ec4b6ef879190a25050565b85858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250508351869250600211159050610535578251604051630e8c626560e41b815260040161044891815260200190565b8151835114610564578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f424061057183612020565b63ffffffff16146105a75761058582612020565b60405163fcc487c160e01b815263ffffffff9091166004820152602401610448565b82516000190160005b8181101561069e578481600101815181106105db57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031685828151811061060c57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161061063e5760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff1684828151811061066657634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff16141561069657604051630db7e4c760e01b815260048101829052602401610448565b6001016105b0565b50600063ffffffff168382815181106106c757634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff1614156106f757604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff16111561072a5760405163308440e360e21b815263ffffffff82166004820152602401610448565b61079a8b8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250612073915050565b61080d8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c92508b91506120c59050565b5050505050505050505050565b6001600160a01b03818116600090815260026020526040902060010154829116331461085b5760405163472511eb60e11b8152336004820152602401610448565b6001600160a01b03808316600081815260026020819052604080832091820180546001600160a01b0319169055600190910154905191931691907f943d69cf2bbe08a9d44b3c4ce6da17d939d758739370620871ce99a6437866d0908490a4506001600160a01b0316600090815260026020526040902060010180546001600160a01b0319169055565b6001600160a01b038116600090815260026020526040812054610909576000610915565b816001600160a01b0316315b6001600160a01b0383166000908152602081905260409020546109389190612f98565b92915050565b6000858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284376000920191909152505083518692506002111590506109cf578251604051630e8c626560e41b815260040161044891815260200190565b81518351146109fe578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f4240610a0b83612020565b63ffffffff1614610a1f5761058582612020565b82516000190160005b81811015610b1657848160010181518110610a5357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316858281518110610a8457634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031610610ab65760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff16848281518110610ade57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415610b0e57604051630db7e4c760e01b815260048101829052602401610448565b600101610a28565b50600063ffffffff16838281518110610b3f57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415610b6f57604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff161115610ba25760405163308440e360e21b815263ffffffff82166004820152602401610448565b6000610c138a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b925061239f915050565b9050610c3f7f0000000000000000000000000000000000000000000000000000000000000000826123d5565b9a9950505050505050505050565b60008167ffffffffffffffff811115610c7657634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610c9f578160200160208202803683370190505b50905060008415610cb657610cb38661247a565b90505b60005b83811015610d3257610cff87868684818110610ce557634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610cfa9190612ab2565b6124cd565b838281518110610d1f57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152600101610cb9565b50856001600160a01b03167fa9e30bf144f83390a4fe47562a4e16892108102221c674ff538da0b72a83d17482868686604051610d729493929190612f08565b60405180910390a2505050505050565b600086868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250508351879250600211159050610e13578251604051630e8c626560e41b815260040161044891815260200190565b8151835114610e42578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f4240610e4f83612020565b63ffffffff1614610e635761058582612020565b82516000190160005b81811015610f5a57848160010181518110610e9757634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316858281518110610ec857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031610610efa5760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff16848281518110610f2257634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415610f5257604051630db7e4c760e01b815260048101829052602401610448565b600101610e6c565b50600063ffffffff16838281518110610f8357634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415610fb357604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff161115610fe65760405163308440e360e21b815263ffffffff82166004820152602401610448565b60006110578b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c925061239f915050565b90506001600160a01b038616611098576110917f000000000000000000000000000000000000000000000000000000000000000082612539565b94506110f5565b6110c17f00000000000000000000000000000000000000000000000000000000000000006125e9565b6001600160a01b03818116600090815260026020526040902060010180546001600160a01b03191691891691909117905594505b6001600160a01b038516600081815260026020526040808220849055517f8d5f9943c664a3edaf4d3eb18cc5e2c45a7d2dc5869be33d33bbc0fff9bc25909190a2505050509695505050505050565b6001600160a01b0388811660009081526002602052604090206001015489911633146111855760405163472511eb60e11b8152336004820152602401610448565b86868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250508351879250600211159050611214578251604051630e8c626560e41b815260040161044891815260200190565b8151835114611243578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f424061125083612020565b63ffffffff16146112645761058582612020565b82516000190160005b8181101561135b5784816001018151811061129857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03168582815181106112c957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316106112fb5760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff1684828151811061132357634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff16141561135357604051630db7e4c760e01b815260048101829052602401610448565b60010161126d565b50600063ffffffff1683828151811061138457634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff1614156113b457604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff1611156113e75760405163308440e360e21b815263ffffffff82166004820152602401610448565b6113f58c8b8b8b8b8b612698565b6114798c8c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508d92508c91506120c59050565b505050505050505050505050565b6001600160a01b0387811660009081526002602052604090206001015488911633146114c85760405163472511eb60e11b8152336004820152602401610448565b86868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250508351879250600211159050611557578251604051630e8c626560e41b815260040161044891815260200190565b8151835114611586578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f424061159383612020565b63ffffffff16146115a75761058582612020565b82516000190160005b8181101561169e578481600101815181106115db57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031685828151811061160c57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161061163e5760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff1684828151811061166657634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff16141561169657604051630db7e4c760e01b815260048101829052602401610448565b6001016115b0565b50600063ffffffff168382815181106116c757634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff1614156116f757604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff16111561172a5760405163308440e360e21b815263ffffffff82166004820152602401610448565b6117388b8b8b8b8b8b612698565b61080d8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c92508b91506127589050565b6001600160a01b0382166000908152600260205260408120546117ce576000611847565b6040516370a0823160e01b81526001600160a01b0384811660048301528316906370a082319060240160206040518083038186803b15801561180f57600080fd5b505afa158015611823573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118479190612e6c565b6001600160a01b038084166000908152600160209081526040808320938816835292905220546118779190612f98565b9392505050565b6001600160a01b038181166000908152600260208190526040909120015482911633146118c05760405163472511eb60e11b8152336004820152602401610448565b6001600160a01b03808316600081815260026020819052604080832091820180546001600160a01b0319169055600190910154905133949190911692917f943d69cf2bbe08a9d44b3c4ce6da17d939d758739370620871ce99a6437866d091a4506001600160a01b0316600090815260026020526040902060010180546001600160a01b03191633179055565b6001600160a01b03828116600090815260026020526040902060010154839116331461198e5760405163472511eb60e11b8152336004820152602401610448565b816001600160a01b0381166119c15760405163c369130760e01b81526001600160a01b0382166004820152602401610448565b6001600160a01b03848116600081815260026020819052604080832090910180546001600160a01b0319169488169485179055517f107cf6ea8668d533df1aab5bb8b6315bb0c25f0b6c955558d09368f290668fc79190a350505050565b85858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250508351869250600211159050611aae578251604051630e8c626560e41b815260040161044891815260200190565b8151835114611add578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f4240611aea83612020565b63ffffffff1614611afe5761058582612020565b82516000190160005b81811015611bf557848160010181518110611b3257634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316858281518110611b6357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031610611b955760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff16848281518110611bbd57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415611bed57604051630db7e4c760e01b815260048101829052602401610448565b600101611b07565b50600063ffffffff16838281518110611c1e57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415611c4e57604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff161115611c815760405163308440e360e21b815263ffffffff82166004820152602401610448565b611cf18a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250612073915050565b611d638a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92508a91506127589050565b50505050505050505050565b6001600160a01b038681166000908152600260205260409020600101548791163314611db05760405163472511eb60e11b8152336004820152602401610448565b85858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250508351869250600211159050611e3f578251604051630e8c626560e41b815260040161044891815260200190565b8151835114611e6e578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f4240611e7b83612020565b63ffffffff1614611e8f5761058582612020565b82516000190160005b81811015611f8657848160010181518110611ec357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316858281518110611ef457634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031610611f265760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff16848281518110611f4e57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415611f7e57604051630db7e4c760e01b815260048101829052602401610448565b600101611e98565b50600063ffffffff16838281518110611faf57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415611fdf57604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff1611156120125760405163308440e360e21b815263ffffffff82166004820152602401610448565b611d638a8a8a8a8a8a612698565b8051600090815b8181101561206c5783818151811061204f57634e487b7160e01b600052603260045260246000fd5b6020026020010151836120629190612fb0565b9250600101612027565b5050919050565b600061208084848461239f565b6001600160a01b03861660009081526002602052604090205490915081146120be5760405163dd5ff45760e01b815260048101829052602401610448565b5050505050565b6001600160a01b038581166000818152600160209081526040808320948b16808452949091528082205490516370a0823160e01b815260048101949094529092909183916370a082319060240160206040518083038186803b15801561212a57600080fd5b505afa15801561213e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121629190612e6c565b9050801561216f57600019015b811561217c576001820391505b818101925081156121b0576001600160a01b038089166000908152600160208181526040808420948e168452939052919020555b836001600160a01b0316886001600160a01b03168a6001600160a01b03167fb5ee5dc3d2c31a019bbf2c787e0e9c97971c96aceea1c38c12fc8fd25c536d46866040516121ff91815260200190565b60405180910390a463ffffffff851615612271576001600160a01b038881166000908152600160205260408120620f424063ffffffff891687020492839290881661224a573361224c565b875b6001600160a01b03168152602081019190915260400160002080549091019055909203915b865160005b81811015612329576122ba858983815181106122a257634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff16620f424091020490565b6001600160a01b038b1660009081526001602052604081208b519091908c90859081106122f757634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516001600160a01b0316825281019190915260400160002080549091019055600101612276565b5050801561239457604051633e0f9fff60e11b81526001600160a01b038981166004830152602482018390528a1690637c1f3ffe90604401600060405180830381600087803b15801561237b57600080fd5b505af115801561238f573d6000803e3d6000fd5b505050505b505050505050505050565b60008383836040516020016123b693929190612e84565b6040516020818303038152906040528051906020012090509392505050565b6000611877838330604051723d605d80600a3d3981f336603057343d52307f60681b81527f830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b160138201527260203da23d3df35b3d3d3d3d363d3d37363d7360681b6033820152606093841b60468201526d5af43d3d93803e605b57fd5bf3ff60901b605a820152921b6068830152607c8201526067808220609c830152605591012090565b6001600160a01b03811660009081526020819052604081205461249f90600190612fd8565b6001600160a01b0383166000818152602081905260409020600190559091506124c8908261293a565b919050565b6001600160a01b038082166000908152600160208181526040808420948716845293905291812054909161250091612fd8565b6001600160a01b038084166000818152600160208181526040808420958a16845294905292902091909155909150610938908483612990565b6000604051723d605d80600a3d3981f336603057343d52307f60681b81527f830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b160138201527260203da23d3df35b3d3d3d3d363d3d37363d7360681b60338201528360601b60468201526c5af43d3d93803e605b57fd5bf360981b605a820152826067826000f59150506001600160a01b0381166109385760405163380bbe1360e01b815260040160405180910390fd5b6000604051723d605d80600a3d3981f336603057343d52307f60681b81527f830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b160138201527260203da23d3df35b3d3d3d3d363d3d37363d7360681b60338201528260601b60468201526c5af43d3d93803e605b57fd5bf360981b605a8201526067816000f09150506001600160a01b0381166124c857604051630985da9b60e41b815260040160405180910390fd5b600061270986868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a0282810182019093528982529093508992508891829185019084908082843760009201919091525087925061239f915050565b6001600160a01b0388166000818152600260205260408082208490555192935090917f45e1e99513dd915ac128b94953ca64c6375717ea1894b3114db08cdca51debd29190a250505050505050565b6001600160a01b0385166000818152602081905260408120549131908215612781576001830392505b5081810182156127a8576001600160a01b0388166000908152602081905260409020600190555b836001600160a01b0316886001600160a01b03167f87c3ca0a87d9b82033e4bc55e6d30621f8d7e0c9d8ca7988edfde8932787b77b836040516127ed91815260200190565b60405180910390a363ffffffff85161561284c57620f424063ffffffff8616820204806000806001600160a01b0388166128275733612829565b875b6001600160a01b0316815260208101919091526040016000208054909101905590035b865160005b818110156128d25761287d838983815181106122a257634e487b7160e01b600052603260045260246000fd5b6000808b84815181106128a057634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516001600160a01b0316825281019190915260400160002080549091019055600101612851565b5050811561293057604051632ac3affd60e21b8152600481018390526001600160a01b0389169063ab0ebff490602401600060405180830381600087803b15801561291c57600080fd5b505af1158015611479573d6000803e3d6000fd5b5050505050505050565b600080600080600085875af190508061298b5760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610448565b505050565b600060405163a9059cbb60e01b81526001600160a01b03841660048201528260248201526000806044836000895af19150506129cb81612a0f565b612a095760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610448565b50505050565b60003d82612a2157806000803e806000fd5b8060208114612a39578015612a4a576000925061206c565b816000803e6000511515925061206c565b5060019392505050565b60008083601f840112612a65578182fd5b50813567ffffffffffffffff811115612a7c578182fd5b6020830191508360208260051b8501011115612a9757600080fd5b9250929050565b803563ffffffff811681146124c857600080fd5b600060208284031215612ac3578081fd5b813561187781613005565b60008060408385031215612ae0578081fd5b8235612aeb81613005565b91506020830135612afb81613005565b809150509250929050565b60008060008060008060808789031215612b1e578182fd5b8635612b2981613005565b9550602087013567ffffffffffffffff80821115612b45578384fd5b612b518a838b01612a54565b90975095506040890135915080821115612b69578384fd5b50612b7689828a01612a54565b9094509250612b89905060608801612a9e565b90509295509295509295565b600080600080600080600060a0888a031215612baf578081fd5b8735612bba81613005565b9650602088013567ffffffffffffffff80821115612bd6578283fd5b612be28b838c01612a54565b909850965060408a0135915080821115612bfa578283fd5b50612c078a828b01612a54565b9095509350612c1a905060608901612a9e565b91506080880135612c2a81613005565b8091505092959891949750929550565b60008060408385031215612ae0578182fd5b60008060008060008060008060c0898b031215612c67578081fd5b8835612c7281613005565b97506020890135612c8281613005565b9650604089013567ffffffffffffffff80821115612c9e578283fd5b612caa8c838d01612a54565b909850965060608b0135915080821115612cc2578283fd5b50612ccf8b828c01612a54565b9095509350612ce2905060808a01612a9e565b915060a0890135612cf281613005565b809150509295985092959890939650565b60008060008060608587031215612d18578384fd5b8435612d2381613005565b935060208501359250604085013567ffffffffffffffff811115612d45578283fd5b612d5187828801612a54565b95989497509550505050565b600080600080600060608688031215612d74578081fd5b853567ffffffffffffffff80821115612d8b578283fd5b612d9789838a01612a54565b90975095506020880135915080821115612daf578283fd5b50612dbc88828901612a54565b9094509250612dcf905060408701612a9e565b90509295509295909350565b60008060008060008060808789031215612df3578182fd5b863567ffffffffffffffff80821115612e0a578384fd5b612e168a838b01612a54565b90985096506020890135915080821115612e2e578384fd5b50612e3b89828a01612a54565b9095509350612e4e905060408801612a9e565b91506060870135612e5e81613005565b809150509295509295509295565b600060208284031215612e7d578081fd5b5051919050565b835160009082906020808801845b83811015612eb75781516001600160a01b031685529382019390820190600101612e92565b50508651818801939250845b81811015612ee557845163ffffffff1684529382019392820192600101612ec3565b50505060e09490941b6001600160e01b0319168452505060049091019392505050565b84815260606020808301829052908201849052600090859060808401835b87811015612f54578335612f3981613005565b6001600160a01b031682529282019290820190600101612f26565b5084810360408601528551808252908201925081860190845b81811015612f8957825185529383019391830191600101612f6d565b50929998505050505050505050565b60008219821115612fab57612fab612fef565b500190565b600063ffffffff808316818516808303821115612fcf57612fcf612fef565b01949350505050565b600082821015612fea57612fea612fef565b500390565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461301a57600080fd5b5056fea2646970667358221220f4f1c42f1a29b064ee2cac8edb468897bcfaa5dd92e9d45ff85b41340608db6664736f6c6343000804003360a060405234801561001057600080fd5b5033606081901b60805261035461004c60003960008181604b0152818160bc015281816101080152818161013c015261018601526103546000f3fe6080604052600436106100345760003560e01c80630e769b2b146100395780637c1f3ffe14610089578063ab0ebff41461009e575b600080fd5b34801561004557600080fd5b5061006d7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61009c6100973660046102d0565b6100b1565b005b61009c6100ac366004610306565b610131565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146100f9576040516282b42960e81b815260040160405180910390fd5b61012d6001600160a01b0383167f0000000000000000000000000000000000000000000000000000000000000000836101af565b5050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610179576040516282b42960e81b815260040160405180910390fd5b6101ac6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001682610233565b50565b600060405163a9059cbb60e01b81526001600160a01b03841660048201528260248201526000806044836000895af19150506101ea81610289565b61022d5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064015b60405180910390fd5b50505050565b600080600080600085875af19050806102845760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610224565b505050565b60003d8261029b57806000803e806000fd5b80602081146102b35780156102c457600092506102c9565b816000803e600051151592506102c9565b600192505b5050919050565b600080604083850312156102e2578182fd5b82356001600160a01b03811681146102f8578283fd5b946020939093013593505050565b600060208284031215610317578081fd5b503591905056fea26469706673582212200905f7a81498365f93a993d61fda991a578e8df58db305c616fb2f570e7c563a64736f6c63430008040033",
  "deployedBytecode": "0x6080604052600436106101185760003560e01c806377b1e4e9116100a0578063c7de644011610064578063c7de64401461034e578063d0e4b2f41461036e578063e10e51d61461038e578063e61cb05e146103cb578063ecef0ace146103eb57600080fd5b806377b1e4e91461027e5780638117abc11461029e57806388c662aa146102d2578063a5e3909e1461030e578063c3a8962c1461032e57600080fd5b80633bb66a7b116100e75780633bb66a7b146101cf5780633f26479e146101ef57806352844dd3146102065780636e5f69191461023e5780637601f7821461025e57600080fd5b80631267c6da146101245780631581130214610146578063189cbaa0146101665780631da0b8fc1461018657600080fd5b3661011f57005b600080fd5b34801561013057600080fd5b5061014461013f366004612ab2565b61040b565b005b34801561015257600080fd5b50610144610161366004612c4c565b6104a6565b34801561017257600080fd5b50610144610181366004612ab2565b61081a565b34801561019257600080fd5b506101bc6101a1366004612ab2565b6001600160a01b031660009081526002602052604090205490565b6040519081526020015b60405180910390f35b3480156101db57600080fd5b506101bc6101ea366004612ab2565b6108e5565b3480156101fb57600080fd5b506101bc620f424081565b34801561021257600080fd5b50610226610221366004612d5d565b61093e565b6040516001600160a01b0390911681526020016101c6565b34801561024a57600080fd5b50610144610259366004612d03565b610c4d565b34801561026a57600080fd5b50610226610279366004612ddb565b610d82565b34801561028a57600080fd5b50610144610299366004612c4c565b611144565b3480156102aa57600080fd5b506102267f000000000000000000000000000000000000000000000000000000000000000081565b3480156102de57600080fd5b506102266102ed366004612ab2565b6001600160a01b039081166000908152600260205260409020600101541690565b34801561031a57600080fd5b50610144610329366004612b95565b611487565b34801561033a57600080fd5b506101bc610349366004612c3a565b6117aa565b34801561035a57600080fd5b50610144610369366004612ab2565b61187e565b34801561037a57600080fd5b50610144610389366004612ace565b61194d565b34801561039a57600080fd5b506102266103a9366004612ab2565b6001600160a01b03908116600090815260026020819052604090912001541690565b3480156103d757600080fd5b506101446103e6366004612b95565b611a1f565b3480156103f757600080fd5b50610144610406366004612b06565b611d6f565b6001600160a01b0381811660009081526002602052604090206001015482911633146104515760405163472511eb60e11b81523360048201526024015b60405180910390fd5b6001600160a01b038216600081815260026020819052604080832090910180546001600160a01b0319169055517f6c2460a415b84be3720c209fe02f2cad7a6bcba21e8637afe8957b7ec4b6ef879190a25050565b85858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250508351869250600211159050610535578251604051630e8c626560e41b815260040161044891815260200190565b8151835114610564578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f424061057183612020565b63ffffffff16146105a75761058582612020565b60405163fcc487c160e01b815263ffffffff9091166004820152602401610448565b82516000190160005b8181101561069e578481600101815181106105db57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031685828151811061060c57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161061063e5760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff1684828151811061066657634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff16141561069657604051630db7e4c760e01b815260048101829052602401610448565b6001016105b0565b50600063ffffffff168382815181106106c757634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff1614156106f757604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff16111561072a5760405163308440e360e21b815263ffffffff82166004820152602401610448565b61079a8b8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250612073915050565b61080d8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c92508b91506120c59050565b5050505050505050505050565b6001600160a01b03818116600090815260026020526040902060010154829116331461085b5760405163472511eb60e11b8152336004820152602401610448565b6001600160a01b03808316600081815260026020819052604080832091820180546001600160a01b0319169055600190910154905191931691907f943d69cf2bbe08a9d44b3c4ce6da17d939d758739370620871ce99a6437866d0908490a4506001600160a01b0316600090815260026020526040902060010180546001600160a01b0319169055565b6001600160a01b038116600090815260026020526040812054610909576000610915565b816001600160a01b0316315b6001600160a01b0383166000908152602081905260409020546109389190612f98565b92915050565b6000858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284376000920191909152505083518692506002111590506109cf578251604051630e8c626560e41b815260040161044891815260200190565b81518351146109fe578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f4240610a0b83612020565b63ffffffff1614610a1f5761058582612020565b82516000190160005b81811015610b1657848160010181518110610a5357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316858281518110610a8457634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031610610ab65760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff16848281518110610ade57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415610b0e57604051630db7e4c760e01b815260048101829052602401610448565b600101610a28565b50600063ffffffff16838281518110610b3f57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415610b6f57604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff161115610ba25760405163308440e360e21b815263ffffffff82166004820152602401610448565b6000610c138a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b925061239f915050565b9050610c3f7f0000000000000000000000000000000000000000000000000000000000000000826123d5565b9a9950505050505050505050565b60008167ffffffffffffffff811115610c7657634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610c9f578160200160208202803683370190505b50905060008415610cb657610cb38661247a565b90505b60005b83811015610d3257610cff87868684818110610ce557634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610cfa9190612ab2565b6124cd565b838281518110610d1f57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152600101610cb9565b50856001600160a01b03167fa9e30bf144f83390a4fe47562a4e16892108102221c674ff538da0b72a83d17482868686604051610d729493929190612f08565b60405180910390a2505050505050565b600086868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250508351879250600211159050610e13578251604051630e8c626560e41b815260040161044891815260200190565b8151835114610e42578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f4240610e4f83612020565b63ffffffff1614610e635761058582612020565b82516000190160005b81811015610f5a57848160010181518110610e9757634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316858281518110610ec857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031610610efa5760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff16848281518110610f2257634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415610f5257604051630db7e4c760e01b815260048101829052602401610448565b600101610e6c565b50600063ffffffff16838281518110610f8357634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415610fb357604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff161115610fe65760405163308440e360e21b815263ffffffff82166004820152602401610448565b60006110578b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c925061239f915050565b90506001600160a01b038616611098576110917f000000000000000000000000000000000000000000000000000000000000000082612539565b94506110f5565b6110c17f00000000000000000000000000000000000000000000000000000000000000006125e9565b6001600160a01b03818116600090815260026020526040902060010180546001600160a01b03191691891691909117905594505b6001600160a01b038516600081815260026020526040808220849055517f8d5f9943c664a3edaf4d3eb18cc5e2c45a7d2dc5869be33d33bbc0fff9bc25909190a2505050509695505050505050565b6001600160a01b0388811660009081526002602052604090206001015489911633146111855760405163472511eb60e11b8152336004820152602401610448565b86868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250508351879250600211159050611214578251604051630e8c626560e41b815260040161044891815260200190565b8151835114611243578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f424061125083612020565b63ffffffff16146112645761058582612020565b82516000190160005b8181101561135b5784816001018151811061129857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03168582815181106112c957634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316106112fb5760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff1684828151811061132357634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff16141561135357604051630db7e4c760e01b815260048101829052602401610448565b60010161126d565b50600063ffffffff1683828151811061138457634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff1614156113b457604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff1611156113e75760405163308440e360e21b815263ffffffff82166004820152602401610448565b6113f58c8b8b8b8b8b612698565b6114798c8c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508d92508c91506120c59050565b505050505050505050505050565b6001600160a01b0387811660009081526002602052604090206001015488911633146114c85760405163472511eb60e11b8152336004820152602401610448565b86868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250508351879250600211159050611557578251604051630e8c626560e41b815260040161044891815260200190565b8151835114611586578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f424061159383612020565b63ffffffff16146115a75761058582612020565b82516000190160005b8181101561169e578481600101815181106115db57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031685828151811061160c57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03161061163e5760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff1684828151811061166657634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff16141561169657604051630db7e4c760e01b815260048101829052602401610448565b6001016115b0565b50600063ffffffff168382815181106116c757634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff1614156116f757604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff16111561172a5760405163308440e360e21b815263ffffffff82166004820152602401610448565b6117388b8b8b8b8b8b612698565b61080d8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c92508b91506127589050565b6001600160a01b0382166000908152600260205260408120546117ce576000611847565b6040516370a0823160e01b81526001600160a01b0384811660048301528316906370a082319060240160206040518083038186803b15801561180f57600080fd5b505afa158015611823573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118479190612e6c565b6001600160a01b038084166000908152600160209081526040808320938816835292905220546118779190612f98565b9392505050565b6001600160a01b038181166000908152600260208190526040909120015482911633146118c05760405163472511eb60e11b8152336004820152602401610448565b6001600160a01b03808316600081815260026020819052604080832091820180546001600160a01b0319169055600190910154905133949190911692917f943d69cf2bbe08a9d44b3c4ce6da17d939d758739370620871ce99a6437866d091a4506001600160a01b0316600090815260026020526040902060010180546001600160a01b03191633179055565b6001600160a01b03828116600090815260026020526040902060010154839116331461198e5760405163472511eb60e11b8152336004820152602401610448565b816001600160a01b0381166119c15760405163c369130760e01b81526001600160a01b0382166004820152602401610448565b6001600160a01b03848116600081815260026020819052604080832090910180546001600160a01b0319169488169485179055517f107cf6ea8668d533df1aab5bb8b6315bb0c25f0b6c955558d09368f290668fc79190a350505050565b85858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250508351869250600211159050611aae578251604051630e8c626560e41b815260040161044891815260200190565b8151835114611add578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f4240611aea83612020565b63ffffffff1614611afe5761058582612020565b82516000190160005b81811015611bf557848160010181518110611b3257634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316858281518110611b6357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031610611b955760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff16848281518110611bbd57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415611bed57604051630db7e4c760e01b815260048101829052602401610448565b600101611b07565b50600063ffffffff16838281518110611c1e57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415611c4e57604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff161115611c815760405163308440e360e21b815263ffffffff82166004820152602401610448565b611cf18a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250612073915050565b611d638a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92508a91506127589050565b50505050505050505050565b6001600160a01b038681166000908152600260205260409020600101548791163314611db05760405163472511eb60e11b8152336004820152602401610448565b85858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250508351869250600211159050611e3f578251604051630e8c626560e41b815260040161044891815260200190565b8151835114611e6e578251825160405163b34f351d60e01b815260048101929092526024820152604401610448565b620f4240611e7b83612020565b63ffffffff1614611e8f5761058582612020565b82516000190160005b81811015611f8657848160010181518110611ec357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316858281518110611ef457634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031610611f265760405163ac6bd23360e01b815260048101829052602401610448565b600063ffffffff16848281518110611f4e57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415611f7e57604051630db7e4c760e01b815260048101829052602401610448565b600101611e98565b50600063ffffffff16838281518110611faf57634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff161415611fdf57604051630db7e4c760e01b815260048101829052602401610448565b50620186a08163ffffffff1611156120125760405163308440e360e21b815263ffffffff82166004820152602401610448565b611d638a8a8a8a8a8a612698565b8051600090815b8181101561206c5783818151811061204f57634e487b7160e01b600052603260045260246000fd5b6020026020010151836120629190612fb0565b9250600101612027565b5050919050565b600061208084848461239f565b6001600160a01b03861660009081526002602052604090205490915081146120be5760405163dd5ff45760e01b815260048101829052602401610448565b5050505050565b6001600160a01b038581166000818152600160209081526040808320948b16808452949091528082205490516370a0823160e01b815260048101949094529092909183916370a082319060240160206040518083038186803b15801561212a57600080fd5b505afa15801561213e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121629190612e6c565b9050801561216f57600019015b811561217c576001820391505b818101925081156121b0576001600160a01b038089166000908152600160208181526040808420948e168452939052919020555b836001600160a01b0316886001600160a01b03168a6001600160a01b03167fb5ee5dc3d2c31a019bbf2c787e0e9c97971c96aceea1c38c12fc8fd25c536d46866040516121ff91815260200190565b60405180910390a463ffffffff851615612271576001600160a01b038881166000908152600160205260408120620f424063ffffffff891687020492839290881661224a573361224c565b875b6001600160a01b03168152602081019190915260400160002080549091019055909203915b865160005b81811015612329576122ba858983815181106122a257634e487b7160e01b600052603260045260246000fd5b602002602001015163ffffffff16620f424091020490565b6001600160a01b038b1660009081526001602052604081208b519091908c90859081106122f757634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516001600160a01b0316825281019190915260400160002080549091019055600101612276565b5050801561239457604051633e0f9fff60e11b81526001600160a01b038981166004830152602482018390528a1690637c1f3ffe90604401600060405180830381600087803b15801561237b57600080fd5b505af115801561238f573d6000803e3d6000fd5b505050505b505050505050505050565b60008383836040516020016123b693929190612e84565b6040516020818303038152906040528051906020012090509392505050565b6000611877838330604051723d605d80600a3d3981f336603057343d52307f60681b81527f830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b160138201527260203da23d3df35b3d3d3d3d363d3d37363d7360681b6033820152606093841b60468201526d5af43d3d93803e605b57fd5bf3ff60901b605a820152921b6068830152607c8201526067808220609c830152605591012090565b6001600160a01b03811660009081526020819052604081205461249f90600190612fd8565b6001600160a01b0383166000818152602081905260409020600190559091506124c8908261293a565b919050565b6001600160a01b038082166000908152600160208181526040808420948716845293905291812054909161250091612fd8565b6001600160a01b038084166000818152600160208181526040808420958a16845294905292902091909155909150610938908483612990565b6000604051723d605d80600a3d3981f336603057343d52307f60681b81527f830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b160138201527260203da23d3df35b3d3d3d3d363d3d37363d7360681b60338201528360601b60468201526c5af43d3d93803e605b57fd5bf360981b605a820152826067826000f59150506001600160a01b0381166109385760405163380bbe1360e01b815260040160405180910390fd5b6000604051723d605d80600a3d3981f336603057343d52307f60681b81527f830d2d700a97af574b186c80d40429385d24241565b08a7c559ba283a964d9b160138201527260203da23d3df35b3d3d3d3d363d3d37363d7360681b60338201528260601b60468201526c5af43d3d93803e605b57fd5bf360981b605a8201526067816000f09150506001600160a01b0381166124c857604051630985da9b60e41b815260040160405180910390fd5b600061270986868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a0282810182019093528982529093508992508891829185019084908082843760009201919091525087925061239f915050565b6001600160a01b0388166000818152600260205260408082208490555192935090917f45e1e99513dd915ac128b94953ca64c6375717ea1894b3114db08cdca51debd29190a250505050505050565b6001600160a01b0385166000818152602081905260408120549131908215612781576001830392505b5081810182156127a8576001600160a01b0388166000908152602081905260409020600190555b836001600160a01b0316886001600160a01b03167f87c3ca0a87d9b82033e4bc55e6d30621f8d7e0c9d8ca7988edfde8932787b77b836040516127ed91815260200190565b60405180910390a363ffffffff85161561284c57620f424063ffffffff8616820204806000806001600160a01b0388166128275733612829565b875b6001600160a01b0316815260208101919091526040016000208054909101905590035b865160005b818110156128d25761287d838983815181106122a257634e487b7160e01b600052603260045260246000fd5b6000808b84815181106128a057634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516001600160a01b0316825281019190915260400160002080549091019055600101612851565b5050811561293057604051632ac3affd60e21b8152600481018390526001600160a01b0389169063ab0ebff490602401600060405180830381600087803b15801561291c57600080fd5b505af1158015611479573d6000803e3d6000fd5b5050505050505050565b600080600080600085875af190508061298b5760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610448565b505050565b600060405163a9059cbb60e01b81526001600160a01b03841660048201528260248201526000806044836000895af19150506129cb81612a0f565b612a095760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610448565b50505050565b60003d82612a2157806000803e806000fd5b8060208114612a39578015612a4a576000925061206c565b816000803e6000511515925061206c565b5060019392505050565b60008083601f840112612a65578182fd5b50813567ffffffffffffffff811115612a7c578182fd5b6020830191508360208260051b8501011115612a9757600080fd5b9250929050565b803563ffffffff811681146124c857600080fd5b600060208284031215612ac3578081fd5b813561187781613005565b60008060408385031215612ae0578081fd5b8235612aeb81613005565b91506020830135612afb81613005565b809150509250929050565b60008060008060008060808789031215612b1e578182fd5b8635612b2981613005565b9550602087013567ffffffffffffffff80821115612b45578384fd5b612b518a838b01612a54565b90975095506040890135915080821115612b69578384fd5b50612b7689828a01612a54565b9094509250612b89905060608801612a9e565b90509295509295509295565b600080600080600080600060a0888a031215612baf578081fd5b8735612bba81613005565b9650602088013567ffffffffffffffff80821115612bd6578283fd5b612be28b838c01612a54565b909850965060408a0135915080821115612bfa578283fd5b50612c078a828b01612a54565b9095509350612c1a905060608901612a9e565b91506080880135612c2a81613005565b8091505092959891949750929550565b60008060408385031215612ae0578182fd5b60008060008060008060008060c0898b031215612c67578081fd5b8835612c7281613005565b97506020890135612c8281613005565b9650604089013567ffffffffffffffff80821115612c9e578283fd5b612caa8c838d01612a54565b909850965060608b0135915080821115612cc2578283fd5b50612ccf8b828c01612a54565b9095509350612ce2905060808a01612a9e565b915060a0890135612cf281613005565b809150509295985092959890939650565b60008060008060608587031215612d18578384fd5b8435612d2381613005565b935060208501359250604085013567ffffffffffffffff811115612d45578283fd5b612d5187828801612a54565b95989497509550505050565b600080600080600060608688031215612d74578081fd5b853567ffffffffffffffff80821115612d8b578283fd5b612d9789838a01612a54565b90975095506020880135915080821115612daf578283fd5b50612dbc88828901612a54565b9094509250612dcf905060408701612a9e565b90509295509295909350565b60008060008060008060808789031215612df3578182fd5b863567ffffffffffffffff80821115612e0a578384fd5b612e168a838b01612a54565b90985096506020890135915080821115612e2e578384fd5b50612e3b89828a01612a54565b9095509350612e4e905060408801612a9e565b91506060870135612e5e81613005565b809150509295509295509295565b600060208284031215612e7d578081fd5b5051919050565b835160009082906020808801845b83811015612eb75781516001600160a01b031685529382019390820190600101612e92565b50508651818801939250845b81811015612ee557845163ffffffff1684529382019392820192600101612ec3565b50505060e09490941b6001600160e01b0319168452505060049091019392505050565b84815260606020808301829052908201849052600090859060808401835b87811015612f54578335612f3981613005565b6001600160a01b031682529282019290820190600101612f26565b5084810360408601528551808252908201925081860190845b81811015612f8957825185529383019391830191600101612f6d565b50929998505050505050505050565b60008219821115612fab57612fab612fef565b500190565b600063ffffffff808316818516808303821115612fcf57612fcf612fef565b01949350505050565b600082821015612fea57612fea612fef565b500390565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461301a57600080fd5b5056fea2646970667358221220f4f1c42f1a29b064ee2cac8edb468897bcfaa5dd92e9d45ff85b41340608db6664736f6c63430008040033",
  "devdoc": {
    "author": "0xSplits <will@0xSplits.xyz>",
    "details": "Split recipients, ownerships, and keeper fees are stored onchain as calldata & re-passed as args / validated via hashing when needed. Each split gets its own address & proxy for maximum composability with other contracts onchain. For these proxies, we extended EIP-1167 Minimal Proxy Contract to avoid `DELEGATECALL` inside `receive()` to accept hard gas-capped `sends` & `transfers`.",
    "errors": {
      "InvalidNewController(address)": [
        {
          "params": {
            "newController": "Invalid new controller"
          }
        }
      ],
      "InvalidSplit__AccountsAndAllocationsMismatch(uint256,uint256)": [
        {
          "params": {
            "accountsLength": "Length of accounts array",
            "allocationsLength": "Length of percentAllocations array"
          }
        }
      ],
      "InvalidSplit__AccountsOutOfOrder(uint256)": [
        {
          "params": {
            "index": "Index of out-of-order account"
          }
        }
      ],
      "InvalidSplit__AllocationMustBePositive(uint256)": [
        {
          "params": {
            "index": "Index of zero percentAllocation"
          }
        }
      ],
      "InvalidSplit__InvalidAllocationsSum(uint32)": [
        {
          "params": {
            "allocationsSum": "Sum of percentAllocations array"
          }
        }
      ],
      "InvalidSplit__InvalidDistributorFee(uint32)": [
        {
          "params": {
            "distributorFee": "Invalid distributorFee amount"
          }
        }
      ],
      "InvalidSplit__InvalidHash(bytes32)": [
        {
          "params": {
            "hash": "Invalid hash"
          }
        }
      ],
      "InvalidSplit__TooFewAccounts(uint256)": [
        {
          "params": {
            "accountsLength": "Length of accounts array"
          }
        }
      ],
      "Unauthorized(address)": [
        {
          "params": {
            "sender": "Transaction sender"
          }
        }
      ]
    },
    "kind": "dev",
    "methods": {
      "acceptControl(address)": {
        "params": {
          "split": "Address of mutable split to accept control transfer for"
        }
      },
      "cancelControlTransfer(address)": {
        "params": {
          "split": "Address of mutable split to cancel control transfer for"
        }
      },
      "createSplit(address[],uint32[],uint32,address)": {
        "params": {
          "accounts": "Ordered, unique list of addresses with ownership in the split",
          "controller": "Controlling address (0x0 if immutable)",
          "distributorFee": "Keeper fee paid by split to cover gas costs of distribution",
          "percentAllocations": "Percent allocations associated with each address"
        },
        "returns": {
          "split": "Address of newly created split"
        }
      },
      "distributeERC20(address,address,address[],uint32[],uint32,address)": {
        "details": "`accounts`, `percentAllocations`, and `distributorFee` are verified by hashing  & comparing to the hash in storage associated with split `split`pernicious ERC20s may cause overflow in this function inside  _scaleAmountByPercentage, but results do not affect ETH & other ERC20 balances",
        "params": {
          "accounts": "Ordered, unique list of addresses with ownership in the split",
          "distributorAddress": "Address to pay `distributorFee` to",
          "distributorFee": "Keeper fee paid by split to cover gas costs of distribution",
          "percentAllocations": "Percent allocations associated with each address",
          "split": "Address of split to distribute balance for",
          "token": "Address of ERC20 to distribute balance for"
        }
      },
      "distributeETH(address,address[],uint32[],uint32,address)": {
        "details": "`accounts`, `percentAllocations`, and `distributorFee` are verified by hashing  & comparing to the hash in storage associated with split `split`",
        "params": {
          "accounts": "Ordered, unique list of addresses with ownership in the split",
          "distributorAddress": "Address to pay `distributorFee` to",
          "distributorFee": "Keeper fee paid by split to cover gas costs of distribution",
          "percentAllocations": "Percent allocations associated with each address",
          "split": "Address of split to distribute balance for"
        }
      },
      "getController(address)": {
        "params": {
          "split": "Split to return controller for"
        },
        "returns": {
          "_0": "Split's controller"
        }
      },
      "getERC20Balance(address,address)": {
        "params": {
          "account": "Account to return ERC20 `token` balance for",
          "token": "Token to return balance for"
        },
        "returns": {
          "_0": "Account's balance of `token`"
        }
      },
      "getETHBalance(address)": {
        "params": {
          "account": "Account to return ETH balance for"
        },
        "returns": {
          "_0": "Account's balance of ETH"
        }
      },
      "getHash(address)": {
        "params": {
          "split": "Split to return hash for"
        },
        "returns": {
          "_0": "Split's hash"
        }
      },
      "getNewPotentialController(address)": {
        "params": {
          "split": "Split to return newPotentialController for"
        },
        "returns": {
          "_0": "Split's newPotentialController"
        }
      },
      "makeSplitImmutable(address)": {
        "params": {
          "split": "Address of mutable split to turn immutable"
        }
      },
      "predictImmutableSplitAddress(address[],uint32[],uint32)": {
        "params": {
          "accounts": "Ordered, unique list of addresses with ownership in the split",
          "distributorFee": "Keeper fee paid by split to cover gas costs of distribution",
          "percentAllocations": "Percent allocations associated with each address"
        },
        "returns": {
          "split": "Predicted address of such an immutable split"
        }
      },
      "transferControl(address,address)": {
        "details": "Two-step control transfer inspired by [dharma](https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/helpers/TwoStepOwnable.sol)",
        "params": {
          "newController": "Address to begin transferring control to",
          "split": "Address of mutable split to transfer control for"
        }
      },
      "updateAndDistributeERC20(address,address,address[],uint32[],uint32,address)": {
        "details": "only callable by SplitControllerpernicious ERC20s may cause overflow in this function inside  _scaleAmountByPercentage, but results do not affect ETH & other ERC20 balances",
        "params": {
          "accounts": "Ordered, unique list of addresses with ownership in the split",
          "distributorAddress": "Address to pay `distributorFee` to",
          "distributorFee": "Keeper fee paid by split to cover gas costs of distribution",
          "percentAllocations": "Percent allocations associated with each address",
          "split": "Address of split to distribute balance for",
          "token": "Address of ERC20 to distribute balance for"
        }
      },
      "updateAndDistributeETH(address,address[],uint32[],uint32,address)": {
        "details": "only callable by SplitController",
        "params": {
          "accounts": "Ordered, unique list of addresses with ownership in the split",
          "distributorAddress": "Address to pay `distributorFee` to",
          "distributorFee": "Keeper fee paid by split to cover gas costs of distribution",
          "percentAllocations": "Percent allocations associated with each address",
          "split": "Address of split to distribute balance for"
        }
      },
      "updateSplit(address,address[],uint32[],uint32)": {
        "params": {
          "accounts": "Ordered, unique list of addresses with ownership in the split",
          "distributorFee": "Keeper fee paid by split to cover gas costs of distribution",
          "percentAllocations": "Percent allocations associated with each address",
          "split": "Address of mutable split to update"
        }
      },
      "withdraw(address,uint256,address[])": {
        "params": {
          "account": "Address to withdraw on behalf of",
          "tokens": "Addresses of ERC20s to withdraw",
          "withdrawETH": "Withdraw all ETH if nonzero"
        }
      }
    },
    "title": "SplitMain",
    "version": 1
  },
  "userdoc": {
    "errors": {
      "Create2Error()": [
        {
          "notice": "create2 opcode failed"
        }
      ],
      "CreateError()": [
        {
          "notice": "create opcode failed"
        }
      ],
      "InvalidNewController(address)": [
        {
          "notice": "Invalid new controlling address `newController` for mutable split"
        }
      ],
      "InvalidSplit__AccountsAndAllocationsMismatch(uint256,uint256)": [
        {
          "notice": "Array lengths of accounts & percentAllocations don't match (`accountsLength` != `allocationsLength`)"
        }
      ],
      "InvalidSplit__AccountsOutOfOrder(uint256)": [
        {
          "notice": "Invalid accounts ordering at `index`"
        }
      ],
      "InvalidSplit__AllocationMustBePositive(uint256)": [
        {
          "notice": "Invalid percentAllocation of zero at `index`"
        }
      ],
      "InvalidSplit__InvalidAllocationsSum(uint32)": [
        {
          "notice": "Invalid percentAllocations sum `allocationsSum` must equal `PERCENTAGE_SCALE`"
        }
      ],
      "InvalidSplit__InvalidDistributorFee(uint32)": [
        {
          "notice": "Invalid distributorFee `distributorFee` cannot be greater than 10% (1e5)"
        }
      ],
      "InvalidSplit__InvalidHash(bytes32)": [
        {
          "notice": "Invalid hash `hash` from split data (accounts, percentAllocations, distributorFee)"
        }
      ],
      "InvalidSplit__TooFewAccounts(uint256)": [
        {
          "notice": "Invalid number of accounts `accountsLength`, must have at least 2"
        }
      ],
      "Unauthorized(address)": [
        {
          "notice": "Unauthorized sender `sender`"
        }
      ]
    },
    "events": {
      "CancelControlTransfer(address)": {
        "notice": "emitted after each canceled split control transfer"
      },
      "ControlTransfer(address,address,address)": {
        "notice": "emitted after each successful split control transfer"
      },
      "CreateSplit(address)": {
        "notice": "emitted after each successful split creation"
      },
      "DistributeERC20(address,address,uint256,address)": {
        "notice": "emitted after each successful ERC20 balance split"
      },
      "DistributeETH(address,uint256,address)": {
        "notice": "emitted after each successful ETH balance split"
      },
      "InitiateControlTransfer(address,address)": {
        "notice": "emitted after each initiated split control transfer"
      },
      "UpdateSplit(address)": {
        "notice": "emitted after each successful split update"
      },
      "Withdrawal(address,uint256,address[],uint256[])": {
        "notice": "emitted after each successful withdrawal"
      }
    },
    "kind": "user",
    "methods": {
      "PERCENTAGE_SCALE()": {
        "notice": "constant to scale uints into percentages (1e6 == 100%)"
      },
      "acceptControl(address)": {
        "notice": "Accepts transfer of the controlling address of mutable split `split`"
      },
      "cancelControlTransfer(address)": {
        "notice": "Cancels transfer of the controlling address of mutable split `split`"
      },
      "constructor": {
        "notice": "CONSTRUCTOR"
      },
      "createSplit(address[],uint32[],uint32,address)": {
        "notice": "Creates a new split with recipients `accounts` with ownerships `percentAllocations`, a keeper fee for splitting of `distributorFee` and the controlling address `controller`"
      },
      "distributeERC20(address,address,address[],uint32[],uint32,address)": {
        "notice": "Distributes the ERC20 `token` balance for split `split`"
      },
      "distributeETH(address,address[],uint32[],uint32,address)": {
        "notice": "Distributes the ETH balance for split `split`"
      },
      "getController(address)": {
        "notice": "Returns the current controller of split `split`"
      },
      "getERC20Balance(address,address)": {
        "notice": "Returns the ERC20 balance of token `token` for account `account`"
      },
      "getETHBalance(address)": {
        "notice": "Returns the current ETH balance of account `account`"
      },
      "getHash(address)": {
        "notice": "Returns the current hash of split `split`"
      },
      "getNewPotentialController(address)": {
        "notice": "Returns the current newPotentialController of split `split`"
      },
      "makeSplitImmutable(address)": {
        "notice": "Turns mutable split `split` immutable"
      },
      "predictImmutableSplitAddress(address[],uint32[],uint32)": {
        "notice": "Predicts the address for an immutable split created with recipients `accounts` with ownerships `percentAllocations` and a keeper fee for splitting of `distributorFee`"
      },
      "transferControl(address,address)": {
        "notice": "Begins transfer of the controlling address of mutable split `split` to `newController`"
      },
      "updateAndDistributeERC20(address,address,address[],uint32[],uint32,address)": {
        "notice": "Updates & distributes the ERC20 `token` balance for split `split`"
      },
      "updateAndDistributeETH(address,address[],uint32[],uint32,address)": {
        "notice": "Updates & distributes the ETH balance for split `split`"
      },
      "updateSplit(address,address[],uint32[],uint32)": {
        "notice": "Updates an existing split with recipients `accounts` with ownerships `percentAllocations` and a keeper fee for splitting of `distributorFee`"
      },
      "walletImplementation()": {
        "notice": "address of wallet implementation for split proxies"
      },
      "withdraw(address,uint256,address[])": {
        "notice": "Withdraw ETH &/ ERC20 balances for account `account`"
      }
    },
    "notice": "A composable and gas-efficient protocol for deploying splitter contracts.",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 587,
        "contract": "contracts/splits/SplitMain.sol:SplitMain",
        "label": "ethBalances",
        "offset": 0,
        "slot": "0",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 595,
        "contract": "contracts/splits/SplitMain.sol:SplitMain",
        "label": "erc20Balances",
        "offset": 0,
        "slot": "1",
        "type": "t_mapping(t_contract(ERC20)394,t_mapping(t_address,t_uint256))"
      },
      {
        "astId": 601,
        "contract": "contracts/splits/SplitMain.sol:SplitMain",
        "label": "splits",
        "offset": 0,
        "slot": "2",
        "type": "t_mapping(t_address,t_struct(Split)570_storage)"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_bytes32": {
        "encoding": "inplace",
        "label": "bytes32",
        "numberOfBytes": "32"
      },
      "t_contract(ERC20)394": {
        "encoding": "inplace",
        "label": "contract ERC20",
        "numberOfBytes": "20"
      },
      "t_mapping(t_address,t_struct(Split)570_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct SplitMain.Split)",
        "numberOfBytes": "32",
        "value": "t_struct(Split)570_storage"
      },
      "t_mapping(t_address,t_uint256)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_mapping(t_contract(ERC20)394,t_mapping(t_address,t_uint256))": {
        "encoding": "mapping",
        "key": "t_contract(ERC20)394",
        "label": "mapping(contract ERC20 => mapping(address => uint256))",
        "numberOfBytes": "32",
        "value": "t_mapping(t_address,t_uint256)"
      },
      "t_struct(Split)570_storage": {
        "encoding": "inplace",
        "label": "struct SplitMain.Split",
        "members": [
          {
            "astId": 565,
            "contract": "contracts/splits/SplitMain.sol:SplitMain",
            "label": "hash",
            "offset": 0,
            "slot": "0",
            "type": "t_bytes32"
          },
          {
            "astId": 567,
            "contract": "contracts/splits/SplitMain.sol:SplitMain",
            "label": "controller",
            "offset": 0,
            "slot": "1",
            "type": "t_address"
          },
          {
            "astId": 569,
            "contract": "contracts/splits/SplitMain.sol:SplitMain",
            "label": "newPotentialController",
            "offset": 0,
            "slot": "2",
            "type": "t_address"
          }
        ],
        "numberOfBytes": "96"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      }
    }
  }
}
