{
  "address": "0x2a1950a06AD5C5113e44721820305645d671eC4F",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_permit2",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_newActivePoolAddress",
          "type": "address"
        }
      ],
      "name": "ActivePoolAddressChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_newBorrowerOperationsAddress",
          "type": "address"
        }
      ],
      "name": "BorrowerOperationsAddressChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_newCommunityIssuanceAddress",
          "type": "address"
        }
      ],
      "name": "CommunityIssuanceAddressChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_newDefaultPoolAddress",
          "type": "address"
        }
      ],
      "name": "DefaultPoolAddressChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_P",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_S",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_G",
          "type": "uint256"
        }
      ],
      "name": "DepositSnapshotUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_ETH",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_ZUSDLoss",
          "type": "uint256"
        }
      ],
      "name": "ETHGainWithdrawn",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint128",
          "name": "_currentEpoch",
          "type": "uint128"
        }
      ],
      "name": "EpochUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        }
      ],
      "name": "EtherSent",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_frontEnd",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_kickbackRate",
          "type": "uint256"
        }
      ],
      "name": "FrontEndRegistered",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_frontEnd",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_P",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_G",
          "type": "uint256"
        }
      ],
      "name": "FrontEndSnapshotUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_frontEnd",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_newFrontEndStake",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        }
      ],
      "name": "FrontEndStakeChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "_frontEnd",
          "type": "address"
        }
      ],
      "name": "FrontEndTagSet",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_G",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint128",
          "name": "_epoch",
          "type": "uint128"
        },
        {
          "indexed": false,
          "internalType": "uint128",
          "name": "_scale",
          "type": "uint128"
        }
      ],
      "name": "G_Updated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "previousOwner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "OwnershipTransferred",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_P",
          "type": "uint256"
        }
      ],
      "name": "P_Updated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_newPriceFeedAddress",
          "type": "address"
        }
      ],
      "name": "PriceFeedAddressChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_SOV",
          "type": "uint256"
        }
      ],
      "name": "SOVPaidToDepositor",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_frontEnd",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_SOV",
          "type": "uint256"
        }
      ],
      "name": "SOVPaidToFrontEnd",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_S",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint128",
          "name": "_epoch",
          "type": "uint128"
        },
        {
          "indexed": false,
          "internalType": "uint128",
          "name": "_scale",
          "type": "uint128"
        }
      ],
      "name": "S_Updated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint128",
          "name": "_currentScale",
          "type": "uint128"
        }
      ],
      "name": "ScaleUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_newSortedTrovesAddress",
          "type": "address"
        }
      ],
      "name": "SortedTrovesAddressChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_newBalance",
          "type": "uint256"
        }
      ],
      "name": "StabilityPoolETHBalanceUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_newBalance",
          "type": "uint256"
        }
      ],
      "name": "StabilityPoolZUSDBalanceUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_newTroveManagerAddress",
          "type": "address"
        }
      ],
      "name": "TroveManagerAddressChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_newDeposit",
          "type": "uint256"
        }
      ],
      "name": "UserDepositChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_zusdAmountRequested",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "_dllrAmountReceived",
          "type": "uint256"
        }
      ],
      "name": "WithdrawFromSpAndConvertToDLLR",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "_newZUSDTokenAddress",
          "type": "address"
        }
      ],
      "name": "ZUSDTokenAddressChanged",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "DECIMAL_PRECISION",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "MIN_NET_DEBT",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "NAME",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "P",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "SCALE_FACTOR",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "ZUSD_GAS_COMPENSATION",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "_100pct",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "activePool",
      "outputs": [
        {
          "internalType": "contract IActivePool",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "borrowerOperations",
      "outputs": [
        {
          "internalType": "contract IBorrowerOperations",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "communityIssuance",
      "outputs": [
        {
          "internalType": "contract ICommunityIssuance",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "currentEpoch",
      "outputs": [
        {
          "internalType": "uint128",
          "name": "",
          "type": "uint128"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "currentScale",
      "outputs": [
        {
          "internalType": "uint128",
          "name": "",
          "type": "uint128"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "defaultPool",
      "outputs": [
        {
          "internalType": "contract IDefaultPool",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "depositSnapshots",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "S",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "P",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "G",
          "type": "uint256"
        },
        {
          "internalType": "uint128",
          "name": "scale",
          "type": "uint128"
        },
        {
          "internalType": "uint128",
          "name": "epoch",
          "type": "uint128"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "deposits",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "initialValue",
          "type": "uint256"
        },
        {
          "internalType": "address",
          "name": "frontEndTag",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint128",
          "name": "",
          "type": "uint128"
        },
        {
          "internalType": "uint128",
          "name": "",
          "type": "uint128"
        }
      ],
      "name": "epochToScaleToG",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint128",
          "name": "",
          "type": "uint128"
        },
        {
          "internalType": "uint128",
          "name": "",
          "type": "uint128"
        }
      ],
      "name": "epochToScaleToSum",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "frontEndSnapshots",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "S",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "P",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "G",
          "type": "uint256"
        },
        {
          "internalType": "uint128",
          "name": "scale",
          "type": "uint128"
        },
        {
          "internalType": "uint128",
          "name": "epoch",
          "type": "uint128"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "frontEndStakes",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "frontEnds",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "kickbackRate",
          "type": "uint256"
        },
        {
          "internalType": "bool",
          "name": "registered",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_frontEnd",
          "type": "address"
        }
      ],
      "name": "getCompoundedFrontEndStake",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        }
      ],
      "name": "getCompoundedZUSDDeposit",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        }
      ],
      "name": "getDepositorETHGain",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_depositor",
          "type": "address"
        }
      ],
      "name": "getDepositorSOVGain",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getETH",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getEntireSystemColl",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "entireSystemColl",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getEntireSystemDebt",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "entireSystemDebt",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_frontEnd",
          "type": "address"
        }
      ],
      "name": "getFrontEndSOVGain",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getOwner",
      "outputs": [
        {
          "internalType": "address",
          "name": "_owner",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getTotalZUSDDeposits",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "lastETHError_Offset",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "lastSOVError",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "lastZUSDLossError_Offset",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "liquityBaseParams",
      "outputs": [
        {
          "internalType": "contract ILiquityBaseParams",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_debtToOffset",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "_collToAdd",
          "type": "uint256"
        }
      ],
      "name": "offset",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "permit2",
      "outputs": [
        {
          "internalType": "contract IPermit2",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "priceFeed",
      "outputs": [
        {
          "internalType": "contract IPriceFeed",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        },
        {
          "internalType": "address",
          "name": "_frontEndTag",
          "type": "address"
        }
      ],
      "name": "provideToSP",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_dllrAmount",
          "type": "uint256"
        },
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "deadline",
              "type": "uint256"
            },
            {
              "internalType": "uint8",
              "name": "v",
              "type": "uint8"
            },
            {
              "internalType": "bytes32",
              "name": "r",
              "type": "bytes32"
            },
            {
              "internalType": "bytes32",
              "name": "s",
              "type": "bytes32"
            }
          ],
          "internalType": "struct IMassetManager.PermitParams",
          "name": "_permitParams",
          "type": "tuple"
        }
      ],
      "name": "provideToSpFromDLLR",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_dllrAmount",
          "type": "uint256"
        },
        {
          "components": [
            {
              "components": [
                {
                  "internalType": "address",
                  "name": "token",
                  "type": "address"
                },
                {
                  "internalType": "uint256",
                  "name": "amount",
                  "type": "uint256"
                }
              ],
              "internalType": "struct ISignatureTransfer.TokenPermissions",
              "name": "permitted",
              "type": "tuple"
            },
            {
              "internalType": "uint256",
              "name": "nonce",
              "type": "uint256"
            },
            {
              "internalType": "uint256",
              "name": "deadline",
              "type": "uint256"
            }
          ],
          "internalType": "struct ISignatureTransfer.PermitTransferFrom",
          "name": "_permit",
          "type": "tuple"
        },
        {
          "internalType": "bytes",
          "name": "_signature",
          "type": "bytes"
        }
      ],
      "name": "provideToSpFromDllrWithPermit2",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_kickbackRate",
          "type": "uint256"
        }
      ],
      "name": "registerFrontEnd",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_liquityBaseParamsAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_borrowerOperationsAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_troveManagerAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_activePoolAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_zusdTokenAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_sortedTrovesAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_priceFeedAddress",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_communityIssuanceAddress",
          "type": "address"
        }
      ],
      "name": "setAddresses",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_communityIssuanceAddress",
          "type": "address"
        }
      ],
      "name": "setCommunityIssuanceAddress",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_owner",
          "type": "address"
        }
      ],
      "name": "setOwner",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "sortedTroves",
      "outputs": [
        {
          "internalType": "contract ISortedTroves",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "troveManager",
      "outputs": [
        {
          "internalType": "contract ITroveManager",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_upperHint",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_lowerHint",
          "type": "address"
        }
      ],
      "name": "withdrawETHGainToTrove",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        }
      ],
      "name": "withdrawFromSP",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_zusdAmountRequested",
          "type": "uint256"
        }
      ],
      "name": "withdrawFromSpAndConvertToDLLR",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "zusdToken",
      "outputs": [
        {
          "internalType": "contract IZUSDToken",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "stateMutability": "payable",
      "type": "receive"
    }
  ],
  "transactionHash": "0x1abdbd2388abebfb2b987c678ee06a38046e552728b35dbe0dfb5debbbe6c2a5",
  "receipt": {
    "to": null,
    "from": "0x13Be55487D37FE3C66EE7305e1e9C1ac85de75Ae",
    "contractAddress": "0xC959895CE6224dde0BdF7eb84519814dE23f2ee5",
    "transactionIndex": 0,
    "gasUsed": "5135892",
    "logsBloom": "0x00000000000020000000000000000000000000000000000000800000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000001800000000000000000040000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000020000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x26eb0b71917b7e14376847d8f22d8b657ac8a4a9756f9bace883ec60614ed674",
    "transactionHash": "0x1abdbd2388abebfb2b987c678ee06a38046e552728b35dbe0dfb5debbbe6c2a5",
    "logs": [
      {
        "transactionIndex": 0,
        "blockNumber": 4748945,
        "transactionHash": "0x1abdbd2388abebfb2b987c678ee06a38046e552728b35dbe0dfb5debbbe6c2a5",
        "address": "0xC959895CE6224dde0BdF7eb84519814dE23f2ee5",
        "topics": [
          "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x00000000000000000000000013be55487d37fe3c66ee7305e1e9c1ac85de75ae"
        ],
        "data": "0x",
        "logIndex": 0,
        "blockHash": "0x26eb0b71917b7e14376847d8f22d8b657ac8a4a9756f9bace883ec60614ed674"
      }
    ],
    "blockNumber": 4748945,
    "cumulativeGasUsed": "5135892",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x000000000022d473030f116ddee9f6b43ac78ba3"
  ],
  "numDeployments": 3,
  "solcInputHash": "849fadfa265e27de6fba2f2d99bdf763",
  "metadata": "{\"compiler\":{\"version\":\"0.6.11+commit.5ef660b1\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_permit2\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newActivePoolAddress\",\"type\":\"address\"}],\"name\":\"ActivePoolAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newBorrowerOperationsAddress\",\"type\":\"address\"}],\"name\":\"BorrowerOperationsAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newCommunityIssuanceAddress\",\"type\":\"address\"}],\"name\":\"CommunityIssuanceAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newDefaultPoolAddress\",\"type\":\"address\"}],\"name\":\"DefaultPoolAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_P\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_S\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_G\",\"type\":\"uint256\"}],\"name\":\"DepositSnapshotUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_ETH\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_ZUSDLoss\",\"type\":\"uint256\"}],\"name\":\"ETHGainWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"_currentEpoch\",\"type\":\"uint128\"}],\"name\":\"EpochUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"EtherSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_frontEnd\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_kickbackRate\",\"type\":\"uint256\"}],\"name\":\"FrontEndRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_frontEnd\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_P\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_G\",\"type\":\"uint256\"}],\"name\":\"FrontEndSnapshotUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_frontEnd\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_newFrontEndStake\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"FrontEndStakeChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_frontEnd\",\"type\":\"address\"}],\"name\":\"FrontEndTagSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_G\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"_epoch\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"_scale\",\"type\":\"uint128\"}],\"name\":\"G_Updated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_P\",\"type\":\"uint256\"}],\"name\":\"P_Updated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newPriceFeedAddress\",\"type\":\"address\"}],\"name\":\"PriceFeedAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_SOV\",\"type\":\"uint256\"}],\"name\":\"SOVPaidToDepositor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_frontEnd\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_SOV\",\"type\":\"uint256\"}],\"name\":\"SOVPaidToFrontEnd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_S\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"_epoch\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"_scale\",\"type\":\"uint128\"}],\"name\":\"S_Updated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"_currentScale\",\"type\":\"uint128\"}],\"name\":\"ScaleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newSortedTrovesAddress\",\"type\":\"address\"}],\"name\":\"SortedTrovesAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_newBalance\",\"type\":\"uint256\"}],\"name\":\"StabilityPoolETHBalanceUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_newBalance\",\"type\":\"uint256\"}],\"name\":\"StabilityPoolZUSDBalanceUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newTroveManagerAddress\",\"type\":\"address\"}],\"name\":\"TroveManagerAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_newDeposit\",\"type\":\"uint256\"}],\"name\":\"UserDepositChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_zusdAmountRequested\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_dllrAmountReceived\",\"type\":\"uint256\"}],\"name\":\"WithdrawFromSpAndConvertToDLLR\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newZUSDTokenAddress\",\"type\":\"address\"}],\"name\":\"ZUSDTokenAddressChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DECIMAL_PRECISION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_NET_DEBT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"P\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SCALE_FACTOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ZUSD_GAS_COMPENSATION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_100pct\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"activePool\",\"outputs\":[{\"internalType\":\"contract IActivePool\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowerOperations\",\"outputs\":[{\"internalType\":\"contract IBorrowerOperations\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"communityIssuance\",\"outputs\":[{\"internalType\":\"contract ICommunityIssuance\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentEpoch\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentScale\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"defaultPool\",\"outputs\":[{\"internalType\":\"contract IDefaultPool\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"depositSnapshots\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"S\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"P\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"G\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"scale\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"epoch\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"initialValue\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"frontEndTag\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"name\":\"epochToScaleToG\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"name\":\"epochToScaleToSum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"frontEndSnapshots\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"S\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"P\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"G\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"scale\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"epoch\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"frontEndStakes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"frontEnds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"kickbackRate\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"registered\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_frontEnd\",\"type\":\"address\"}],\"name\":\"getCompoundedFrontEndStake\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"getCompoundedZUSDDeposit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"getDepositorETHGain\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_depositor\",\"type\":\"address\"}],\"name\":\"getDepositorSOVGain\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getEntireSystemColl\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"entireSystemColl\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getEntireSystemDebt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"entireSystemDebt\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_frontEnd\",\"type\":\"address\"}],\"name\":\"getFrontEndSOVGain\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTotalZUSDDeposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastETHError_Offset\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastSOVError\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastZUSDLossError_Offset\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquityBaseParams\",\"outputs\":[{\"internalType\":\"contract ILiquityBaseParams\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_debtToOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_collToAdd\",\"type\":\"uint256\"}],\"name\":\"offset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"permit2\",\"outputs\":[{\"internalType\":\"contract IPermit2\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"priceFeed\",\"outputs\":[{\"internalType\":\"contract IPriceFeed\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_frontEndTag\",\"type\":\"address\"}],\"name\":\"provideToSP\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_dllrAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct IMassetManager.PermitParams\",\"name\":\"_permitParams\",\"type\":\"tuple\"}],\"name\":\"provideToSpFromDLLR\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_dllrAmount\",\"type\":\"uint256\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct ISignatureTransfer.TokenPermissions\",\"name\":\"permitted\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"internalType\":\"struct ISignatureTransfer.PermitTransferFrom\",\"name\":\"_permit\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"provideToSpFromDllrWithPermit2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_kickbackRate\",\"type\":\"uint256\"}],\"name\":\"registerFrontEnd\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_liquityBaseParamsAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_borrowerOperationsAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_troveManagerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_activePoolAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_zusdTokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sortedTrovesAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_priceFeedAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_communityIssuanceAddress\",\"type\":\"address\"}],\"name\":\"setAddresses\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_communityIssuanceAddress\",\"type\":\"address\"}],\"name\":\"setCommunityIssuanceAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sortedTroves\",\"outputs\":[{\"internalType\":\"contract ISortedTroves\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"troveManager\",\"outputs\":[{\"internalType\":\"contract ITroveManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_upperHint\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_lowerHint\",\"type\":\"address\"}],\"name\":\"withdrawETHGainToTrove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawFromSP\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_zusdAmountRequested\",\"type\":\"uint256\"}],\"name\":\"withdrawFromSpAndConvertToDLLR\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"zusdToken\",\"outputs\":[{\"internalType\":\"contract IZUSDToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getETH()\":{\"returns\":{\"_0\":\"the total amount of ETH held by the pool, accounted in an internal variable instead of `balance`, to exclude edge cases like ETH received from a self-destruct.\"}},\"getOwner()\":{\"returns\":{\"_owner\":\"Address of the owner. \"}},\"getTotalZUSDDeposits()\":{\"returns\":{\"_0\":\"ZUSD held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset.\"}},\"setAddresses(address,address,address,address,address,address,address,address)\":{\"details\":\"initializer function, checks addresses are contracts\",\"params\":{\"_activePoolAddress\":\"ActivePool contract address\",\"_borrowerOperationsAddress\":\"BorrowerOperations contract address\",\"_communityIssuanceAddress\":\"CommunityIssuanceAddress\",\"_liquityBaseParamsAddress\":\"LiquidityBaseParams contract address\",\"_priceFeedAddress\":\"PriceFeed contract address\",\"_sortedTrovesAddress\":\"SortedTroves contract address\",\"_troveManagerAddress\":\"TroveManager contract address\",\"_zusdTokenAddress\":\"ZUSDToken contract address\"}},\"setCommunityIssuanceAddress(address)\":{\"details\":\"setter function specific for community issuance contract.\",\"params\":{\"_communityIssuanceAddress\":\"address of new community issuance contract.\"}},\"setOwner(address)\":{\"params\":{\"_owner\":\"Address of the owner. \"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MIN_NET_DEBT()\":{\"notice\":\"Minimum amount of net ZUSD debt a trove must have\"},\"ZUSD_GAS_COMPENSATION()\":{\"notice\":\"Amount of ZUSD to be locked in gas pool on opening troves\"},\"constructor\":\"Constructor \",\"getCompoundedFrontEndStake(address)\":{\"notice\":\"Return the front end's compounded stake. Given by the formula:  D = D0 * P/P(0) where P(0) is the depositor's snapshot of the product P, taken at the last time when one of the front end's tagged deposits updated their deposit. The front end's compounded stake is equal to the sum of its depositors' compounded deposits.\"},\"getCompoundedZUSDDeposit(address)\":{\"notice\":\"Return the user's compounded deposit. Given by the formula:  d = d0 * P/P(0) where P(0) is the depositor's snapshot of the product P, taken when they last updated their deposit.\"},\"getDepositorETHGain(address)\":{\"notice\":\"Calculates the ETH gain earned by the deposit since its last snapshots were taken. Given by the formula:  E = d0 * (S - S(0))/P(0) where S(0) and P(0) are the depositor's snapshots of the sum S and product P, respectively. d0 is the last recorded deposit value.\"},\"getDepositorSOVGain(address)\":{\"notice\":\"Calculate the SOV gain earned by a deposit since its last snapshots were taken. Given by the formula:  SOV = d0 * (G - G(0))/P(0) where G(0) and P(0) are the depositor's snapshots of the sum G and product P, respectively. d0 is the last recorded deposit value.\"},\"getFrontEndSOVGain(address)\":{\"notice\":\"Return the SOV gain earned by the front end. Given by the formula:  E = D0 * (G - G(0))/P(0) where G(0) and P(0) are the depositor's snapshots of the sum G and product P, respectively. D0 is the last recorded value of the front end's total tagged deposits.\"},\"getOwner()\":{\"notice\":\"Return address of the owner.\"},\"offset(uint256,uint256)\":{\"notice\":\"Cancels out the specified debt against the ZUSD contained in the Stability Pool (as far as possible) and transfers the Trove's ETH collateral from ActivePool to StabilityPool. Only called by liquidation functions in the TroveManager.\"},\"provideToSP(uint256,address)\":{\"notice\":\"provideToSP(): - Triggers a SOV issuance, based on time passed since the last issuance and total amount of deposited ZUSD. The SOV issuance is shared between *all* depositors and front ends - Tags the deposit with the provided front end tag param, if it's a new deposit - Sends depositor's accumulated gains (SOV, ETH) to depositor - Sends the tagged front end's accumulated SOV gains to the tagged front end - Increases deposit and tagged front end's stake, and takes new snapshots for each.\"},\"provideToSpFromDLLR(uint256,(uint256,uint8,bytes32,bytes32))\":{\"notice\":\"DLLR _owner or _spender can convert a specified amount of DLLR into ZUSD via Sovryn Mynt and deposit the ZUSD into the Zero Stability Pool, all in a single transaction\"},\"provideToSpFromDllrWithPermit2(uint256,((address,uint256),uint256,uint256),bytes)\":{\"notice\":\"DLLR _owner or _spender can convert a specified amount of DLLR into ZUSD via Sovryn Mynt and deposit the ZUSD into the Zero Stability Pool, all in a single transaction\"},\"registerFrontEnd(uint256)\":{\"notice\":\"Front end makes a one-time selection of kickback rate upon registering\"},\"setAddresses(address,address,address,address,address,address,address,address)\":{\"notice\":\"Called only once on init, to set addresses of other Liquity contracts. Callable only by owner\"},\"setOwner(address)\":{\"notice\":\"Set address of the owner (only owner can call this function)\"},\"withdrawETHGainToTrove(address,address)\":{\"notice\":\"withdrawETHGainToTrove: - Triggers a SOV issuance, based on time passed since the last issuance. The SOV issuance is shared between *all* depositors and front ends - Sends all depositor's SOV gain to  depositor - Sends all tagged front end's SOV gain to the tagged front end - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove - Leaves their compounded deposit in the Stability Pool - Updates snapshots for deposit and tagged front end stake \"},\"withdrawFromSP(uint256)\":{\"notice\":\"withdrawFromSP(): - Triggers a SOV issuance, based on time passed since the last issuance and total amount of ZUSD is deposited. The SOV issuance is shared between *all* depositors and front ends - Removes the deposit's front end tag if it is a full withdrawal - Sends all depositor's accumulated gains (SOV, ETH) to depositor - Sends the tagged front end's accumulated SOV gains to the tagged front end - Decreases deposit and tagged front end's stake, and takes new snapshots for each. If _amount > userDeposit, the user withdraws all of their compounded deposit.\"},\"withdrawFromSpAndConvertToDLLR(uint256)\":{\"notice\":\"Stability Pool depositor can withdraw a specified amount of ZUSD from the Zero Stability Pool and convert the ZUSD to DLLR via Sovryn Mynt, all in a single transaction\"}},\"notice\":\"The Stability Pool holds ZUSD tokens deposited by Stability Pool depositors. When a trove is liquidated, then depending on system conditions, some of its ZUSD debt gets offset with ZUSD in the Stability Pool:  that is, the offset debt evaporates, and an equal amount of ZUSD tokens in the Stability Pool is burned. Thus, a liquidation causes each depositor to receive a ZUSD loss, in proportion to their deposit as a share of total deposits. They also receive an ETH gain, as the ETH collateral of the liquidated trove is distributed among Stability depositors, in the same proportion. When a liquidation occurs, it depletes every deposit by the same fraction: for example, a liquidation that depletes 40% of the total ZUSD in the Stability Pool, depletes 40% of each deposit. A deposit that has experienced a series of liquidations is termed a \\\"compounded deposit\\\": each liquidation depletes the deposit, multiplying it by some factor in range ]0,1[ --- IMPLEMENTATION --- We use a highly scalable method of tracking deposits and ETH gains that has O(1) complexity. When a liquidation occurs, rather than updating each depositor's deposit and ETH gain, we simply update two state variables: a product P, and a sum S. A mathematical manipulation allows us to factor out the initial deposit, and accurately track all depositors' compounded deposits and accumulated ETH gains over time, as liquidations occur, using just these two variables P and S. When depositors join the Stability Pool, they get a snapshot of the latest P and S: P_t and S_t, respectively. The formula for a depositor's accumulated ETH gain is derived here: https://github.com/liquity/dev/blob/main/packages/contracts/mathProofs/Scalable%20Compounding%20Stability%20Pool%20Deposits.pdf For a given deposit d_t, the ratio P/P_t tells us the factor by which a deposit has decreased since it joined the Stability Pool, and the term d_t * (S - S_t)/P_t gives us the deposit's total accumulated ETH gain. Each liquidation updates the product P and sum S. After a series of liquidations, a compounded deposit and corresponding ETH gain can be calculated using the initial deposit, the depositor\\u2019s snapshots of P and S, and the latest values of P and S. Any time a depositor updates their deposit (withdrawal, top-up) their accumulated ETH gain is paid out, their new deposit is recorded (based on their latest compounded deposit and modified by the withdrawal/top-up), and they receive new snapshots of the latest P and S. Essentially, they make a fresh deposit that overwrites the old one. --- SCALE FACTOR --- Since P is a running product in range ]0,1] that is always-decreasing, it should never reach 0 when multiplied by a number in range ]0,1[. Unfortunately, Solidity floor division always reaches 0, sooner or later. A series of liquidations that nearly empty the Pool (and thus each multiply P by a very small number in range ]0,1[ ) may push P to its 18 digit decimal limit, and round it to 0, when in fact the Pool hasn't been emptied: this would break deposit tracking. So, to track P accurately, we use a scale factor: if a liquidation would cause P to decrease to <1e-9 (and be rounded to 0 by Solidity), we first multiply P by 1e9, and increment a currentScale factor by 1. The added benefit of using 1e9 for the scale factor (rather than 1e18) is that it ensures negligible precision loss close to the scale boundary: when P is at its minimum value of 1e9, the relative precision loss in P due to floor division is only on the order of 1e-9. --- EPOCHS --- Whenever a liquidation fully empties the Stability Pool, all deposits should become 0. However, setting P to 0 would make P be 0 forever, and break all future reward calculations. So, every time the Stability Pool is emptied by a liquidation, we reset P = 1 and currentScale = 0, and increment the currentEpoch by 1. --- TRACKING DEPOSIT OVER SCALE CHANGES AND EPOCHS --- When a deposit is made, it gets snapshots of the currentEpoch and the currentScale. When calculating a compounded deposit, we compare the current epoch to the deposit's epoch snapshot. If the current epoch is newer, then the deposit was present during a pool-emptying liquidation, and necessarily has been depleted to 0. Otherwise, we then compare the current scale to the deposit's scale snapshot. If they're equal, the compounded deposit is given by d_t * P/P_t. If it spans one scale change, it is given by d_t * P/(P_t * 1e9). If it spans more than one scale change, we define the compounded deposit as 0, since it is now less than 1e-9'th of its initial value (e.g. a deposit of 1 billion ZUSD has depleted to < 1 ZUSD).  --- TRACKING DEPOSITOR'S ETH GAIN OVER SCALE CHANGES AND EPOCHS --- In the current epoch, the latest value of S is stored upon each scale change, and the mapping (scale -> S) is stored for each epoch. This allows us to calculate a deposit's accumulated ETH gain, during the epoch in which the deposit was non-zero and earned ETH. We calculate the depositor's accumulated ETH gain for the scale at which they made the deposit, using the ETH gain formula: e_1 = d_t * (S - S_t) / P_t and also for scale after, taking care to divide the latter by a factor of 1e9: e_2 = d_t * S / (P_t * 1e9) The gain in the second scale will be full, as the starting point was in the previous scale, thus no need to subtract anything. The deposit therefore was present for reward events from the beginning of that second scale.        S_i-S_t + S_{i+1}      .<--------.------------>      .         .      . S_i     .   S_{i+1}   <--.-------->.<----------->   S_t.         .   <->.         .      t         .  |---+---------|-------------|-----...         i            i+1 The sum of (e_1 + e_2) captures the depositor's total accumulated ETH gain, handling the case where their deposit spanned one scale change. We only care about gains across one scale change, since the compounded deposit is defined as being 0 once it has spanned more than one scale change. --- UPDATING P WHEN A LIQUIDATION OCCURS --- Please see the implementation spec in the proof document, which closely follows on from the compounded deposit / ETH gain derivations: https://github.com/liquity/liquity/blob/master/papers/Scalable_Reward_Distribution_with_Compounding_Stakes.pdf --- SOV ISSUANCE TO STABILITY POOL DEPOSITORS --- An SOV issuance event occurs at every deposit operation, and every liquidation. Each deposit is tagged with the address of the front end through which it was made. All deposits earn a share of the issued SOV in proportion to the deposit as a share of total deposits. The SOV earned by a given deposit, is split between the depositor and the front end through which the deposit was made, based on the front end's kickbackRate. Please see the system Readme for an overview: https://github.com/liquity/dev/blob/main/README.md#zero-issuance-to-stability-providers We use the same mathematical product-sum approach to track SOV gains for depositors, where 'G' is the sum corresponding to SOV gains. The product P (and snapshot P_t) is re-used, as the ratio P/P_t tracks a deposit's depletion due to liquidations.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/StabilityPool.sol\":\"StabilityPool\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"contracts/Dependencies/BaseMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.11;\\n\\n\\ncontract BaseMath {\\n    uint constant public DECIMAL_PRECISION = 1e18;\\n}\\n\",\"keccak256\":\"0x7e1369ca5cb09e818e345a2def19a261401f79c985a6030b55b7311dd6f53be4\",\"license\":\"MIT\"},\"contracts/Dependencies/CheckContract.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\n\\ncontract CheckContract {\\n    /**\\n     * @dev Check that the account is an already deployed non-destroyed contract.\\n     * See: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol#L12\\n     */\\n    function checkContract(address _account) internal view {\\n        require(_account != address(0), \\\"Account cannot be zero address\\\");\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(_account) }\\n        require(size > 0, \\\"Account code size cannot be zero\\\");\\n    }\\n}\\n\",\"keccak256\":\"0x4c7dc4d0197c27ebc7de671b00458a9ff45f57223aeb520e6ddd2eb6d2d89e5c\",\"license\":\"MIT\"},\"contracts/Dependencies/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\n/**\\n * Based on the OpenZeppelin IER20 interface:\\n * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol\\n *\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);\\n    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n    function name() external view returns (string memory);\\n    function symbol() external view returns (string memory);\\n    function decimals() external view returns (uint8);\\n    \\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\",\"keccak256\":\"0xe0b2473eba89df8d27d7cea2a99fce788c212f3fd393c9508e449e51a3f220fa\",\"license\":\"MIT\"},\"contracts/Dependencies/IERC2612.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\n/**\\n * @dev Interface of the ERC2612 standard as defined in the EIP.\\n *\\n * Adds the {permit} method, which can be used to change one's\\n * {IERC20-allowance} without having to send a transaction, by signing a\\n * message. This allows users to spend tokens without having to hold Ether.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2612.\\n * \\n * Code adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/\\n */\\ninterface IERC2612 {\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over `owner`'s tokens,\\n     * given `owner`'s signed approval.\\n     *\\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n     * ordering also apply here.\\n     *\\n     * Emits an {Approval} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `owner` cannot be the zero address.\\n     * - `spender` cannot be the zero address.\\n     * - `deadline` must be a timestamp in the future.\\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n     * over the EIP712-formatted function arguments.\\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\\n     *\\n     * For more information on the signature format, see the\\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n     * section].\\n     */\\n    function permit(address owner, address spender, uint256 amount, \\n                    uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\\n    \\n    /**\\n     * @dev Returns the current ERC2612 nonce for `owner`. This value must be\\n     * included whenever a signature is generated for {permit}.\\n     *\\n     * Every successful call to {permit} increases `owner`'s nonce by one. This\\n     * prevents a signature from being used multiple times.\\n     *\\n     * `owner` can limit the time a Permit is valid for by setting `deadline` to \\n     * a value in the near future. The deadline argument can be set to uint(-1) to \\n     * create Permits that effectively never expire.\\n     */\\n    function nonces(address owner) external view returns (uint256);\\n    \\n    function version() external view returns (string memory);\\n    function permitTypeHash() external view returns (bytes32);\\n    function domainSeparator() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xd376458452f8b480bfea549637bd71d3f9eb1f12e9d59d1beff373417462d67f\",\"license\":\"MIT\"},\"contracts/Dependencies/LiquityBase.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\nimport \\\"./BaseMath.sol\\\";\\nimport \\\"./LiquityMath.sol\\\";\\nimport \\\"../Interfaces/IActivePool.sol\\\";\\nimport \\\"../Interfaces/IDefaultPool.sol\\\";\\nimport \\\"../Interfaces/IPriceFeed.sol\\\";\\nimport \\\"../Interfaces/ILiquityBase.sol\\\";\\nimport \\\"../Interfaces/ILiquityBaseParams.sol\\\";\\n\\n/**\\n * Base contract for TroveManager, BorrowerOperations and StabilityPool. Contains global system constants and\\n * common functions.\\n */\\ncontract LiquityBase is BaseMath, ILiquityBase {\\n    using SafeMath for uint256;\\n\\n    uint256 public constant _100pct = 1000000000000000000; // 1e18 == 100%\\n\\n    /// Amount of ZUSD to be locked in gas pool on opening troves\\n    uint256 public constant ZUSD_GAS_COMPENSATION = 20e18;\\n\\n    /// Minimum amount of net ZUSD debt a trove must have\\n    uint256 public constant MIN_NET_DEBT = 180e18;\\n\\n    IActivePool public activePool;\\n\\n    IDefaultPool public defaultPool;\\n\\n    IPriceFeed public override priceFeed;\\n\\n    ILiquityBaseParams public override liquityBaseParams;\\n\\n    // --- Gas compensation functions ---\\n\\n    // Returns the composite debt (drawn debt + gas compensation) of a trove, for the purpose of ICR calculation\\n    function _getCompositeDebt(uint256 _debt) internal pure returns (uint256) {\\n        return _debt.add(ZUSD_GAS_COMPENSATION);\\n    }\\n\\n    function _getNetDebt(uint256 _debt) internal pure returns (uint256) {\\n        return _debt.sub(ZUSD_GAS_COMPENSATION);\\n    }\\n\\n    /// Return the amount of ETH to be drawn from a trove's collateral and sent as gas compensation.\\n    function _getCollGasCompensation(uint256 _entireColl) internal view returns (uint256) {\\n        return _entireColl / liquityBaseParams.PERCENT_DIVISOR();\\n    }\\n\\n    function getEntireSystemColl() public view returns (uint256 entireSystemColl) {\\n        uint256 activeColl = activePool.getETH();\\n        uint256 liquidatedColl = defaultPool.getETH();\\n\\n        return activeColl.add(liquidatedColl);\\n    }\\n\\n    function getEntireSystemDebt() public view returns (uint256 entireSystemDebt) {\\n        uint256 activeDebt = activePool.getZUSDDebt();\\n        uint256 closedDebt = defaultPool.getZUSDDebt();\\n\\n        return activeDebt.add(closedDebt);\\n    }\\n\\n    function _getTCR(uint256 _price) internal view returns (uint256 TCR) {\\n        uint256 entireSystemColl = getEntireSystemColl();\\n        uint256 entireSystemDebt = getEntireSystemDebt();\\n\\n        TCR = LiquityMath._computeCR(entireSystemColl, entireSystemDebt, _price);\\n\\n        return TCR;\\n    }\\n\\n    function _checkRecoveryMode(uint256 _price) internal view returns (bool) {\\n        uint256 TCR = _getTCR(_price);\\n\\n        return TCR < liquityBaseParams.CCR();\\n    }\\n\\n    function _requireUserAcceptsFee(\\n        uint256 _fee,\\n        uint256 _amount,\\n        uint256 _maxFeePercentage\\n    ) internal pure {\\n        uint256 feePercentage = _fee.mul(DECIMAL_PRECISION).div(_amount);\\n        require(feePercentage <= _maxFeePercentage, \\\"Fee exceeded provided maximum\\\");\\n    }\\n}\\n\",\"keccak256\":\"0x100b8a1c17caa95f5c9977e88f9263847a1977a365ca0a795753dd74aa1d6d7c\",\"license\":\"MIT\"},\"contracts/Dependencies/LiquityMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\nimport \\\"./SafeMath.sol\\\";\\nimport \\\"./console.sol\\\";\\n\\nlibrary LiquityMath {\\n    using SafeMath for uint;\\n\\n    uint internal constant DECIMAL_PRECISION = 1e18;\\n\\n    /* Precision for Nominal ICR (independent of price). Rationale for the value:\\n     *\\n     * - Making it \\u201ctoo high\\u201d could lead to overflows.\\n     * - Making it \\u201ctoo low\\u201d could lead to an ICR equal to zero, due to truncation from Solidity floor division. \\n     *\\n     * This value of 1e20 is chosen for safety: the NICR will only overflow for numerator > ~1e39 ETH,\\n     * and will only truncate to 0 if the denominator is at least 1e20 times greater than the numerator.\\n     *\\n     */\\n    uint internal constant NICR_PRECISION = 1e20;\\n\\n    function _min(uint _a, uint _b) internal pure returns (uint) {\\n        return (_a < _b) ? _a : _b;\\n    }\\n\\n    function _max(uint _a, uint _b) internal pure returns (uint) {\\n        return (_a >= _b) ? _a : _b;\\n    }\\n\\n    /* \\n    * Multiply two decimal numbers and use normal rounding rules:\\n    * -round product up if 19'th mantissa digit >= 5\\n    * -round product down if 19'th mantissa digit < 5\\n    *\\n    * Used only inside the exponentiation, _decPow().\\n    */\\n    function decMul(uint x, uint y) internal pure returns (uint decProd) {\\n        uint prod_xy = x.mul(y);\\n\\n        decProd = prod_xy.add(DECIMAL_PRECISION / 2).div(DECIMAL_PRECISION);\\n    }\\n\\n    /* \\n    * _decPow: Exponentiation function for 18-digit decimal base, and integer exponent n.\\n    * \\n    * Uses the efficient \\\"exponentiation by squaring\\\" algorithm. O(log(n)) complexity. \\n    * \\n    * Called by two functions that represent time in units of minutes:\\n    * 1) TroveManager._calcDecayedBaseRate\\n    * 2) CommunityIssuance._getCumulativeIssuanceFraction \\n    * \\n    * The exponent is capped to avoid reverting due to overflow. The cap 525600000 equals\\n    * \\\"minutes in 1000 years\\\": 60 * 24 * 365 * 1000\\n    * \\n    * If a period of > 1000 years is ever used as an exponent in either of the above functions, the result will be\\n    * negligibly different from just passing the cap, since: \\n    *\\n    * In function 1), the decayed base rate will be 0 for 1000 years or > 1000 years\\n    * In function 2), the difference in tokens issued at 1000 years and any time > 1000 years, will be negligible\\n    */\\n    function _decPow(uint _base, uint _minutes) internal pure returns (uint) {\\n       \\n        if (_minutes > 525600000) {_minutes = 525600000;}  // cap to avoid overflow\\n    \\n        if (_minutes == 0) {return DECIMAL_PRECISION;}\\n\\n        uint y = DECIMAL_PRECISION;\\n        uint x = _base;\\n        uint n = _minutes;\\n\\n        // Exponentiation-by-squaring\\n        while (n > 1) {\\n            if (n % 2 == 0) {\\n                x = decMul(x, x);\\n                n = n.div(2);\\n            } else { // if (n % 2 != 0)\\n                y = decMul(x, y);\\n                x = decMul(x, x);\\n                n = (n.sub(1)).div(2);\\n            }\\n        }\\n\\n        return decMul(x, y);\\n  }\\n\\n    function _getAbsoluteDifference(uint _a, uint _b) internal pure returns (uint) {\\n        return (_a >= _b) ? _a.sub(_b) : _b.sub(_a);\\n    }\\n\\n    function _computeNominalCR(uint _coll, uint _debt) internal pure returns (uint) {\\n        if (_debt > 0) {\\n            return _coll.mul(NICR_PRECISION).div(_debt);\\n        }\\n        // Return the maximal value for uint256 if the Trove has a debt of 0. Represents \\\"infinite\\\" CR.\\n        else { // if (_debt == 0)\\n            return 2**256 - 1;\\n        }\\n    }\\n\\n    function _computeCR(uint _coll, uint _debt, uint _price) internal pure returns (uint) {\\n        if (_debt > 0) {\\n            uint newCollRatio = _coll.mul(_price).div(_debt);\\n\\n            return newCollRatio;\\n        }\\n        // Return the maximal value for uint256 if the Trove has a debt of 0. Represents \\\"infinite\\\" CR.\\n        else { // if (_debt == 0)\\n            return 2**256 - 1; \\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x7a95ed70d8937e0896c054b433ad0dfc87a9cfd028cae1694098e9d5d68127cd\",\"license\":\"MIT\"},\"contracts/Dependencies/LiquitySafeMath128.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\n// uint128 addition and subtraction, with overflow protection.\\n\\nlibrary LiquitySafeMath128 {\\n    function add(uint128 a, uint128 b) internal pure returns (uint128) {\\n        uint128 c = a + b;\\n        require(c >= a, \\\"LiquitySafeMath128: addition overflow\\\");\\n\\n        return c;\\n    }\\n   \\n    function sub(uint128 a, uint128 b) internal pure returns (uint128) {\\n        require(b <= a, \\\"LiquitySafeMath128: subtraction overflow\\\");\\n        uint128 c = a - b;\\n\\n        return c;\\n    }\\n}\",\"keccak256\":\"0x6e51d34d6fe3a2afbf5b64d1e14984a170f30247b318f62e04b9f4afdb660fc5\",\"license\":\"MIT\"},\"contracts/Dependencies/Mynt/IDLLR.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\nimport \\\"../IERC20.sol\\\";\\n\\n/// Public interface for Sovryn Dollar DLLR (Meta Asset Token of Sovryn Mynt) exposing specific functions\\ninterface IDLLR is IERC20 {\\n    /**\\n     * @notice Only owner can transfer the token.\\n     * @notice destination cannot be:\\n     * - zero (0x0) address.\\n     *\\n     * @param _recipient Recipient of the token.\\n     * @param _amount The amount of token that will be transferred.\\n     *\\n     * @return true / false.\\n     */\\n    function transfer(address _recipient, uint256 _amount) external override returns (bool);\\n\\n    /**\\n     * @notice Only owner who can transfer the token.\\n     * @notice destination cannot be:\\n     * - zero (0x0) address.\\n     *\\n     * @param _from Sender of the token.\\n     * @param _to Recipient of the token.\\n     * @param _amount The amount of token that will be transferred.\\n     *\\n     * @return true / false.\\n     */\\n    function transferFrom(\\n        address _from,\\n        address _to,\\n        uint256 _amount\\n    ) external override returns (bool);\\n\\n    /**\\n     * @notice transfer utilizing EIP-2612, to reduce the additional sending transaction for doing the approval to the spender.\\n     *\\n     * @notice destination cannot be:\\n     * - zero (0x0) address.\\n     *\\n     * @dev By calling this function, the allowance will be overwritten by the total amount.\\n     *\\n     * @param _from Sender of the token.\\n     * @param _to Recipient of the token.\\n     * @param _amount The amount of the token that will be transferred.\\n     * @param _deadline Expiration time of the signature.\\n     * @param _v Last 1 byte of ECDSA signature.\\n     * @param _r First 32 bytes of ECDSA signature.\\n     * @param _s 32 bytes after _r in ECDSA signature.\\n     */\\n    function transferWithPermit(\\n        address _from,\\n        address _to,\\n        uint256 _amount,\\n        uint256 _deadline,\\n        uint8 _v,\\n        bytes32 _r,\\n        bytes32 _s\\n    ) external;\\n\\n    /**\\n     * @notice Approves and then calls the receiving contract.\\n     * Useful to encapsulate sending tokens to a contract in one call.\\n     * Solidity has no native way to send tokens to contracts.\\n     * ERC-20 tokens require approval to be spent by third parties, such as a contract in this case.\\n     * @param _spender The contract address to spend the tokens.\\n     * @param _amount The amount of tokens to be sent.\\n     * @param _data Parameters for the contract call, such as endpoint signature.\\n     */\\n    function approveAndCall(address _spender, uint256 _amount, bytes calldata _data) external;\\n}\\n\",\"keccak256\":\"0x1fcc09759323769fcaa430bef598cf08a9f5e98ce6a9bdd6faa79d8b7b6ecce2\",\"license\":\"MIT\"},\"contracts/Dependencies/Mynt/IMassetManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\ninterface IMassetManager {\\n    struct PermitParams {\\n        uint256 deadline;\\n        uint8 v;\\n        bytes32 r;\\n        bytes32 s;\\n    }\\n\\n    function mintTo(\\n        address _bAsset,\\n        uint256 _bAssetQuantity,\\n        address _recipient\\n    ) external returns (uint256);\\n\\n    function getToken() external view returns (address);\\n\\n    /**\\n     * @dev Credits a recipient with a certain quantity of selected bAsset, in exchange for burning the\\n     *      relative mAsset quantity from the sender. Sender also incurs a small fee, if any.\\n     * @param _bAsset           Address of the bAsset to redeem.\\n     * @param _massetQuantity   Units of the masset to redeem.\\n     * @param _recipient        Address to credit with withdrawn bAssets.\\n     * @return massetRedeemed   Relative number of mAsset units burned to pay for the bAssets.\\n     */\\n    function redeemTo(\\n        address _bAsset,\\n        uint256 _massetQuantity,\\n        address _recipient\\n    ) external returns (uint256 massetRedeemed);\\n}\\n\",\"keccak256\":\"0x3e8de462d45e8f07ef83b6b6e7eb90a5d09f21d3bcbb1225e8f781488ab4a771\",\"license\":\"MIT\"},\"contracts/Dependencies/Mynt/MyntLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\nimport \\\"./IMassetManager.sol\\\";\\nimport \\\"./IDLLR.sol\\\";\\nimport \\\"../SafeMath.sol\\\";\\nimport { IPermit2, ISignatureTransfer } from \\\"../../Interfaces/IPermit2.sol\\\";\\n\\nlibrary MyntLib {\\n    using SafeMath for uint256;\\n\\n    /**\\n     * @notice Convert DLLR _dllrAmount to _toToken utilizing EIP-2612 permit\\n     * to reduce the additional sending transaction for doing the approval to the spender.\\n     *\\n     * @dev WARNING!! Do not us this lib function on RSK network because there is a griefing attack issue in the DLLR contract.\\n     *\\n     * @param _myntMassetManager Mynt protocol MassetManager contract address - needed for integration\\n     * @param _dllrAmount The amount of the DLLR (mAsset) token that will be burned in exchange for _toToken\\n     * @param _toToken bAsset token address to withdraw from DLLR\\n     * @param _permitParams EIP-2612 permit params:\\n     *        _deadline Expiration time of the signature.\\n     *        _v Last 1 byte of ECDSA signature.\\n     *        _r First 32 bytes of ECDSA signature.\\n     *        _s 32 bytes after _r in ECDSA signature.\\n     * @return redeemed ZUSD amount\\n     */\\n    function redeemZusdFromDllrWithPermit(\\n        IMassetManager _myntMassetManager,\\n        uint256 _dllrAmount,\\n        address _toToken,\\n        IMassetManager.PermitParams calldata _permitParams\\n    ) internal returns (uint256) {\\n        IDLLR dllr = IDLLR(_myntMassetManager.getToken());\\n        uint256 thisBalanceBefore = dllr.balanceOf(address(this));\\n        address thisAddress = address(this);\\n        dllr.transferWithPermit(\\n            msg.sender,\\n            thisAddress,\\n            _dllrAmount,\\n            _permitParams.deadline,\\n            _permitParams.v,\\n            _permitParams.r,\\n            _permitParams.s\\n        );\\n        require(\\n            dllr.balanceOf(thisAddress).sub(thisBalanceBefore) == _dllrAmount,\\n            \\\"DLLR transferred amount validation failed\\\"\\n        );\\n        return _myntMassetManager.redeemTo(_toToken, _dllrAmount, msg.sender);\\n    }\\n\\n    /**\\n     * @notice Convert DLLR _dllrAmount to _toToken utilizing EIP-2612 permit via a canonical Permit2 contract\\n     * to reduce the additional sending transaction for doing the approval to the spender.\\n     *\\n     * @param _myntMassetManager Mynt protocol MassetManager contract address - needed for integration\\n     * @param _toToken bAsset token address to withdraw from DLLR\\n     * @param _permit permit data, in form of PermitTransferFrom struct.\\n     * @param _permit2 permit2 contract address\\n     * @param _signature signatue of the permit data.\\n     * @return redeemed ZUSD amount\\n     */\\n    function redeemZusdFromDllrWithPermit2(\\n        IMassetManager _myntMassetManager,\\n        address _toToken,\\n        ISignatureTransfer.PermitTransferFrom memory _permit,\\n        IPermit2 _permit2,\\n        bytes calldata _signature\\n    ) internal returns (uint256) {\\n        IDLLR dllr = IDLLR(_myntMassetManager.getToken());\\n        uint256 thisBalanceBefore = dllr.balanceOf(address(this));\\n        address thisAddress = address(this);\\n        uint256 _dllrAmount = _permit.permitted.amount;\\n\\n        _permit2.permitTransferFrom(\\n            _permit,\\n            _generateTransferDetails(thisAddress, _dllrAmount),\\n            msg.sender,\\n            _signature\\n        );\\n\\n        require(\\n            dllr.balanceOf(thisAddress).sub(thisBalanceBefore) == _dllrAmount,\\n            \\\"DLLR transferred amount validation failed\\\"\\n        );\\n        return _myntMassetManager.redeemTo(_toToken, _dllrAmount, msg.sender);\\n    }\\n\\n    /**\\n     * @dev view function to construct SignatureTransferDetails struct to be used by Permit2\\n     *\\n     * @param _to ultimate recipient\\n     * @param _amount amount of transfer\\n     *\\n     * @return SignatureTransferDetails struct object \\n     */\\n    function _generateTransferDetails(address _to, uint256 _amount) private view returns (ISignatureTransfer.SignatureTransferDetails memory) {\\n        ISignatureTransfer.SignatureTransferDetails memory transferDetails = ISignatureTransfer.SignatureTransferDetails({\\n            to: _to,\\n            requestedAmount: _amount\\n        });\\n\\n        return transferDetails;\\n    }\\n}\\n\",\"keccak256\":\"0x6f0c78d8c4ea0b5b5e6bbe8d78374b9d2d367ffc07054dde36b9cbe2061944b6\",\"license\":\"MIT\"},\"contracts/Dependencies/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\n/**\\n * Based on OpenZeppelin's Ownable contract:\\n * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol\\n *\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n    bytes32 private constant KEY_OWNER = keccak256(\\\"key.ownable.owner\\\");\\n\\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n    /**\\n     * @dev Initializes the contract setting the deployer as the initial owner.\\n     */\\n    constructor () internal {\\n        _setOwner(msg.sender);\\n    }\\n\\n    /**\\n     * @dev Throws if called by any account other than the owner.\\n     */\\n    modifier onlyOwner() {\\n        require(msg.sender == getOwner(), \\\"Ownable:: access denied\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @notice Set address of the owner.\\n     * @param _owner Address of the owner.\\n     * */\\n    function _setOwner(address _owner) internal {\\n        require(_owner != address(0), \\\"Ownable::setOwner: invalid address\\\");\\n        emit OwnershipTransferred(getOwner(), _owner);\\n\\n        bytes32 key = KEY_OWNER;\\n        assembly {\\n            sstore(key, _owner)\\n        }\\n    }\\n\\n    /**\\n     * @notice Set address of the owner (only owner can call this function)\\n     * @param _owner Address of the owner.\\n     * */\\n    function setOwner(address _owner) public onlyOwner {\\n        _setOwner(_owner);\\n    }\\n\\n    /**\\n     * @notice Return address of the owner.\\n     * @return _owner Address of the owner.\\n     * */\\n    function getOwner() public view returns (address _owner) {\\n        bytes32 key = KEY_OWNER;\\n        assembly {\\n            _owner := sload(key)\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xb5fc626e0b227fc0feb1d84440585015a0a5f586547d298534a604dd113efec6\",\"license\":\"MIT\"},\"contracts/Dependencies/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\n/**\\n * Based on OpenZeppelin's SafeMath:\\n * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol\\n *\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n    /**\\n     * @dev Returns the addition of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `+` operator.\\n     *\\n     * Requirements:\\n     * - Addition cannot overflow.\\n     */\\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     * - Subtraction cannot overflow.\\n     */\\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n     * overflow (when the result is negative).\\n     *\\n     * Counterpart to Solidity's `-` operator.\\n     *\\n     * Requirements:\\n     * - Subtraction cannot overflow.\\n     *\\n     * _Available since v2.4.0._\\n     */\\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        uint256 c = a - b;\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the multiplication of two unsigned integers, reverting on\\n     * overflow.\\n     *\\n     * Counterpart to Solidity's `*` operator.\\n     *\\n     * Requirements:\\n     * - Multiplication cannot overflow.\\n     */\\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n        // benefit is lost if 'b' is also tested.\\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n        if (a == 0) {\\n            return 0;\\n        }\\n\\n        uint256 c = a * b;\\n        require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers. Reverts on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return div(a, b, \\\"SafeMath: division by zero\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n     * division by zero. The result is rounded towards zero.\\n     *\\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n     * uses an invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     *\\n     * _Available since v2.4.0._\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        // Solidity only automatically asserts when dividing by 0\\n        require(b > 0, errorMessage);\\n        uint256 c = a / b;\\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n        return c;\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * Reverts when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     */\\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n    }\\n\\n    /**\\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n     * Reverts with custom message when dividing by zero.\\n     *\\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\\n     * invalid opcode to revert (consuming all remaining gas).\\n     *\\n     * Requirements:\\n     * - The divisor cannot be zero.\\n     *\\n     * _Available since v2.4.0._\\n     */\\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n        require(b != 0, errorMessage);\\n        return a % b;\\n    }\\n}\\n\",\"keccak256\":\"0x666b890992a066cc791f36c2975cd595d9761a014c654c385ed36ffaf658f3fd\",\"license\":\"MIT\"},\"contracts/Dependencies/console.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\n// Buidler's helper contract for console logging\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction log() internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t\\tignored;\\n\\t}\\tfunction logInt(int p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logByte(byte p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(byte)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t(bool ignored, ) = CONSOLE_ADDRESS.staticcall(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t\\tignored;\\n\\t}\\n\\n}\\n\",\"keccak256\":\"0x6fa1de4ffe22b8f58b0b64d65db11dd5037be9b9db47b365a72adb489e217000\",\"license\":\"MIT\"},\"contracts/Interfaces/IActivePool.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\nimport \\\"./IPool.sol\\\";\\n\\n/**\\n * The Active Pool holds the ETH collateral and ZUSD debt (but not ZUSD tokens) for all active troves.\\n *\\n * When a trove is liquidated, it's ETH and ZUSD debt are transferred from the Active Pool, to either the\\n * Stability Pool, the Default Pool, or both, depending on the liquidation conditions.\\n *\\n */\\ninterface IActivePool is IPool {\\n    // --- Events ---\\n    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);\\n    event TroveManagerAddressChanged(address _newTroveManagerAddress);\\n    event ActivePoolZUSDDebtUpdated(uint _ZUSDDebt);\\n    event ActivePoolETHBalanceUpdated(uint _ETH);\\n\\n    // --- Functions ---\\n\\n    /// @notice Send ETH amount to given account. Updates ActivePool balance. Only callable by BorrowerOperations, TroveManager or StabilityPool.\\n    /// @param _account account to receive the ETH amount\\n    /// @param _amount ETH amount to send\\n    function sendETH(address _account, uint _amount) external;\\n}\\n\",\"keccak256\":\"0xdd5f1b6fae4050b4c885a85a10c2d0e73b82187a51736d009065aaeea33bf0d0\",\"license\":\"MIT\"},\"contracts/Interfaces/IAllowanceTransfer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.11;\\npragma experimental ABIEncoderV2;\\n\\nimport {IEIP712} from \\\"./IEIP712.sol\\\";\\n\\n/// @title AllowanceTransfer\\n/// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts\\n/// @dev Requires user's token approval on the Permit2 contract\\ninterface IAllowanceTransfer is IEIP712 {\\n    /// @notice Emits an event when the owner successfully invalidates an ordered nonce.\\n    event NonceInvalidation(\\n        address indexed owner, address indexed token, address indexed spender, uint48 newNonce, uint48 oldNonce\\n    );\\n\\n    /// @notice Emits an event when the owner successfully sets permissions on a token for the spender.\\n    event Approval(\\n        address indexed owner, address indexed token, address indexed spender, uint160 amount, uint48 expiration\\n    );\\n\\n    /// @notice Emits an event when the owner successfully sets permissions using a permit signature on a token for the spender.\\n    event Permit(\\n        address indexed owner,\\n        address indexed token,\\n        address indexed spender,\\n        uint160 amount,\\n        uint48 expiration,\\n        uint48 nonce\\n    );\\n\\n    /// @notice Emits an event when the owner sets the allowance back to 0 with the lockdown function.\\n    event Lockdown(address indexed owner, address token, address spender);\\n\\n    /// @notice The permit data for a token\\n    struct PermitDetails {\\n        // ERC20 token address\\n        address token;\\n        // the maximum amount allowed to spend\\n        uint160 amount;\\n        // timestamp at which a spender's token allowances become invalid\\n        uint48 expiration;\\n        // an incrementing value indexed per owner,token,and spender for each signature\\n        uint48 nonce;\\n    }\\n\\n    /// @notice The permit message signed for a single token allowance\\n    struct PermitSingle {\\n        // the permit data for a single token alownce\\n        PermitDetails details;\\n        // address permissioned on the allowed tokens\\n        address spender;\\n        // deadline on the permit signature\\n        uint256 sigDeadline;\\n    }\\n\\n    /// @notice The permit message signed for multiple token allowances\\n    struct PermitBatch {\\n        // the permit data for multiple token allowances\\n        PermitDetails[] details;\\n        // address permissioned on the allowed tokens\\n        address spender;\\n        // deadline on the permit signature\\n        uint256 sigDeadline;\\n    }\\n\\n    /// @notice The saved permissions\\n    /// @dev This info is saved per owner, per token, per spender and all signed over in the permit message\\n    /// @dev Setting amount to type(uint160).max sets an unlimited approval\\n    struct PackedAllowance {\\n        // amount allowed\\n        uint160 amount;\\n        // permission expiry\\n        uint48 expiration;\\n        // an incrementing value indexed per owner,token,and spender for each signature\\n        uint48 nonce;\\n    }\\n\\n    /// @notice A token spender pair.\\n    struct TokenSpenderPair {\\n        // the token the spender is approved\\n        address token;\\n        // the spender address\\n        address spender;\\n    }\\n\\n    /// @notice Details for a token transfer.\\n    struct AllowanceTransferDetails {\\n        // the owner of the token\\n        address from;\\n        // the recipient of the token\\n        address to;\\n        // the amount of the token\\n        uint160 amount;\\n        // the token to be transferred\\n        address token;\\n    }\\n\\n    /// @notice A mapping from owner address to token address to spender address to PackedAllowance struct, which contains details and conditions of the approval.\\n    /// @notice The mapping is indexed in the above order see: allowance[ownerAddress][tokenAddress][spenderAddress]\\n    /// @dev The packed slot holds the allowed amount, expiration at which the allowed amount is no longer valid, and current nonce thats updated on any signature based approvals.\\n    function allowance(address user, address token, address spender)\\n        external\\n        view\\n        returns (uint160 amount, uint48 expiration, uint48 nonce);\\n\\n    /// @notice Approves the spender to use up to amount of the specified token up until the expiration\\n    /// @param token The token to approve\\n    /// @param spender The spender address to approve\\n    /// @param amount The approved amount of the token\\n    /// @param expiration The timestamp at which the approval is no longer valid\\n    /// @dev The packed allowance also holds a nonce, which will stay unchanged in approve\\n    /// @dev Setting amount to type(uint160).max sets an unlimited approval\\n    function approve(address token, address spender, uint160 amount, uint48 expiration) external;\\n\\n    /// @notice Permit a spender to a given amount of the owners token via the owner's EIP-712 signature\\n    /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce\\n    /// @param owner The owner of the tokens being approved\\n    /// @param permitSingle Data signed over by the owner specifying the terms of approval\\n    /// @param signature The owner's signature over the permit data\\n    function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;\\n\\n    /// @notice Permit a spender to the signed amounts of the owners tokens via the owner's EIP-712 signature\\n    /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce\\n    /// @param owner The owner of the tokens being approved\\n    /// @param permitBatch Data signed over by the owner specifying the terms of approval\\n    /// @param signature The owner's signature over the permit data\\n    function permit(address owner, PermitBatch memory permitBatch, bytes calldata signature) external;\\n\\n    /// @notice Transfer approved tokens from one address to another\\n    /// @param from The address to transfer from\\n    /// @param to The address of the recipient\\n    /// @param amount The amount of the token to transfer\\n    /// @param token The token address to transfer\\n    /// @dev Requires the from address to have approved at least the desired amount\\n    /// of tokens to msg.sender.\\n    function transferFrom(address from, address to, uint160 amount, address token) external;\\n\\n    /// @notice Transfer approved tokens in a batch\\n    /// @param transferDetails Array of owners, recipients, amounts, and tokens for the transfers\\n    /// @dev Requires the from addresses to have approved at least the desired amount\\n    /// of tokens to msg.sender.\\n    function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external;\\n\\n    /// @notice Enables performing a \\\"lockdown\\\" of the sender's Permit2 identity\\n    /// by batch revoking approvals\\n    /// @param approvals Array of approvals to revoke.\\n    function lockdown(TokenSpenderPair[] calldata approvals) external;\\n\\n    /// @notice Invalidate nonces for a given (token, spender) pair\\n    /// @param token The token to invalidate nonces for\\n    /// @param spender The spender to invalidate nonces for\\n    /// @param newNonce The new nonce to set. Invalidates all nonces less than it.\\n    /// @dev Can't invalidate more than 2**16 nonces per transaction.\\n    function invalidateNonces(address token, address spender, uint48 newNonce) external;\\n}\\n\",\"keccak256\":\"0xf15059fb68f89542908f963f22e18c0b0ae9997a6f9aaf6a9fb46aa2424acac9\",\"license\":\"MIT\"},\"contracts/Interfaces/IBorrowerOperations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../Dependencies/Mynt/IMassetManager.sol\\\";\\nimport { IPermit2, ISignatureTransfer } from \\\"./IPermit2.sol\\\";\\n\\n/// Common interface for the Trove Manager.\\ninterface IBorrowerOperations {\\n    // --- Events ---\\n\\n    event FeeDistributorAddressChanged(address _feeDistributorAddress);\\n    event TroveManagerAddressChanged(address _newTroveManagerAddress);\\n    event ActivePoolAddressChanged(address _activePoolAddress);\\n    event DefaultPoolAddressChanged(address _defaultPoolAddress);\\n    event StabilityPoolAddressChanged(address _stabilityPoolAddress);\\n    event GasPoolAddressChanged(address _gasPoolAddress);\\n    event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress);\\n    event PriceFeedAddressChanged(address _newPriceFeedAddress);\\n    event SortedTrovesAddressChanged(address _sortedTrovesAddress);\\n    event ZUSDTokenAddressChanged(address _zusdTokenAddress);\\n    event ZEROStakingAddressChanged(address _zeroStakingAddress);\\n\\n    event TroveCreated(address indexed _borrower, uint256 arrayIndex);\\n    event TroveUpdated(\\n        address indexed _borrower,\\n        uint256 _debt,\\n        uint256 _coll,\\n        uint256 stake,\\n        uint8 operation\\n    );\\n    event ZUSDBorrowingFeePaid(address indexed _borrower, uint256 _ZUSDFee);\\n\\n    // --- Functions ---\\n\\n    /**\\n     * @notice Called only once on init, to set addresses of other Zero contracts. Callable only by owner\\n     * @dev initializer function, checks addresses are contracts\\n     * @param _feeDistributorAddress feeDistributor contract address\\n     * @param _liquityBaseParamsAddress LiquidityBaseParams contract address\\n     * @param _troveManagerAddress TroveManager contract address\\n     * @param _activePoolAddress ActivePool contract address\\n     * @param _defaultPoolAddress DefaultPool contract address\\n     * @param _stabilityPoolAddress StabilityPool contract address\\n     * @param _gasPoolAddress GasPool contract address\\n     * @param _collSurplusPoolAddress CollSurplusPool contract address\\n     * @param _priceFeedAddress PrideFeed contract address\\n     * @param _sortedTrovesAddress SortedTroves contract address\\n     * @param _zusdTokenAddress ZUSDToken contract address\\n     * @param _zeroStakingAddress ZEROStaking contract address\\n     */\\n    function setAddresses(\\n        address _feeDistributorAddress,\\n        address _liquityBaseParamsAddress,\\n        address _troveManagerAddress,\\n        address _activePoolAddress,\\n        address _defaultPoolAddress,\\n        address _stabilityPoolAddress,\\n        address _gasPoolAddress,\\n        address _collSurplusPoolAddress,\\n        address _priceFeedAddress,\\n        address _sortedTrovesAddress,\\n        address _zusdTokenAddress,\\n        address _zeroStakingAddress\\n    ) external;\\n\\n    /**\\n     * @notice payable function that creates a Trove for the caller with the requested debt, and the Ether received as collateral.\\n     * Successful execution is conditional mainly on the resulting collateralization ratio which must exceed the minimum (110% in Normal Mode, 150% in Recovery Mode).\\n     * In addition to the requested debt, extra debt is issued to pay the issuance fee, and cover the gas compensation.\\n     * The borrower has to provide a `_maxFeePercentage` that he/she is willing to accept in case of a fee slippage, i.e. when a redemption transaction is processed first, driving up the issuance fee.\\n     * @param _maxFee max fee percentage to acept in case of a fee slippage\\n     * @param _ZUSDAmount ZUSD requested debt\\n     * @param _upperHint upper trove id hint\\n     * @param _lowerHint lower trove id hint\\n     */\\n    function openTrove(\\n        uint256 _maxFee,\\n        uint256 _ZUSDAmount,\\n        address _upperHint,\\n        address _lowerHint\\n    ) external payable;\\n\\n    /**\\n     * @notice payable function that creates a Trove for the caller with the requested debt, and the Ether received as collateral.\\n     * Successful execution is conditional mainly on the resulting collateralization ratio which must exceed the minimum (110% in Normal Mode, 150% in Recovery Mode).\\n     * In addition to the requested debt, extra debt is issued to pay the issuance fee, and cover the gas compensation.\\n     * The borrower has to provide a `_maxFeePercentage` that he/she is willing to accept in case of a fee slippage, i.e. when a redemption transaction is processed first, driving up the issuance fee.\\n     * This method is identical to `openTrove()`, but operates on NUE tokens instead of ZUSD.\\n     * @param _maxFee max fee percentage to acept in case of a fee slippage\\n     * @param _ZUSDAmount ZUSD requested debt\\n     * @param _upperHint upper trove id hint\\n     * @param _lowerHint lower trove id hint\\n     */\\n    function openNueTrove(\\n        uint256 _maxFee,\\n        uint256 _ZUSDAmount,\\n        address _upperHint,\\n        address _lowerHint\\n    ) external payable;\\n\\n    /// @notice payable function that adds the received Ether to the caller's active Trove.\\n    /// @param _upperHint upper trove id hint\\n    /// @param _lowerHint lower trove id hint\\n    function addColl(address _upperHint, address _lowerHint) external payable;\\n\\n    /// @notice send ETH as collateral to a trove. Called by only the Stability Pool.\\n    /// @param _user user trove address\\n    /// @param _upperHint upper trove id hint\\n    /// @param _lowerHint lower trove id hint\\n    function moveETHGainToTrove(\\n        address _user,\\n        address _upperHint,\\n        address _lowerHint\\n    ) external payable;\\n\\n    /**\\n     * @notice withdraws `_amount` of collateral from the caller\\u2019s Trove.\\n     * Executes only if the user has an active Trove, the withdrawal would not pull the user\\u2019s Trove below the minimum collateralization ratio,\\n     * and the resulting total collateralization ratio of the system is above 150%.\\n     * @param _amount collateral amount to withdraw\\n     * @param _upperHint upper trove id hint\\n     * @param _lowerHint lower trove id hint\\n     */\\n    function withdrawColl(uint256 _amount, address _upperHint, address _lowerHint) external;\\n\\n    /**\\n     * @notice issues `_amount` of ZUSD from the caller\\u2019s Trove to the caller.\\n     * Executes only if the Trove's collateralization ratio would remain above the minimum, and the resulting total collateralization ratio is above 150%.\\n     * The borrower has to provide a `_maxFeePercentage` that he/she is willing to accept in case of a fee slippage, i.e. when a redemption transaction is processed first, driving up the issuance fee.\\n     * @param _maxFee max fee percentage to acept in case of a fee slippage\\n     * @param _amount ZUSD amount to withdraw\\n     * @param _upperHint upper trove id hint\\n     * @param _lowerHint lower trove id hint\\n     */\\n    function withdrawZUSD(\\n        uint256 _maxFee,\\n        uint256 _amount,\\n        address _upperHint,\\n        address _lowerHint\\n    ) external;\\n\\n    /// Borrow (withdraw) ZUSD tokens from a trove: mint new ZUSD tokens to the owner and convert it to DLLR in one transaction\\n    function withdrawZusdAndConvertToDLLR(\\n        uint256 _maxFeePercentage,\\n        uint256 _ZUSDAmount,\\n        address _upperHint,\\n        address _lowerHint\\n    ) external returns (uint256);\\n\\n    /// @notice repay `_amount` of ZUSD to the caller\\u2019s Trove, subject to leaving 50 debt in the Trove (which corresponds to the 50 ZUSD gas compensation).\\n    /// @param _amount ZUSD amount to repay\\n    /// @param _upperHint upper trove id hint\\n    /// @param _lowerHint lower trove id hint\\n    function repayZUSD(uint256 _amount, address _upperHint, address _lowerHint) external;\\n\\n    /// Repay ZUSD tokens to a Trove: Burn the repaid ZUSD tokens, and reduce the trove's debt accordingly\\n    function repayZusdFromDLLR(\\n        uint256 _dllrAmount,\\n        address _upperHint,\\n        address _lowerHint,\\n        IMassetManager.PermitParams calldata _permitParams\\n    ) external;\\n\\n    /// Repay ZUSD tokens to a Trove: Burn the repaid ZUSD tokens, and reduce the trove's debt accordingly\\n    function repayZusdFromDLLRWithPermit2(\\n        uint256 _dllrAmount,\\n        address _upperHint,\\n        address _lowerHint,\\n        ISignatureTransfer.PermitTransferFrom memory _permit,\\n        bytes calldata _signature\\n    ) external;\\n\\n    /**\\n     * @notice allows a borrower to repay all debt, withdraw all their collateral, and close their Trove.\\n     * Requires the borrower have a ZUSD balance sufficient to repay their trove's debt, excluding gas compensation - i.e. `(debt - 50)` ZUSD.\\n     */\\n    function closeTrove() external;\\n\\n    /**\\n     * @notice allows a borrower to repay all debt, withdraw all their collateral, and close their Trove.\\n     * Requires the borrower have a NUE balance sufficient to repay their trove's debt, excluding gas compensation - i.e. `(debt - 50)` NUE.\\n     * This method is identical to `closeTrove()`, but operates on NUE tokens instead of ZUSD.\\n     */\\n    function closeNueTrove(IMassetManager.PermitParams calldata _permitParams) external;\\n\\n    /**\\n     * @notice allows a borrower to repay all debt, withdraw all their collateral, and close their Trove.\\n     * Requires the borrower have a NUE balance sufficient to repay their trove's debt, excluding gas compensation - i.e. `(debt - 50)` NUE.\\n     * This method is identical to `closeTrove()`, but operates on NUE tokens instead of ZUSD.\\n     */\\n    function closeNueTroveWithPermit2(ISignatureTransfer.PermitTransferFrom memory _permit, bytes calldata _signature) external;\\n\\n    /**\\n     * @notice enables a borrower to simultaneously change both their collateral and debt, subject to all the restrictions that apply to individual increases/decreases of each quantity with the following particularity:\\n     * if the adjustment reduces the collateralization ratio of the Trove, the function only executes if the resulting total collateralization ratio is above 150%.\\n     * The borrower has to provide a `_maxFeePercentage` that he/she is willing to accept in case of a fee slippage, i.e. when a redemption transaction is processed first, driving up the issuance fee.\\n     * The parameter is ignored if the debt is not increased with the transaction.\\n     * @param _maxFee max fee percentage to acept in case of a fee slippage\\n     * @param _collWithdrawal collateral amount to withdraw\\n     * @param _debtChange ZUSD amount to change\\n     * @param isDebtIncrease indicates if increases debt\\n     * @param _upperHint upper trove id hint\\n     * @param _lowerHint lower trove id hint\\n     */\\n    function adjustTrove(\\n        uint256 _maxFee,\\n        uint256 _collWithdrawal,\\n        uint256 _debtChange,\\n        bool isDebtIncrease,\\n        address _upperHint,\\n        address _lowerHint\\n    ) external payable;\\n\\n    /**\\n     * @notice enables a borrower to simultaneously change both their collateral and debt, subject to all the restrictions that apply to individual increases/decreases of each quantity with the following particularity:\\n     * if the adjustment reduces the collateralization ratio of the Trove, the function only executes if the resulting total collateralization ratio is above 150%.\\n     * The borrower has to provide a `_maxFeePercentage` that he/she is willing to accept in case of a fee slippage, i.e. when a redemption transaction is processed first, driving up the issuance fee.\\n     * The parameter is ignored if the debt is not increased with the transaction.\\n     * This method is identical to `adjustTrove()`, but operates on NUE tokens instead of ZUSD.\\n     * @param _maxFee max fee percentage to acept in case of a fee slippage\\n     * @param _collWithdrawal collateral amount to withdraw\\n     * @param _debtChange ZUSD amount to change\\n     * @param isDebtIncrease indicates if increases debt\\n     * @param _upperHint upper trove id hint\\n     * @param _lowerHint lower trove id hint\\n     */\\n    function adjustNueTrove(\\n        uint256 _maxFee,\\n        uint256 _collWithdrawal,\\n        uint256 _debtChange,\\n        bool isDebtIncrease,\\n        address _upperHint,\\n        address _lowerHint,\\n        IMassetManager.PermitParams calldata _permitParams\\n    ) external payable;\\n\\n    /**\\n     * @notice enables a borrower to simultaneously change both their collateral and debt, subject to all the restrictions that apply to individual increases/decreases of each quantity with the following particularity:\\n     * if the adjustment reduces the collateralization ratio of the Trove, the function only executes if the resulting total collateralization ratio is above 150%.\\n     * The borrower has to provide a `_maxFeePercentage` that he/she is willing to accept in case of a fee slippage, i.e. when a redemption transaction is processed first, driving up the issuance fee.\\n     * The parameter is ignored if the debt is not increased with the transaction.\\n     * This method is identical to `adjustTrove()`, but operates on NUE tokens instead of ZUSD.\\n     * @param _maxFee max fee percentage to acept in case of a fee slippage\\n     * @param _collWithdrawal collateral amount to withdraw\\n     * @param _debtChange ZUSD amount to change\\n     * @param isDebtIncrease indicates if increases debt\\n     * @param _upperHint upper trove id hint\\n     * @param _lowerHint lower trove id hint\\n     */\\n    function adjustNueTroveWithPermit2(\\n        uint256 _maxFee,\\n        uint256 _collWithdrawal,\\n        uint256 _debtChange,\\n        bool isDebtIncrease,\\n        address _upperHint,\\n        address _lowerHint,\\n        ISignatureTransfer.PermitTransferFrom memory _permit,\\n        bytes calldata _signature\\n    ) external payable;\\n\\n    /**\\n     * @notice when a borrower\\u2019s Trove has been fully redeemed from and closed, or liquidated in Recovery Mode with a collateralization ratio above 110%,\\n     * this function allows the borrower to claim their ETH collateral surplus that remains in the system (collateral - debt upon redemption; collateral - 110% of the debt upon liquidation).\\n     */\\n    function claimCollateral() external;\\n\\n    function getCompositeDebt(uint256 _debt) external view returns (uint256);\\n\\n    function BORROWING_FEE_FLOOR() external view returns (uint256);\\n\\n    function getMassetManager() external view returns (IMassetManager);\\n}\\n\",\"keccak256\":\"0x75da117f4bc4cca15fc16ca0466c68894f1befed0471ea7a670fa9b466ef2bc5\",\"license\":\"MIT\"},\"contracts/Interfaces/ICommunityIssuance.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\ninterface ICommunityIssuance { \\n    \\n    // --- Events ---\\n    \\n    event SOVTokenAddressSet(address _zeroTokenAddress);\\n    event ZUSDTokenAddressSet(address _zusdTokenAddress);\\n    event StabilityPoolAddressSet(address _stabilityPoolAddress);\\n    event PriceFeedAddressSet(address _priceFeed);\\n    event RewardManagerAddressSet(address _rewardManagerAddress);\\n    event APRSet(uint256 _APR);\\n\\n    // --- Functions ---\\n\\n    /**\\n     * @notice Called only once on init, to set addresses of other contracts. Callable only by owner.\\n     * @dev initializer function, checks addresses are contracts\\n     * @param _sovTokenAddress sov token address.\\n     * @param _zusdTokenAddress zero token address.\\n     * @param _stabilityPoolAddress stability pool address.\\n     * @param _priceFeed price feed address.\\n     * @param _APR apr in basis points.\\n     */\\n    function initialize(\\n        address _sovTokenAddress,\\n        address _zusdTokenAddress,\\n        address _stabilityPoolAddress,\\n        address _priceFeed,\\n        uint256 _APR\\n    ) external;\\n\\n    /**\\n     * @dev setter function to set the APR value in basis points.\\n     * can only be called by reward manager.\\n     * @param _APR apr value in basis points.\\n     */\\n    function setAPR(uint256 _APR) external;\\n\\n    /**\\n     * @dev setter function to set the price feed.\\n     * can only be called by the owner.\\n     * @param _priceFeedAddress price feed address.\\n     */\\n    function setPriceFeed(address _priceFeedAddress) external;\\n\\n    /**\\n     * @dev setter function to set reward manager.\\n     * can only be called by the owner.\\n     * @param _rewardManagerAddress reward manager address.\\n     */\\n    function setRewardManager(address _rewardManagerAddress) external;\\n\\n    /// @notice issues SOV tokens based on total zusd is deposited.\\n    /// @return SOV tokens issuance \\n    function issueSOV(uint256 _totalZUSDDeposits) external returns (uint256);\\n\\n    /// @notice sends ZERO tokens to given account\\n    /// @param _account account to receive the tokens\\n    /// @param _ZEROamount amount of tokens to transfer\\n    function sendSOV(address _account, uint _ZEROamount) external;\\n}\\n\",\"keccak256\":\"0x39b482323f5bfa1983ab020b5a8dc805116ffceb03f2729ffbe91b164403a96a\",\"license\":\"MIT\"},\"contracts/Interfaces/IDefaultPool.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\nimport \\\"./IPool.sol\\\";\\n\\ninterface IDefaultPool is IPool {\\n    // --- Events ---\\n    event TroveManagerAddressChanged(address _newTroveManagerAddress);\\n    event DefaultPoolZUSDDebtUpdated(uint256 _ZUSDDebt);\\n    event DefaultPoolETHBalanceUpdated(uint256 _ETH);\\n\\n    // --- Functions ---\\n\\n    /// @notice Send ETH to Active Pool\\n    /// @param _amount ETH to send\\n    function sendETHToActivePool(uint256 _amount) external;\\n}\\n\",\"keccak256\":\"0xfb2607676b2eb0f2defd248b4dd32895820048317f29aa6bdb572403a3e3d44e\",\"license\":\"MIT\"},\"contracts/Interfaces/IEIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.11;\\n\\ninterface IEIP712 {\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xff52e9168eaa532ebacdad2ab6197f60171e3aa2fa2c1d6397d9da4d7782a543\",\"license\":\"MIT\"},\"contracts/Interfaces/ILiquityBase.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\nimport \\\"./IPriceFeed.sol\\\";\\nimport \\\"./ILiquityBaseParams.sol\\\";\\n\\ninterface ILiquityBase {\\n    /// @return PriceFeed contract\\n    function priceFeed() external view returns (IPriceFeed);\\n\\n    /// @return LiquityBaseParams contract\\n    function liquityBaseParams() external view returns (ILiquityBaseParams);\\n}\\n\",\"keccak256\":\"0xa4a57bd79e64d56a687c28d2a35c55b733fde8dda2a7ba861606eed3211724e1\",\"license\":\"MIT\"},\"contracts/Interfaces/ILiquityBaseParams.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\ninterface ILiquityBaseParams {\\n\\n    /// Minimum collateral ratio for individual troves\\n    function MCR() external view returns (uint);\\n\\n    /// Critical system collateral ratio. If the system's total collateral ratio (TCR) falls below the CCR, Recovery Mode is triggered.\\n    function CCR() external view returns (uint);\\n\\n    function PERCENT_DIVISOR() external view returns (uint);\\n\\n    function BORROWING_FEE_FLOOR() external view returns (uint);\\n\\n    /**\\n     * Half-life of 12h. 12h = 720 min\\n     * (1/2) = d^720 => d = (1/2)^(1/720)\\n     */\\n    function REDEMPTION_FEE_FLOOR() external view returns (uint);\\n\\n    function MAX_BORROWING_FEE() external view returns (uint);\\n\\n}\",\"keccak256\":\"0xef8c0e8ad5d13d604c11b04983ff5bdd41768b646f2b33f45ddd988adec204e0\",\"license\":\"MIT\"},\"contracts/Interfaces/IPermit2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.11;\\npragma experimental ABIEncoderV2;\\n\\nimport {ISignatureTransfer} from \\\"./ISignatureTransfer.sol\\\";\\nimport {IAllowanceTransfer} from \\\"./IAllowanceTransfer.sol\\\";\\n\\n/// @notice Permit2 handles signature-based transfers in SignatureTransfer and allowance-based transfers in AllowanceTransfer.\\n/// @dev Users must approve Permit2 before calling any of the transfer functions.\\ninterface IPermit2 is ISignatureTransfer, IAllowanceTransfer {\\n// IPermit2 unifies the two interfaces so users have maximal flexibility with their approval.\\n}\\n\",\"keccak256\":\"0x3df819f5ca8de7324a676839d72e9f44c0f789c41c13bf0a892f3bb98d72ee86\",\"license\":\"MIT\"},\"contracts/Interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\n// Common interface for the Pools.\\ninterface IPool {\\n    // --- Events ---\\n\\n    event ETHBalanceUpdated(uint _newBalance);\\n    event ZUSDBalanceUpdated(uint _newBalance);\\n    event ActivePoolAddressChanged(address _newActivePoolAddress);\\n    event DefaultPoolAddressChanged(address _newDefaultPoolAddress);\\n    event StabilityPoolAddressChanged(address _newStabilityPoolAddress);\\n    event EtherSent(address _to, uint _amount);\\n\\n    // --- Functions ---\\n\\n    /// @notice Not necessarily equal to the raw ether balance - ether can be forcibly sent to contracts.\\n    /// @return ETH pool balance\\n    function getETH() external view returns (uint);\\n\\n    /// @return ZUSD debt pool balance\\n    function getZUSDDebt() external view returns (uint);\\n\\n    /// @notice Increases ZUSD debt of the pool.\\n    /// @param _amount ZUSD amount to add to the pool debt\\n    function increaseZUSDDebt(uint _amount) external;\\n\\n    /// @notice Decreases ZUSD debt of the pool.\\n    /// @param _amount ZUSD amount to subtract to the pool debt\\n    function decreaseZUSDDebt(uint _amount) external;\\n}\\n\",\"keccak256\":\"0x148e87ab38c6176d74f36c9e8989b99e768a7b18d8a045f1f01d6583b986806d\",\"license\":\"MIT\"},\"contracts/Interfaces/IPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\ninterface IPriceFeed {\\n    // --- Events ---\\n    event LastGoodPriceUpdated(uint256 _lastGoodPrice);\\n\\n    // --- Function ---\\n\\n    /// @notice Returns the latest price obtained from the Oracle. Called by Zero functions that require a current price.\\n    ///         It uses the main price feed and fallback to the backup one in case of an error. If both fail return the last\\n    ///         good price seen.\\n    /// @dev It's also callable by anyone externally\\n    /// @return The price\\n    function fetchPrice() external returns (uint256);\\n}\\n\",\"keccak256\":\"0x85fd97219a8156209d2cb5c6ae7c5ead01d893db000bf575023fcef0e62f9591\",\"license\":\"MIT\"},\"contracts/Interfaces/ISignatureTransfer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.11;\\npragma experimental ABIEncoderV2;\\n\\nimport {IEIP712} from \\\"./IEIP712.sol\\\";\\n\\n/// @title SignatureTransfer\\n/// @notice Handles ERC20 token transfers through signature based actions\\n/// @dev Requires user's token approval on the Permit2 contract\\ninterface ISignatureTransfer is IEIP712 {\\n    /// @notice Emits an event when the owner successfully invalidates an unordered nonce.\\n    event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask);\\n\\n    /// @notice The token and amount details for a transfer signed in the permit transfer signature\\n    struct TokenPermissions {\\n        // ERC20 token address\\n        address token;\\n        // the maximum amount that can be spent\\n        uint256 amount;\\n    }\\n\\n    /// @notice The signed permit message for a single token transfer\\n    struct PermitTransferFrom {\\n        TokenPermissions permitted;\\n        // a unique value for every token owner's signature to prevent signature replays\\n        uint256 nonce;\\n        // deadline on the permit signature\\n        uint256 deadline;\\n    }\\n\\n    /// @notice Specifies the recipient address and amount for batched transfers.\\n    /// @dev Recipients and amounts correspond to the index of the signed token permissions array.\\n    /// @dev Reverts if the requested amount is greater than the permitted signed amount.\\n    struct SignatureTransferDetails {\\n        // recipient address\\n        address to;\\n        // spender requested amount\\n        uint256 requestedAmount;\\n    }\\n\\n    /// @notice Used to reconstruct the signed permit message for multiple token transfers\\n    /// @dev Do not need to pass in spender address as it is required that it is msg.sender\\n    /// @dev Note that a user still signs over a spender address\\n    struct PermitBatchTransferFrom {\\n        // the tokens and corresponding amounts permitted for a transfer\\n        TokenPermissions[] permitted;\\n        // a unique value for every token owner's signature to prevent signature replays\\n        uint256 nonce;\\n        // deadline on the permit signature\\n        uint256 deadline;\\n    }\\n\\n    /// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection\\n    /// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order\\n    /// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce\\n    /// @dev It returns a uint256 bitmap\\n    /// @dev The index, or wordPosition is capped at type(uint248).max\\n    function nonceBitmap(address, uint256) external view returns (uint256);\\n\\n    /// @notice Transfers a token using a signed permit message\\n    /// @dev Reverts if the requested amount is greater than the permitted signed amount\\n    /// @param permit The permit data signed over by the owner\\n    /// @param owner The owner of the tokens to transfer\\n    /// @param transferDetails The spender's requested transfer details for the permitted token\\n    /// @param signature The signature to verify\\n    function permitTransferFrom(\\n        PermitTransferFrom memory permit,\\n        SignatureTransferDetails calldata transferDetails,\\n        address owner,\\n        bytes calldata signature\\n    ) external;\\n\\n    /// @notice Transfers multiple tokens using a signed permit message\\n    /// @param permit The permit data signed over by the owner\\n    /// @param owner The owner of the tokens to transfer\\n    /// @param transferDetails Specifies the recipient and requested amount for the token transfer\\n    /// @param signature The signature to verify\\n    function permitTransferFrom(\\n        PermitBatchTransferFrom memory permit,\\n        SignatureTransferDetails[] calldata transferDetails,\\n        address owner,\\n        bytes calldata signature\\n    ) external;\\n\\n    /// @notice Invalidates the bits specified in mask for the bitmap at the word position\\n    /// @dev The wordPos is maxed at type(uint248).max\\n    /// @param wordPos A number to index the nonceBitmap at\\n    /// @param mask A bitmap masked against msg.sender's current bitmap at the word position\\n    function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external;\\n}\\n\",\"keccak256\":\"0x7efc63c119694e23dd76e44a5b125999829026bbc23409de7646a6a45e1ac341\",\"license\":\"MIT\"},\"contracts/Interfaces/ISortedTroves.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\n// Common interface for the SortedTroves Doubly Linked List.\\ninterface ISortedTroves {\\n    // --- Events ---\\n\\n    event SortedTrovesAddressChanged(address _sortedDoublyLLAddress);\\n    event BorrowerOperationsAddressChanged(address _borrowerOperationsAddress);\\n    event NodeAdded(address _id, uint256 _NICR);\\n    event NodeRemoved(address _id);\\n\\n    // --- Functions ---\\n\\n    /**\\n     * @notice Called only once on init, to set addresses of other Zero contracts and size. Callable only by owner\\n     * @dev initializer function, checks addresses are contracts\\n     * @param _size max size of troves list\\n     * @param _TroveManagerAddress TroveManager contract address\\n     * @param _borrowerOperationsAddress BorrowerOperations contract address\\n     */\\n    function setParams(\\n        uint256 _size,\\n        address _TroveManagerAddress,\\n        address _borrowerOperationsAddress\\n    ) external;\\n\\n    /**\\n     * @dev Add a node to the list\\n     * @param _id Node's id\\n     * @param _ICR Node's NICR\\n     * @param _prevId Id of previous node for the insert position\\n     * @param _nextId Id of next node for the insert position\\n     */\\n    function insert(\\n        address _id,\\n        uint256 _ICR,\\n        address _prevId,\\n        address _nextId\\n    ) external;\\n\\n    /**\\n     * @dev Remove a node from the list\\n     * @param _id Node's id\\n     */\\n    function remove(address _id) external;\\n\\n    /**\\n     * @dev Re-insert the node at a new position, based on its new NICR\\n     * @param _id Node's id\\n     * @param _newICR Node's new NICR\\n     * @param _prevId Id of previous node for the new insert position\\n     * @param _nextId Id of next node for the new insert position\\n     */\\n    function reInsert(\\n        address _id,\\n        uint256 _newICR,\\n        address _prevId,\\n        address _nextId\\n    ) external;\\n\\n    /**\\n     * @dev Checks if the list contains a node\\n     * @param _id Node's id\\n     * @return true if list contains a node with given id\\n     */\\n    function contains(address _id) external view returns (bool);\\n\\n    /**\\n     * @dev Checks if the list is full\\n     * @return true if list is full\\n     */\\n    function isFull() external view returns (bool);\\n\\n    /**\\n     * @dev Checks if the list is empty\\n     * @return true if list is empty\\n     */\\n    function isEmpty() external view returns (bool);\\n\\n    /**\\n     * @return list current size\\n     */\\n    function getSize() external view returns (uint256);\\n\\n    /**\\n     * @return list max size\\n     */\\n    function getMaxSize() external view returns (uint256);\\n\\n    /**\\n     * @return the first node in the list (node with the largest NICR)\\n     */\\n    function getFirst() external view returns (address);\\n\\n    /**\\n     * @return the last node in the list (node with the smallest NICR)\\n     */\\n    function getLast() external view returns (address);\\n\\n    /**\\n     * @param _id Node's id\\n     * @return the next node (with a smaller NICR) in the list for a given node\\n     */\\n    function getNext(address _id) external view returns (address);\\n\\n    /**\\n     * @param _id Node's id\\n     * @return the previous node (with a larger NICR) in the list for a given node\\n     */\\n    function getPrev(address _id) external view returns (address);\\n\\n    /**\\n     * @notice Check if a pair of nodes is a valid insertion point for a new node with the given NICR\\n     * @param _ICR Node's NICR\\n     * @param _prevId Id of previous node for the insert position\\n     * @param _nextId Id of next node for the insert position\\n     */\\n    function validInsertPosition(\\n        uint256 _ICR,\\n        address _prevId,\\n        address _nextId\\n    ) external view returns (bool);\\n\\n    /**\\n     * @notice Find the insert position for a new node with the given NICR\\n     * @param _ICR Node's NICR\\n     * @param _prevId Id of previous node for the insert position\\n     * @param _nextId Id of next node for the insert position\\n     */\\n    function findInsertPosition(\\n        uint256 _ICR,\\n        address _prevId,\\n        address _nextId\\n    ) external view returns (address, address);\\n}\\n\",\"keccak256\":\"0x7328ad009da6230ddea1559564428464a5c3ace2258fb534dfbba5b5a8c7c60d\",\"license\":\"MIT\"},\"contracts/Interfaces/IStabilityPool.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../Dependencies/Mynt/IMassetManager.sol\\\";\\nimport { IPermit2, ISignatureTransfer } from \\\"./IPermit2.sol\\\";\\n\\n/*\\n * The Stability Pool holds ZUSD tokens deposited by Stability Pool depositors.\\n *\\n * When a trove is liquidated, then depending on system conditions, some of its ZUSD debt gets offset with\\n * ZUSD in the Stability Pool:  that is, the offset debt evaporates, and an equal amount of ZUSD tokens in the Stability Pool is burned.\\n *\\n * Thus, a liquidation causes each depositor to receive a ZUSD loss, in proportion to their deposit as a share of total deposits.\\n * They also receive an ETH gain, as the ETH collateral of the liquidated trove is distributed among Stability depositors,\\n * in the same proportion.\\n *\\n * When a liquidation occurs, it depletes every deposit by the same fraction: for example, a liquidation that depletes 40%\\n * of the total ZUSD in the Stability Pool, depletes 40% of each deposit.\\n *\\n * A deposit that has experienced a series of liquidations is termed a \\\"compounded deposit\\\": each liquidation depletes the deposit,\\n * multiplying it by some factor in range ]0,1[\\n *\\n * Please see the implementation spec in the proof document, which closely follows on from the compounded deposit / ETH gain derivations:\\n * https://github.com/liquity/liquity/blob/master/papers/Scalable_Reward_Distribution_with_Compounding_Stakes.pdf\\n *\\n * --- SOV ISSUANCE TO STABILITY POOL DEPOSITORS ---\\n *\\n * An SOV issuance event occurs at every deposit operation, and every liquidation.\\n *\\n * Each deposit is tagged with the address of the front end through which it was made.\\n *\\n * All deposits earn a share of the issued SOV in proportion to the deposit as a share of total deposits. The SOV earned\\n * by a given deposit, is split between the depositor and the front end through which the deposit was made, based on the front end's kickbackRate.\\n *\\n * Please see the system Readme for an overview:\\n * https://github.com/liquity/dev/blob/main/README.md#zero-issuance-to-stability-providers\\n */\\ninterface IStabilityPool {\\n    // --- Events ---\\n\\n    event StabilityPoolETHBalanceUpdated(uint _newBalance);\\n    event StabilityPoolZUSDBalanceUpdated(uint _newBalance);\\n\\n    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);\\n    event TroveManagerAddressChanged(address _newTroveManagerAddress);\\n    event ActivePoolAddressChanged(address _newActivePoolAddress);\\n    event DefaultPoolAddressChanged(address _newDefaultPoolAddress);\\n    event ZUSDTokenAddressChanged(address _newZUSDTokenAddress);\\n    event SortedTrovesAddressChanged(address _newSortedTrovesAddress);\\n    event PriceFeedAddressChanged(address _newPriceFeedAddress);\\n    event CommunityIssuanceAddressChanged(address _newCommunityIssuanceAddress);\\n\\n    event P_Updated(uint _P);\\n    event S_Updated(uint _S, uint128 _epoch, uint128 _scale);\\n    event G_Updated(uint _G, uint128 _epoch, uint128 _scale);\\n    event EpochUpdated(uint128 _currentEpoch);\\n    event ScaleUpdated(uint128 _currentScale);\\n\\n    event FrontEndRegistered(address indexed _frontEnd, uint _kickbackRate);\\n    event FrontEndTagSet(address indexed _depositor, address indexed _frontEnd);\\n\\n    event DepositSnapshotUpdated(address indexed _depositor, uint _P, uint _S, uint _G);\\n    event FrontEndSnapshotUpdated(address indexed _frontEnd, uint _P, uint _G);\\n    event UserDepositChanged(address indexed _depositor, uint _newDeposit);\\n    event FrontEndStakeChanged(\\n        address indexed _frontEnd,\\n        uint _newFrontEndStake,\\n        address _depositor\\n    );\\n\\n    event ETHGainWithdrawn(address indexed _depositor, uint _ETH, uint _ZUSDLoss);\\n    event SOVPaidToDepositor(address indexed _depositor, uint _SOV);\\n    event SOVPaidToFrontEnd(address indexed _frontEnd, uint _SOV);\\n    event EtherSent(address _to, uint _amount);\\n\\n    event WithdrawFromSpAndConvertToDLLR(\\n        address _depositor,\\n        uint256 _zusdAmountRequested,\\n        uint256 _dllrAmountReceived\\n    );\\n\\n    // --- Functions ---\\n\\n    /**\\n     * @notice Called only once on init, to set addresses of other Liquity contracts. Callable only by owner\\n     * @dev initializer function, checks addresses are contracts\\n     * @param _liquityBaseParamsAddress LiquidityBaseParams contract address\\n     * @param _borrowerOperationsAddress BorrowerOperations contract address\\n     * @param _troveManagerAddress TroveManager contract address\\n     * @param _activePoolAddress ActivePool contract address\\n     * @param _zusdTokenAddress ZUSDToken contract address\\n     * @param _sortedTrovesAddress SortedTroves contract address\\n     * @param _priceFeedAddress PriceFeed contract address\\n     * @param _communityIssuanceAddress CommunityIssuanceAddress\\n     */\\n    function setAddresses(\\n        address _liquityBaseParamsAddress,\\n        address _borrowerOperationsAddress,\\n        address _troveManagerAddress,\\n        address _activePoolAddress,\\n        address _zusdTokenAddress,\\n        address _sortedTrovesAddress,\\n        address _priceFeedAddress,\\n        address _communityIssuanceAddress\\n    ) external;\\n\\n    /**\\n     * @notice Initial checks:\\n     *  - Frontend is registered or zero address\\n     *  - Sender is not a registered frontend\\n     *  - _amount is not zero\\n     *  ---\\n     *  - Triggers a SOV issuance, based on time passed since the last issuance. The SOV issuance is shared between *all* depositors and front ends\\n     *  - Tags the deposit with the provided front end tag param, if it's a new deposit\\n     *  - Sends depositor's accumulated gains (SOV, ETH) to depositor\\n     *  - Sends the tagged front end's accumulated SOV gains to the tagged front end\\n     *  - Increases deposit and tagged front end's stake, and takes new snapshots for each.\\n     * @param _amount amount to provide\\n     * @param _frontEndTag frontend address to receive accumulated SOV gains\\n     */\\n    function provideToSP(uint _amount, address _frontEndTag) external;\\n\\n    /**\\n     * @notice Initial checks:\\n     *    - _amount is zero or there are no under collateralized troves left in the system\\n     *    - User has a non zero deposit\\n     *    ---\\n     *    - Triggers a SOV issuance, based on time passed since the last issuance. The SOV issuance is shared between *all* depositors and front ends\\n     *    - Removes the deposit's front end tag if it is a full withdrawal\\n     *    - Sends all depositor's accumulated gains (SOV, ETH) to depositor\\n     *    - Sends the tagged front end's accumulated SOV gains to the tagged front end\\n     *    - Decreases deposit and tagged front end's stake, and takes new snapshots for each.\\n     *\\n     *    If _amount > userDeposit, the user withdraws all of their compounded deposit.\\n     * @param _amount amount to withdraw\\n     */\\n    function withdrawFromSP(uint _amount) external;\\n\\n    /**\\n     * @notice Initial checks:\\n     *    - User has a non zero deposit\\n     *    - User has an open trove\\n     *    - User has some ETH gain\\n     *    ---\\n     *    - Triggers a SOV issuance, based on time passed since the last issuance. The SOV issuance is shared between *all* depositors and front ends\\n     *    - Sends all depositor's SOV gain to  depositor\\n     *    - Sends all tagged front end's SOV gain to the tagged front end\\n     *    - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove\\n     *    - Leaves their compounded deposit in the Stability Pool\\n     *    - Updates snapshots for deposit and tagged front end stake\\n     * @param _upperHint upper trove id hint\\n     * @param _lowerHint lower trove id hint\\n     */\\n    function withdrawETHGainToTrove(address _upperHint, address _lowerHint) external;\\n\\n    /**\\n     * @notice Initial checks:\\n     *    - Frontend (sender) not already registered\\n     *    - User (sender) has no deposit\\n     *    - _kickbackRate is in the range [0, 100%]\\n     *    ---\\n     *    Front end makes a one-time selection of kickback rate upon registering\\n     * @param _kickbackRate kickback rate selected by frontend\\n     */\\n    function registerFrontEnd(uint _kickbackRate) external;\\n\\n    /**\\n     * @notice Initial checks:\\n     *    - Caller is TroveManager\\n     *    ---\\n     *    Cancels out the specified debt against the ZUSD contained in the Stability Pool (as far as possible)\\n     *    and transfers the Trove's ETH collateral from ActivePool to StabilityPool.\\n     *    Only called by liquidation functions in the TroveManager.\\n     * @param _debt debt to cancel\\n     * @param _coll collateral to transfer\\n     */\\n    function offset(uint _debt, uint _coll) external;\\n\\n    /**\\n     * @return the total amount of ETH held by the pool, accounted in an internal variable instead of `balance`,\\n     * to exclude edge cases like ETH received from a self-destruct.\\n     */\\n    function getETH() external view returns (uint);\\n\\n    /**\\n     * @return ZUSD held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset.\\n     */\\n    function getTotalZUSDDeposits() external view returns (uint);\\n\\n    /**\\n     * @notice Calculates the ETH gain earned by the deposit since its last snapshots were taken.\\n     * @param _depositor address to calculate ETH gain\\n     * @return ETH gain from given depositor\\n     */\\n    function getDepositorETHGain(address _depositor) external view returns (uint);\\n\\n    /**\\n     * @notice Calculate the SOV gain earned by a deposit since its last snapshots were taken.\\n     *    If not tagged with a front end, the depositor gets a 100% cut of what their deposit earned.\\n     *    Otherwise, their cut of the deposit's earnings is equal to the kickbackRate, set by the front end through\\n     *    which they made their deposit.\\n     * @param _depositor address to calculate ETH gain\\n     * @return SOV gain from given depositor\\n     */\\n    function getDepositorSOVGain(address _depositor) external view returns (uint);\\n\\n    /**\\n     * @param _frontEnd front end address\\n     * @return the SOV gain earned by the front end.\\n     */\\n    function getFrontEndSOVGain(address _frontEnd) external view returns (uint);\\n\\n    /**\\n     * @param _depositor depositor address\\n     * @return the user's compounded deposit.\\n     */\\n    function getCompoundedZUSDDeposit(address _depositor) external view returns (uint);\\n\\n    /**\\n     * @notice The front end's compounded stake is equal to the sum of its depositors' compounded deposits.\\n     * @param _frontEnd front end address\\n     * @return the front end's compounded stake.\\n     */\\n    function getCompoundedFrontEndStake(address _frontEnd) external view returns (uint);\\n\\n    //DLLR _owner or _spender can convert a specified amount of DLLR into ZUSD via Sovryn Mynt and deposit the ZUSD into the Zero Stability Pool, all in a single transaction\\n    function provideToSpFromDLLR(\\n        uint _dllrAmount,\\n        IMassetManager.PermitParams calldata _permitParams\\n    ) external;\\n\\n    function provideToSpFromDllrWithPermit2(\\n        uint256 _dllrAmount,\\n        ISignatureTransfer.PermitTransferFrom memory _permit,\\n        bytes calldata _signature\\n    ) external;\\n\\n    /// Stability Pool depositor can withdraw a specified amount of ZUSD from the Zero Stability Pool and optionally convert the ZUSD to DLLR via Sovryn Mynt, all in a single transaction\\n    function withdrawFromSpAndConvertToDLLR(uint256 _zusdAmount) external;\\n\\n    /**\\n     * Fallback function\\n     * Only callable by Active Pool, it just accounts for ETH received\\n     * receive() external payable;\\n     */\\n}\\n\",\"keccak256\":\"0xb35c5ec991dd2b4f8ecb6b28ae29e97313fca6054aa0df14ebdb7336fcea84a6\",\"license\":\"MIT\"},\"contracts/Interfaces/ITroveManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"./ILiquityBase.sol\\\";\\nimport \\\"./IStabilityPool.sol\\\";\\nimport \\\"./IZUSDToken.sol\\\";\\nimport \\\"./IZEROToken.sol\\\";\\nimport \\\"./IZEROStaking.sol\\\";\\nimport \\\"../Dependencies/Mynt/IMassetManager.sol\\\";\\nimport { IPermit2, ISignatureTransfer } from \\\"./IPermit2.sol\\\";\\n\\n/// Common interface for the Trove Manager.\\ninterface ITroveManager is ILiquityBase {\\n    // --- Events ---\\n\\n    event FeeDistributorAddressChanged(address _feeDistributorAddress);\\n    event TroveManagerRedeemOpsAddressChanged(address _troveManagerRedeemOps);\\n    event LiquityBaseParamsAddressChanges(address _borrowerOperationsAddress);\\n    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);\\n    event PriceFeedAddressChanged(address _newPriceFeedAddress);\\n    event ZUSDTokenAddressChanged(address _newZUSDTokenAddress);\\n    event ActivePoolAddressChanged(address _activePoolAddress);\\n    event DefaultPoolAddressChanged(address _defaultPoolAddress);\\n    event StabilityPoolAddressChanged(address _stabilityPoolAddress);\\n    event GasPoolAddressChanged(address _gasPoolAddress);\\n    event CollSurplusPoolAddressChanged(address _collSurplusPoolAddress);\\n    event SortedTrovesAddressChanged(address _sortedTrovesAddress);\\n    event ZEROTokenAddressChanged(address _zeroTokenAddress);\\n    event ZEROStakingAddressChanged(address _zeroStakingAddress);\\n\\n    event Liquidation(\\n        uint256 _liquidatedDebt,\\n        uint256 _liquidatedColl,\\n        uint256 _collGasCompensation,\\n        uint256 _ZUSDGasCompensation\\n    );\\n    event Redemption(\\n        uint256 _attemptedZUSDAmount,\\n        uint256 _actualZUSDAmount,\\n        uint256 _ETHSent,\\n        uint256 _ETHFee\\n    );\\n    event TroveUpdated(\\n        address indexed _borrower,\\n        uint256 _debt,\\n        uint256 _coll,\\n        uint256 stake,\\n        uint8 operation\\n    );\\n    event TroveLiquidated(\\n        address indexed _borrower,\\n        uint256 _debt,\\n        uint256 _coll,\\n        uint8 operation\\n    );\\n    event BaseRateUpdated(uint256 _baseRate);\\n    event LastFeeOpTimeUpdated(uint256 _lastFeeOpTime);\\n    event TotalStakesUpdated(uint256 _newTotalStakes);\\n    event SystemSnapshotsUpdated(uint256 _totalStakesSnapshot, uint256 _totalCollateralSnapshot);\\n    event LTermsUpdated(uint256 _L_ETH, uint256 _L_ZUSDDebt);\\n    event TroveSnapshotsUpdated(uint256 _L_ETH, uint256 _L_ZUSDDebt);\\n    event TroveIndexUpdated(address _borrower, uint256 _newIndex);\\n\\n    struct TroveManagerInitAddressesParams {\\n        address _feeDistributorAddress;\\n        address _troveManagerRedeemOps;\\n        address _liquityBaseParamsAddress;\\n        address _borrowerOperationsAddress;\\n        address _activePoolAddress;\\n        address _defaultPoolAddress;\\n        address _stabilityPoolAddress;\\n        address _gasPoolAddress;\\n        address _collSurplusPoolAddress;\\n        address _priceFeedAddress;\\n        address _zusdTokenAddress;\\n        address _sortedTrovesAddress;\\n        address _zeroTokenAddress;\\n        address _zeroStakingAddress;\\n    }\\n\\n    // --- Functions ---\\n    /**\\n     * @notice Called only once on init, to set addresses of other Zero contracts. Callable only by owner\\n     * @dev initializer function, checks addresses are contracts\\n     * @param _troveManagerInitAddresses addresses list to intialize TroveManager with _\\n     *        _feeDistributorAddress feeDistributor contract address\\n     *        _troveManagerRedeemOps TroveManagerRedeemOps contract address\\n     *        _liquityBaseParamsAddress LiquityBaseParams contract address\\n     *        _borrowerOperationsAddress BorrowerOperations contract address\\n     *        _activePoolAddress ActivePool contract address\\n     *        _defaultPoolAddress DefaultPool contract address\\n     *        _stabilityPoolAddress StabilityPool contract address\\n     *        _gasPoolAddress GasPool contract address\\n     *        _collSurplusPoolAddress CollSurplusPool contract address\\n     *        _priceFeedAddress PriceFeed contract address\\n     *        _zusdTokenAddress ZUSDToken contract address\\n     *        _sortedTrovesAddress SortedTroves contract address\\n     *        _zeroTokenAddress ZEROToken contract address\\n     *        _zeroStakingAddress ZEROStaking contract address\\n     */\\n    function setAddresses(\\n        TroveManagerInitAddressesParams memory _troveManagerInitAddresses\\n    ) external;\\n\\n    function setTroveManagerRedeemOps(address _troveManagerRedeemOps) external;\\n\\n    /// @return Trove owners count\\n    function getTroveOwnersCount() external view returns (uint256);\\n\\n    /// @param _index Trove owner index\\n    /// @return Trove from TroveOwners array in given index\\n    function getTroveFromTroveOwnersArray(uint256 _index) external view returns (address);\\n\\n    /// @param _borrower borrower address\\n    /// @return the nominal collateral ratio (ICR) of a given Trove, without the price. Takes a trove's pending coll and debt rewards from redistributions into account.\\n    function getNominalICR(address _borrower) external view returns (uint256);\\n\\n    /// @notice computes the user\\u2019s individual collateralization ratio (ICR) based on their total collateral and total ZUSD debt. Returns 2^256 -1 if they have 0 debt.\\n    /// @param _borrower borrower address\\n    /// @param _price ETH price\\n    /// @return the current collateral ratio (ICR) of a given Trove. Takes a trove's pending coll and debt rewards from redistributions into account.\\n    function getCurrentICR(address _borrower, uint256 _price) external view returns (uint256);\\n\\n    /// @notice Closes the trove if its ICR is lower than the minimum collateral ratio.\\n    /// @param _borrower borrower address\\n    function liquidate(address _borrower) external;\\n\\n    /**\\n     * @notice Liquidate a sequence of troves. Closes a maximum number of n under-collateralized Troves,\\n     * starting from the one with the lowest collateral ratio in the system, and moving upwards\\n     * @param _n max number of under-collateralized Troves to liquidate\\n     */\\n    function liquidateTroves(uint256 _n) external;\\n\\n    /**\\n     * @notice Attempt to liquidate a custom list of troves provided by the caller.\\n     * @param _troveArray list of trove addresses\\n     */\\n    function batchLiquidateTroves(address[] calldata _troveArray) external;\\n\\n    /**\\n     * @notice Send _ZUSDamount ZUSD to the system and redeem the corresponding amount of collateral from as many Troves as are needed to fill the redemption\\n     * request.  Applies pending rewards to a Trove before reducing its debt and coll.\\n     *\\n     * Note that if _amount is very large, this function can run out of gas, specially if traversed troves are small. This can be easily avoided by\\n     * splitting the total _amount in appropriate chunks and calling the function multiple times.\\n     *\\n     * Param `_maxIterations` can also be provided, so the loop through Troves is capped (if it\\u2019s zero, it will be ignored).This makes it easier to\\n     * avoid OOG for the frontend, as only knowing approximately the average cost of an iteration is enough, without needing to know the \\u201ctopology\\u201d\\n     * of the trove list. It also avoids the need to set the cap in stone in the contract, nor doing gas calculations, as both gas price and opcode\\n     * costs can vary.\\n     *\\n     * All Troves that are redeemed from -- with the likely exception of the last one -- will end up with no debt left, therefore they will be closed.\\n     * If the last Trove does have some remaining debt, it has a finite ICR, and the reinsertion could be anywhere in the list, therefore it requires a hint.\\n     * A frontend should use getRedemptionHints() to calculate what the ICR of this Trove will be after redemption, and pass a hint for its position\\n     * in the sortedTroves list along with the ICR value that the hint was found for.\\n     *\\n     * If another transaction modifies the list between calling getRedemptionHints() and passing the hints to redeemCollateral(), it\\n     * is very likely that the last (partially) redeemed Trove would end up with a different ICR than what the hint is for. In this case the\\n     * redemption will stop after the last completely redeemed Trove and the sender will keep the remaining ZUSD amount, which they can attempt\\n     * to redeem later.\\n     *\\n     * @param _ZUSDAmount ZUSD amount to send to the system\\n     * @param _firstRedemptionHint calculated ICR hint of first trove after redemption\\n     * @param _maxIterations max Troves iterations (can be 0)\\n     * @param _maxFee max fee percentage to accept\\n     */\\n    function redeemCollateral(\\n        uint256 _ZUSDAmount,\\n        address _firstRedemptionHint,\\n        address _upperPartialRedemptionHint,\\n        address _lowerPartialRedemptionHint,\\n        uint256 _partialRedemptionHintNICR,\\n        uint256 _maxIterations,\\n        uint256 _maxFee\\n    ) external;\\n\\n    function redeemCollateralViaDLLR(\\n        uint256 _dllrAmount,\\n        address _firstRedemptionHint,\\n        address _upperPartialRedemptionHint,\\n        address _lowerPartialRedemptionHint,\\n        uint256 _partialRedemptionHintNICR,\\n        uint256 _maxIterations,\\n        uint256 _maxFeePercentage,\\n        IMassetManager.PermitParams calldata _permitParams\\n    ) external;\\n\\n    function redeemCollateralViaDllrWithPermit2(\\n        uint256 _dllrAmount,\\n        address _firstRedemptionHint,\\n        address _upperPartialRedemptionHint,\\n        address _lowerPartialRedemptionHint,\\n        uint256 _partialRedemptionHintNICR,\\n        uint256 _maxIterations,\\n        uint256 _maxFeePercentage,\\n        ISignatureTransfer.PermitTransferFrom memory _permit,\\n        bytes calldata _signature\\n    ) external;\\n    \\n\\n    /// @notice Update borrower's stake based on their latest collateral value\\n    /// @param _borrower borrower address\\n    function updateStakeAndTotalStakes(address _borrower) external returns (uint256);\\n\\n    /// @notice Update borrower's snapshots of L_ETH and L_ZUSDDebt to reflect the current values\\n    /// @param _borrower borrower address\\n    function updateTroveRewardSnapshots(address _borrower) external;\\n\\n    /// @notice Push the owner's address to the Trove owners list, and record the corresponding array index on the Trove struct\\n    /// @param _borrower borrower address\\n    /// @return index where Trove was inserted\\n    function addTroveOwnerToArray(address _borrower) external returns (uint256 index);\\n\\n    /// @notice Add the borrowers's coll and debt rewards earned from redistributions, to their Trove\\n    /// @param _borrower borrower address\\n    function applyPendingRewards(address _borrower) external;\\n\\n    /// @param _borrower borrower address\\n    /// @return the borrower's pending accumulated ETH reward, earned by their stake\\n    function getPendingETHReward(address _borrower) external view returns (uint256);\\n\\n    /// @param _borrower borrower address\\n    /// @return the borrower's pending accumulated ZUSD reward, earned by their stake\\n    function getPendingZUSDDebtReward(address _borrower) external view returns (uint256);\\n\\n    /*\\n     * @notice A Trove has pending rewards if its snapshot is less than the current rewards per-unit-staked sum:\\n     * this indicates that rewards have occured since the snapshot was made, and the user therefore has\\n     * pending rewards\\n     *\\n     * @param _borrower borrower address\\n     * @return true if has pending rewards\\n     */\\n    function hasPendingRewards(address _borrower) external view returns (bool);\\n\\n    /// @notice returns the Troves entire debt and coll, including pending rewards from redistributions.\\n    /// @param _borrower borrower address\\n    function getEntireDebtAndColl(\\n        address _borrower\\n    )\\n        external\\n        view\\n        returns (\\n            uint256 debt,\\n            uint256 coll,\\n            uint256 pendingZUSDDebtReward,\\n            uint256 pendingETHReward\\n        );\\n\\n    /// @notice Close given trove. Called by BorrowerOperations.\\n    /// @param _borrower borrower address\\n    function closeTrove(address _borrower) external;\\n\\n    /// @notice Remove borrower's stake from the totalStakes sum, and set their stake to 0\\n    /// @param _borrower borrower address\\n    function removeStake(address _borrower) external;\\n\\n    /// @return calculated redemption rate using baseRate\\n    function getRedemptionRate() external view returns (uint256);\\n\\n    /// @return calculated redemption rate using calculated decayed as base rate\\n    function getRedemptionRateWithDecay() external view returns (uint256);\\n\\n    /// @notice The redemption fee is taken as a cut of the total ETH drawn from the system in a redemption. It is based on the current redemption rate.\\n    /// @param _ETHDrawn ETH drawn\\n    function getRedemptionFeeWithDecay(uint256 _ETHDrawn) external view returns (uint256);\\n\\n    /// @return borrowing rate\\n    function getBorrowingRate() external view returns (uint256);\\n\\n    /// @return borrowing rate calculated using decayed as base rate\\n    function getBorrowingRateWithDecay() external view returns (uint256);\\n\\n    /// @param ZUSDDebt ZUSD debt amount to calculate fee\\n    /// @return borrowing fee using borrowing rate\\n    function getBorrowingFee(uint256 ZUSDDebt) external view returns (uint256);\\n\\n    /// @param _ZUSDDebt ZUSD debt amount to calculate fee\\n    /// @return borrowing fee using borrowing rate with decay\\n    function getBorrowingFeeWithDecay(uint256 _ZUSDDebt) external view returns (uint256);\\n\\n    /// @notice Updates the baseRate state variable based on time elapsed since the last redemption or ZUSD borrowing operation.\\n    function decayBaseRateFromBorrowing() external;\\n\\n    /// @param _borrower borrower address\\n    /// @return Trove status from given trove\\n    function getTroveStatus(address _borrower) external view returns (uint256);\\n\\n    /// @param _borrower borrower address\\n    /// @return Trove stake from given trove\\n    function getTroveStake(address _borrower) external view returns (uint256);\\n\\n    /// @param _borrower borrower address\\n    /// @return Trove debt from given trove\\n    function getTroveDebt(address _borrower) external view returns (uint256);\\n\\n    /// @param _borrower borrower address\\n    /// @return Trove collateral from given trove\\n    function getTroveColl(address _borrower) external view returns (uint256);\\n\\n    /// @param _borrower borrower address\\n    /// @param num status to set\\n    function setTroveStatus(address _borrower, uint256 num) external;\\n\\n    /// @param _borrower borrower address\\n    /// @param _collIncrease amount of collateral to increase\\n    /// @return new trove collateral\\n    function increaseTroveColl(\\n        address _borrower,\\n        uint256 _collIncrease\\n    ) external returns (uint256);\\n\\n    /// @param _borrower borrower address\\n    /// @param _collDecrease amount of collateral to decrease\\n    /// @return new trove collateral\\n    function decreaseTroveColl(\\n        address _borrower,\\n        uint256 _collDecrease\\n    ) external returns (uint256);\\n\\n    /// @param _borrower borrower address\\n    /// @param _debtIncrease amount of debt to increase\\n    /// @return new trove debt\\n    function increaseTroveDebt(\\n        address _borrower,\\n        uint256 _debtIncrease\\n    ) external returns (uint256);\\n\\n    /// @param _borrower borrower address\\n    /// @param _debtDecrease amount of debt to decrease\\n    /// @return new trove debt\\n    function decreaseTroveDebt(\\n        address _borrower,\\n        uint256 _debtDecrease\\n    ) external returns (uint256);\\n\\n    /**\\n     * @param _price ETH price\\n     * @return the total collateralization ratio (TCR) of the system.\\n     * The TCR is based on the the entire system debt and collateral (including pending rewards).\\n     */\\n    function getTCR(uint256 _price) external view returns (uint256);\\n\\n    function MCR() external view returns (uint256);\\n\\n    function CCR() external view returns (uint256);\\n\\n    /// @notice reveals whether or not the system is in Recovery Mode (i.e. whether the Total Collateralization Ratio (TCR) is below the Critical Collateralization Ratio (CCR)).\\n    function checkRecoveryMode(uint256 _price) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x396367eb7763c289e419a025532150e2a1d9d99eead359ceb6a081787501a00b\",\"license\":\"MIT\"},\"contracts/Interfaces/IZEROStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\ninterface IZEROStaking {\\n    // --- Events --\\n\\n    event ZEROTokenAddressSet(address _zeroTokenAddress);\\n    event ZUSDTokenAddressSet(address _zusdTokenAddress);\\n    event FeeDistributorAddressAddressSet(address _feeDistributorAddress);\\n    event ActivePoolAddressSet(address _activePoolAddress);\\n\\n    event StakeChanged(address indexed staker, uint256 newStake);\\n    event StakingGainsWithdrawn(address indexed staker, uint256 ZUSDGain, uint256 ETHGain);\\n    event F_ETHUpdated(uint256 _F_ETH);\\n    event F_ZUSDUpdated(uint256 _F_ZUSD);\\n    event TotalZEROStakedUpdated(uint256 _totalZEROStaked);\\n    event EtherSent(address _account, uint256 _amount);\\n    event StakerSnapshotsUpdated(address _staker, uint256 _F_ETH, uint256 _F_ZUSD);\\n\\n    // --- Functions ---\\n\\n    /**\\n     * @notice Called only once on init, to set addresses of other Zero contracts. Callable only by owner\\n     * @dev initializer function, checks addresses are contracts\\n     * @param _zeroTokenAddress ZEROToken contract address\\n     * @param _zusdTokenAddress ZUSDToken contract address\\n     * @param _feeDistributorAddress FeeDistributorAddress contract address\\n     * @param _activePoolAddress ActivePool contract address\\n     */\\n    function setAddresses(\\n        address _zeroTokenAddress,\\n        address _zusdTokenAddress,\\n        address _feeDistributorAddress,\\n        address _activePoolAddress\\n    ) external;\\n\\n    /// @notice If caller has a pre-existing stake, send any accumulated ETH and ZUSD gains to them.\\n    /// @param _ZEROamount ZERO tokens to stake\\n    function stake(uint256 _ZEROamount) external;\\n\\n    /**\\n     * @notice Unstake the ZERO and send the it back to the caller, along with their accumulated ZUSD & ETH gains.\\n     * If requested amount > stake, send their entire stake.\\n     * @param _ZEROamount ZERO tokens to unstake\\n     */\\n    function unstake(uint256 _ZEROamount) external;\\n\\n    /// @param _ETHFee ETH fee\\n    /// @notice increase ETH fee\\n    function increaseF_ETH(uint256 _ETHFee) external;\\n\\n    /// @param _ZEROFee ZUSD fee\\n    /// @notice increase ZUSD fee\\n    function increaseF_ZUSD(uint256 _ZEROFee) external;\\n\\n    /// @param _user user address\\n    /// @return pending ETH gain of given user\\n    function getPendingETHGain(address _user) external view returns (uint256);\\n\\n    /// @param _user user address\\n    /// @return pending ZUSD gain of given user\\n    function getPendingZUSDGain(address _user) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x4c7948ce7dff9ea9b8495054e511eabcf44a91c7db8520ec58ff2a002327e0c5\",\"license\":\"MIT\"},\"contracts/Interfaces/IZEROToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\nimport \\\"../Dependencies/IERC20.sol\\\";\\nimport \\\"../Dependencies/IERC2612.sol\\\";\\n\\ninterface IZEROToken is IERC20, IERC2612 { \\n\\n    // --- Functions ---\\n\\n    /// @notice send zero tokens to ZEROStaking contract\\n    /// @param _sender sender address\\n    /// @param _amount amount to send\\n    function sendToZEROStaking(address _sender, uint256 _amount) external;\\n\\n    /// @return deployment start time\\n    function getDeploymentStartTime() external view returns (uint256);\\n\\n}\\n\",\"keccak256\":\"0xbcc0baabe4c4686563a09cf1486f2d152b70404996676a89d525691f69637f66\",\"license\":\"MIT\"},\"contracts/Interfaces/IZUSDToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\nimport \\\"../Dependencies/IERC20.sol\\\";\\nimport \\\"../Dependencies/IERC2612.sol\\\";\\n\\ninterface IZUSDToken is IERC20, IERC2612 { \\n    \\n    // --- Events ---\\n\\n    event TroveManagerAddressChanged(address _troveManagerAddress);\\n    event StabilityPoolAddressChanged(address _newStabilityPoolAddress);\\n    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);\\n\\n    event ZUSDTokenBalanceUpdated(address _user, uint _amount);\\n\\n    // --- Functions ---\\n\\n    function mint(address _account, uint256 _amount) external;\\n\\n    function burn(address _account, uint256 _amount) external;\\n\\n    function sendToPool(address _sender,  address poolAddress, uint256 _amount) external;\\n\\n    function returnFromPool(address poolAddress, address user, uint256 _amount ) external;\\n}\\n\",\"keccak256\":\"0xe52df063aa08f709640c28888edd27310c820f6d08564855538ae245eb2f5a8c\",\"license\":\"MIT\"},\"contracts/StabilityPool.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"./Interfaces/IBorrowerOperations.sol\\\";\\nimport \\\"./Interfaces/IStabilityPool.sol\\\";\\nimport \\\"./Interfaces/ITroveManager.sol\\\";\\nimport \\\"./Interfaces/IZUSDToken.sol\\\";\\nimport \\\"./Interfaces/ISortedTroves.sol\\\";\\nimport \\\"./Interfaces/ICommunityIssuance.sol\\\";\\nimport \\\"./Dependencies/LiquityBase.sol\\\";\\nimport \\\"./Dependencies/LiquitySafeMath128.sol\\\";\\nimport \\\"./Dependencies/CheckContract.sol\\\";\\nimport \\\"./Dependencies/Mynt/MyntLib.sol\\\";\\nimport \\\"./StabilityPoolStorage.sol\\\";\\nimport \\\"./Interfaces/IPermit2.sol\\\";\\n\\n/**\\n * The Stability Pool holds ZUSD tokens deposited by Stability Pool depositors.\\n *\\n * When a trove is liquidated, then depending on system conditions, some of its ZUSD debt gets offset with\\n * ZUSD in the Stability Pool:  that is, the offset debt evaporates, and an equal amount of ZUSD tokens in the Stability Pool is burned.\\n *\\n * Thus, a liquidation causes each depositor to receive a ZUSD loss, in proportion to their deposit as a share of total deposits.\\n * They also receive an ETH gain, as the ETH collateral of the liquidated trove is distributed among Stability depositors,\\n * in the same proportion.\\n *\\n * When a liquidation occurs, it depletes every deposit by the same fraction: for example, a liquidation that depletes 40%\\n * of the total ZUSD in the Stability Pool, depletes 40% of each deposit.\\n *\\n * A deposit that has experienced a series of liquidations is termed a \\\"compounded deposit\\\": each liquidation depletes the deposit,\\n * multiplying it by some factor in range ]0,1[\\n *\\n *\\n * --- IMPLEMENTATION ---\\n *\\n * We use a highly scalable method of tracking deposits and ETH gains that has O(1) complexity.\\n *\\n * When a liquidation occurs, rather than updating each depositor's deposit and ETH gain, we simply update two state variables:\\n * a product P, and a sum S.\\n *\\n * A mathematical manipulation allows us to factor out the initial deposit, and accurately track all depositors' compounded deposits\\n * and accumulated ETH gains over time, as liquidations occur, using just these two variables P and S. When depositors join the\\n * Stability Pool, they get a snapshot of the latest P and S: P_t and S_t, respectively.\\n *\\n * The formula for a depositor's accumulated ETH gain is derived here:\\n * https://github.com/liquity/dev/blob/main/packages/contracts/mathProofs/Scalable%20Compounding%20Stability%20Pool%20Deposits.pdf\\n *\\n * For a given deposit d_t, the ratio P/P_t tells us the factor by which a deposit has decreased since it joined the Stability Pool,\\n * and the term d_t * (S - S_t)/P_t gives us the deposit's total accumulated ETH gain.\\n *\\n * Each liquidation updates the product P and sum S. After a series of liquidations, a compounded deposit and corresponding ETH gain\\n * can be calculated using the initial deposit, the depositor\\u2019s snapshots of P and S, and the latest values of P and S.\\n *\\n * Any time a depositor updates their deposit (withdrawal, top-up) their accumulated ETH gain is paid out, their new deposit is recorded\\n * (based on their latest compounded deposit and modified by the withdrawal/top-up), and they receive new snapshots of the latest P and S.\\n * Essentially, they make a fresh deposit that overwrites the old one.\\n *\\n *\\n * --- SCALE FACTOR ---\\n *\\n * Since P is a running product in range ]0,1] that is always-decreasing, it should never reach 0 when multiplied by a number in range ]0,1[.\\n * Unfortunately, Solidity floor division always reaches 0, sooner or later.\\n *\\n * A series of liquidations that nearly empty the Pool (and thus each multiply P by a very small number in range ]0,1[ ) may push P\\n * to its 18 digit decimal limit, and round it to 0, when in fact the Pool hasn't been emptied: this would break deposit tracking.\\n *\\n * So, to track P accurately, we use a scale factor: if a liquidation would cause P to decrease to <1e-9 (and be rounded to 0 by Solidity),\\n * we first multiply P by 1e9, and increment a currentScale factor by 1.\\n *\\n * The added benefit of using 1e9 for the scale factor (rather than 1e18) is that it ensures negligible precision loss close to the\\n * scale boundary: when P is at its minimum value of 1e9, the relative precision loss in P due to floor division is only on the\\n * order of 1e-9.\\n *\\n * --- EPOCHS ---\\n *\\n * Whenever a liquidation fully empties the Stability Pool, all deposits should become 0. However, setting P to 0 would make P be 0\\n * forever, and break all future reward calculations.\\n *\\n * So, every time the Stability Pool is emptied by a liquidation, we reset P = 1 and currentScale = 0, and increment the currentEpoch by 1.\\n *\\n * --- TRACKING DEPOSIT OVER SCALE CHANGES AND EPOCHS ---\\n *\\n * When a deposit is made, it gets snapshots of the currentEpoch and the currentScale.\\n *\\n * When calculating a compounded deposit, we compare the current epoch to the deposit's epoch snapshot. If the current epoch is newer,\\n * then the deposit was present during a pool-emptying liquidation, and necessarily has been depleted to 0.\\n *\\n * Otherwise, we then compare the current scale to the deposit's scale snapshot. If they're equal, the compounded deposit is given by d_t * P/P_t.\\n * If it spans one scale change, it is given by d_t * P/(P_t * 1e9). If it spans more than one scale change, we define the compounded deposit\\n * as 0, since it is now less than 1e-9'th of its initial value (e.g. a deposit of 1 billion ZUSD has depleted to < 1 ZUSD).\\n *\\n *\\n *  --- TRACKING DEPOSITOR'S ETH GAIN OVER SCALE CHANGES AND EPOCHS ---\\n *\\n * In the current epoch, the latest value of S is stored upon each scale change, and the mapping (scale -> S) is stored for each epoch.\\n *\\n * This allows us to calculate a deposit's accumulated ETH gain, during the epoch in which the deposit was non-zero and earned ETH.\\n *\\n * We calculate the depositor's accumulated ETH gain for the scale at which they made the deposit, using the ETH gain formula:\\n * e_1 = d_t * (S - S_t) / P_t\\n *\\n * and also for scale after, taking care to divide the latter by a factor of 1e9:\\n * e_2 = d_t * S / (P_t * 1e9)\\n *\\n * The gain in the second scale will be full, as the starting point was in the previous scale, thus no need to subtract anything.\\n * The deposit therefore was present for reward events from the beginning of that second scale.\\n *\\n *        S_i-S_t + S_{i+1}\\n *      .<--------.------------>\\n *      .         .\\n *      . S_i     .   S_{i+1}\\n *   <--.-------->.<----------->\\n *   S_t.         .\\n *   <->.         .\\n *      t         .\\n *  |---+---------|-------------|-----...\\n *         i            i+1\\n *\\n * The sum of (e_1 + e_2) captures the depositor's total accumulated ETH gain, handling the case where their\\n * deposit spanned one scale change. We only care about gains across one scale change, since the compounded\\n * deposit is defined as being 0 once it has spanned more than one scale change.\\n *\\n *\\n * --- UPDATING P WHEN A LIQUIDATION OCCURS ---\\n *\\n * Please see the implementation spec in the proof document, which closely follows on from the compounded deposit / ETH gain derivations:\\n * https://github.com/liquity/liquity/blob/master/papers/Scalable_Reward_Distribution_with_Compounding_Stakes.pdf\\n *\\n *\\n * --- SOV ISSUANCE TO STABILITY POOL DEPOSITORS ---\\n *\\n * An SOV issuance event occurs at every deposit operation, and every liquidation.\\n *\\n * Each deposit is tagged with the address of the front end through which it was made.\\n *\\n * All deposits earn a share of the issued SOV in proportion to the deposit as a share of total deposits. The SOV earned\\n * by a given deposit, is split between the depositor and the front end through which the deposit was made, based on the front end's kickbackRate.\\n *\\n * Please see the system Readme for an overview:\\n * https://github.com/liquity/dev/blob/main/README.md#zero-issuance-to-stability-providers\\n *\\n * We use the same mathematical product-sum approach to track SOV gains for depositors, where 'G' is the sum corresponding to SOV gains.\\n * The product P (and snapshot P_t) is re-used, as the ratio P/P_t tracks a deposit's depletion due to liquidations.\\n *\\n */\\ncontract StabilityPool is LiquityBase, StabilityPoolStorage, CheckContract, IStabilityPool {\\n    using LiquitySafeMath128 for uint128;\\n    address private constant ADDRESS_ZERO = address(0);\\n    IPermit2 public immutable permit2;\\n\\n    // --- Events ---\\n\\n    event StabilityPoolETHBalanceUpdated(uint256 _newBalance);\\n    event StabilityPoolZUSDBalanceUpdated(uint256 _newBalance);\\n\\n    event BorrowerOperationsAddressChanged(address _newBorrowerOperationsAddress);\\n    event TroveManagerAddressChanged(address _newTroveManagerAddress);\\n    event ActivePoolAddressChanged(address _newActivePoolAddress);\\n    event DefaultPoolAddressChanged(address _newDefaultPoolAddress);\\n    event ZUSDTokenAddressChanged(address _newZUSDTokenAddress);\\n    event SortedTrovesAddressChanged(address _newSortedTrovesAddress);\\n    event PriceFeedAddressChanged(address _newPriceFeedAddress);\\n    event CommunityIssuanceAddressChanged(address _newCommunityIssuanceAddress);\\n\\n    event P_Updated(uint256 _P);\\n    event S_Updated(uint256 _S, uint128 _epoch, uint128 _scale);\\n    event G_Updated(uint256 _G, uint128 _epoch, uint128 _scale);\\n    event EpochUpdated(uint128 _currentEpoch);\\n    event ScaleUpdated(uint128 _currentScale);\\n\\n    event FrontEndRegistered(address indexed _frontEnd, uint256 _kickbackRate);\\n    event FrontEndTagSet(address indexed _depositor, address indexed _frontEnd);\\n\\n    event DepositSnapshotUpdated(address indexed _depositor, uint256 _P, uint256 _S, uint256 _G);\\n    event FrontEndSnapshotUpdated(address indexed _frontEnd, uint256 _P, uint256 _G);\\n    event UserDepositChanged(address indexed _depositor, uint256 _newDeposit);\\n    event FrontEndStakeChanged(\\n        address indexed _frontEnd,\\n        uint256 _newFrontEndStake,\\n        address _depositor\\n    );\\n\\n    event ETHGainWithdrawn(address indexed _depositor, uint256 _ETH, uint256 _ZUSDLoss);\\n    event SOVPaidToDepositor(address indexed _depositor, uint256 _SOV);\\n    event SOVPaidToFrontEnd(address indexed _frontEnd, uint256 _SOV);\\n    event EtherSent(address _to, uint256 _amount);\\n\\n    /** Constructor */\\n    constructor(address _permit2) public {\\n        permit2 = IPermit2(_permit2);\\n    }\\n\\n    // --- Contract setters ---\\n\\n    function setAddresses(\\n        address _liquityBaseParamsAddress,\\n        address _borrowerOperationsAddress,\\n        address _troveManagerAddress,\\n        address _activePoolAddress,\\n        address _zusdTokenAddress,\\n        address _sortedTrovesAddress,\\n        address _priceFeedAddress,\\n        address _communityIssuanceAddress\\n    ) external override onlyOwner {\\n        checkContract(_liquityBaseParamsAddress);\\n        checkContract(_borrowerOperationsAddress);\\n        checkContract(_troveManagerAddress);\\n        checkContract(_activePoolAddress);\\n        checkContract(_zusdTokenAddress);\\n        checkContract(_sortedTrovesAddress);\\n        checkContract(_priceFeedAddress);\\n        checkContract(_communityIssuanceAddress);\\n\\n        P = DECIMAL_PRECISION;\\n\\n        liquityBaseParams = ILiquityBaseParams(_liquityBaseParamsAddress);\\n        borrowerOperations = IBorrowerOperations(_borrowerOperationsAddress);\\n        troveManager = ITroveManager(_troveManagerAddress);\\n        activePool = IActivePool(_activePoolAddress);\\n        zusdToken = IZUSDToken(_zusdTokenAddress);\\n        sortedTroves = ISortedTroves(_sortedTrovesAddress);\\n        priceFeed = IPriceFeed(_priceFeedAddress);\\n        communityIssuance = ICommunityIssuance(_communityIssuanceAddress);\\n\\n        emit BorrowerOperationsAddressChanged(_borrowerOperationsAddress);\\n        emit TroveManagerAddressChanged(_troveManagerAddress);\\n        emit ActivePoolAddressChanged(_activePoolAddress);\\n        emit ZUSDTokenAddressChanged(_zusdTokenAddress);\\n        emit SortedTrovesAddressChanged(_sortedTrovesAddress);\\n        emit PriceFeedAddressChanged(_priceFeedAddress);\\n        emit CommunityIssuanceAddressChanged(_communityIssuanceAddress);\\n    }\\n\\n    /**\\n     * @dev setter function specific for community issuance contract.\\n     * @param _communityIssuanceAddress address of new community issuance contract.\\n     */\\n    function setCommunityIssuanceAddress(address _communityIssuanceAddress) external onlyOwner {\\n        checkContract(_communityIssuanceAddress);\\n        communityIssuance = ICommunityIssuance(_communityIssuanceAddress);\\n        emit CommunityIssuanceAddressChanged(_communityIssuanceAddress);\\n    }\\n\\n    // --- Getters for public variables. Required by IPool interface ---\\n\\n    function getETH() external view override returns (uint256) {\\n        return ETH;\\n    }\\n\\n    function getTotalZUSDDeposits() external view override returns (uint256) {\\n        return totalZUSDDeposits;\\n    }\\n\\n    // --- External Depositor Functions ---\\n\\n    /**  provideToSP():\\n     *\\n     * - Triggers a SOV issuance, based on time passed since the last issuance and total amount of deposited ZUSD. The SOV issuance is shared between *all* depositors and front ends\\n     * - Tags the deposit with the provided front end tag param, if it's a new deposit\\n     * - Sends depositor's accumulated gains (SOV, ETH) to depositor\\n     * - Sends the tagged front end's accumulated SOV gains to the tagged front end\\n     * - Increases deposit and tagged front end's stake, and takes new snapshots for each.\\n     */\\n    function provideToSP(uint256 _amount, address _frontEndTag) external override {\\n        _provideToSP(_amount, _frontEndTag);\\n    }\\n\\n    function _provideToSP(uint256 _amount, address _frontEndTag) internal {\\n        _requireFrontEndIsRegisteredOrZero(_frontEndTag);\\n        _requireFrontEndNotRegistered(msg.sender);\\n        _requireNonZeroAmount(_amount);\\n\\n        uint256 initialDeposit = deposits[msg.sender].initialValue;\\n\\n        ICommunityIssuance communityIssuanceCached = communityIssuance;\\n\\n        _triggerSOVIssuance(communityIssuanceCached);\\n\\n        if (initialDeposit == 0) {\\n            _setFrontEndTag(msg.sender, _frontEndTag);\\n        }\\n        uint256 depositorETHGain = getDepositorETHGain(msg.sender);\\n        uint256 compoundedZUSDDeposit = getCompoundedZUSDDeposit(msg.sender);\\n        uint256 ZUSDLoss = initialDeposit.sub(compoundedZUSDDeposit); // Needed only for event log\\n\\n        // First pay out any SOV gains\\n        address frontEnd = deposits[msg.sender].frontEndTag;\\n        _payOutSOVGains(communityIssuanceCached, msg.sender, frontEnd);\\n\\n        // Update front end stake\\n        uint256 compoundedFrontEndStake = getCompoundedFrontEndStake(frontEnd);\\n        uint256 newFrontEndStake = compoundedFrontEndStake.add(_amount);\\n        _updateFrontEndStakeAndSnapshots(frontEnd, newFrontEndStake);\\n        emit FrontEndStakeChanged(frontEnd, newFrontEndStake, msg.sender);\\n\\n        _sendZUSDtoStabilityPool(msg.sender, _amount);\\n\\n        uint256 newDeposit = compoundedZUSDDeposit.add(_amount);\\n        _updateDepositAndSnapshots(msg.sender, newDeposit);\\n        emit UserDepositChanged(msg.sender, newDeposit);\\n\\n        emit ETHGainWithdrawn(msg.sender, depositorETHGain, ZUSDLoss); // ZUSD Loss required for event log\\n\\n        _sendETHGainToDepositor(depositorETHGain);\\n    }\\n\\n    ///DLLR _owner or _spender can convert a specified amount of DLLR into ZUSD via Sovryn Mynt and deposit the ZUSD into the Zero Stability Pool, all in a single transaction\\n    function provideToSpFromDLLR(\\n        uint256 _dllrAmount,\\n        IMassetManager.PermitParams calldata _permitParams\\n    ) external override {\\n        uint256 _ZUSDAmount = MyntLib.redeemZusdFromDllrWithPermit(\\n            borrowerOperations.getMassetManager(),\\n            _dllrAmount,\\n            address(zusdToken),\\n            _permitParams\\n        );\\n\\n        _provideToSP(_ZUSDAmount, ADDRESS_ZERO);\\n    }\\n\\n    ///DLLR _owner or _spender can convert a specified amount of DLLR into ZUSD via Sovryn Mynt and deposit the ZUSD into the Zero Stability Pool, all in a single transaction\\n    function provideToSpFromDllrWithPermit2(\\n        uint256 _dllrAmount,\\n        ISignatureTransfer.PermitTransferFrom memory _permit,\\n        bytes calldata _signature\\n    ) external override {\\n        uint256 _ZUSDAmount = MyntLib.redeemZusdFromDllrWithPermit2(\\n            borrowerOperations.getMassetManager(),\\n            address(zusdToken),\\n            _permit,\\n            permit2,\\n            _signature\\n        );\\n\\n        _provideToSP(_ZUSDAmount, ADDRESS_ZERO);\\n    }\\n\\n    /**  withdrawFromSP():\\n     *\\n     * - Triggers a SOV issuance, based on time passed since the last issuance and total amount of ZUSD is deposited. The SOV issuance is shared between *all* depositors and front ends\\n     * - Removes the deposit's front end tag if it is a full withdrawal\\n     * - Sends all depositor's accumulated gains (SOV, ETH) to depositor\\n     * - Sends the tagged front end's accumulated SOV gains to the tagged front end\\n     * - Decreases deposit and tagged front end's stake, and takes new snapshots for each.\\n     *\\n     * If _amount > userDeposit, the user withdraws all of their compounded deposit.\\n     */\\n    function withdrawFromSP(uint256 _amount) external override {\\n        _withdrawFromSpTo(_amount, msg.sender);\\n    }\\n\\n    ///@return actual ZUSD amount withdrawn\\n    function _withdrawFromSpTo(uint256 _amount, address _receiver) internal returns (uint256) {\\n        require(_receiver != address(0), \\\"SP::_withdrawFromSpTo: _receiver is zero address\\\");\\n        if (_amount != 0) {\\n            _requireNoUnderCollateralizedTroves();\\n        }\\n        uint256 initialDeposit = deposits[msg.sender].initialValue;\\n        _requireUserHasDeposit(initialDeposit);\\n\\n        ICommunityIssuance communityIssuanceCached = communityIssuance;\\n\\n        _triggerSOVIssuance(communityIssuanceCached);\\n\\n        uint256 depositorETHGain = getDepositorETHGain(msg.sender);\\n\\n        uint256 compoundedZUSDDeposit = getCompoundedZUSDDeposit(msg.sender);\\n        uint256 ZUSDtoWithdraw = LiquityMath._min(_amount, compoundedZUSDDeposit);\\n        uint256 ZUSDLoss = initialDeposit.sub(compoundedZUSDDeposit); // Needed only for event log\\n\\n        // First pay out any SOV gains\\n        address frontEnd = deposits[msg.sender].frontEndTag;\\n        _payOutSOVGains(communityIssuanceCached, msg.sender, frontEnd);\\n\\n        // Update front end stake\\n        uint256 compoundedFrontEndStake = getCompoundedFrontEndStake(frontEnd);\\n        uint256 newFrontEndStake = compoundedFrontEndStake.sub(ZUSDtoWithdraw);\\n        _updateFrontEndStakeAndSnapshots(frontEnd, newFrontEndStake);\\n        emit FrontEndStakeChanged(frontEnd, newFrontEndStake, msg.sender);\\n\\n        _sendZUSDToDepositor(_receiver, ZUSDtoWithdraw);\\n\\n        // Update deposit\\n        uint256 newDeposit = compoundedZUSDDeposit.sub(ZUSDtoWithdraw);\\n        _updateDepositAndSnapshots(msg.sender, newDeposit);\\n        emit UserDepositChanged(msg.sender, newDeposit);\\n\\n        emit ETHGainWithdrawn(msg.sender, depositorETHGain, ZUSDLoss); // ZUSD Loss required for event log\\n\\n        _sendETHGainTo(depositorETHGain, msg.sender);\\n\\n        return ZUSDtoWithdraw;\\n    }\\n\\n    ///Stability Pool depositor can withdraw a specified amount of ZUSD from the Zero Stability Pool and convert the ZUSD to DLLR via Sovryn Mynt, all in a single transaction\\n    function withdrawFromSpAndConvertToDLLR(uint256 _zusdAmountRequested) external override {\\n        IMassetManager massetManager = borrowerOperations.getMassetManager();\\n        uint256 amountWithdrawn = _withdrawFromSpTo(_zusdAmountRequested, address(this));\\n        require(\\n            zusdToken.approve(address(massetManager), amountWithdrawn),\\n            \\\"Failed to approve ZUSD amount for Mynt mAsset to redeem\\\"\\n        );\\n        massetManager.mintTo(address(zusdToken), amountWithdrawn, msg.sender);\\n        emit WithdrawFromSpAndConvertToDLLR(msg.sender, _zusdAmountRequested, amountWithdrawn);\\n    }\\n\\n    /** withdrawETHGainToTrove:\\n     * - Triggers a SOV issuance, based on time passed since the last issuance. The SOV issuance is shared between *all* depositors and front ends\\n     * - Sends all depositor's SOV gain to  depositor\\n     * - Sends all tagged front end's SOV gain to the tagged front end\\n     * - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove\\n     * - Leaves their compounded deposit in the Stability Pool\\n     * - Updates snapshots for deposit and tagged front end stake */\\n    function withdrawETHGainToTrove(address _upperHint, address _lowerHint) external override {\\n        uint256 initialDeposit = deposits[msg.sender].initialValue;\\n        _requireUserHasDeposit(initialDeposit);\\n        _requireUserHasTrove(msg.sender);\\n        _requireUserHasETHGain(msg.sender);\\n\\n        ICommunityIssuance communityIssuanceCached = communityIssuance;\\n\\n        _triggerSOVIssuance(communityIssuanceCached);\\n\\n        uint256 depositorETHGain = getDepositorETHGain(msg.sender);\\n\\n        uint256 compoundedZUSDDeposit = getCompoundedZUSDDeposit(msg.sender);\\n        uint256 ZUSDLoss = initialDeposit.sub(compoundedZUSDDeposit); // Needed only for event log\\n\\n        // First pay out any SOV gains\\n        address frontEnd = deposits[msg.sender].frontEndTag;\\n        _payOutSOVGains(communityIssuanceCached, msg.sender, frontEnd);\\n\\n        // Update front end stake\\n        uint256 compoundedFrontEndStake = getCompoundedFrontEndStake(frontEnd);\\n        uint256 newFrontEndStake = compoundedFrontEndStake;\\n        _updateFrontEndStakeAndSnapshots(frontEnd, newFrontEndStake);\\n        emit FrontEndStakeChanged(frontEnd, newFrontEndStake, msg.sender);\\n\\n        _updateDepositAndSnapshots(msg.sender, compoundedZUSDDeposit);\\n\\n        /* Emit events before transferring ETH gain to Trove.\\n         This lets the event log make more sense (i.e. so it appears that first the ETH gain is withdrawn\\n        and then it is deposited into the Trove, not the other way around). */\\n        emit ETHGainWithdrawn(msg.sender, depositorETHGain, ZUSDLoss);\\n        emit UserDepositChanged(msg.sender, compoundedZUSDDeposit);\\n\\n        ETH = ETH.sub(depositorETHGain);\\n        emit StabilityPoolETHBalanceUpdated(ETH);\\n        emit EtherSent(msg.sender, depositorETHGain);\\n\\n        borrowerOperations.moveETHGainToTrove{ value: depositorETHGain }(\\n            msg.sender,\\n            _upperHint,\\n            _lowerHint\\n        );\\n    }\\n\\n    // --- SOV issuance functions ---\\n\\n    function _triggerSOVIssuance(ICommunityIssuance _communityIssuance) internal {\\n        uint256 SOVIssuance = _communityIssuance.issueSOV(totalZUSDDeposits);\\n        _updateG(SOVIssuance);\\n    }\\n\\n    function _updateG(uint256 _SOVIssuance) internal {\\n        uint256 totalZUSD = totalZUSDDeposits; // cached to save an SLOAD\\n        /*\\n         * When total deposits is 0, G is not updated. In this case, the SOV issued can not be obtained by later\\n         * depositors - it is missed out on, and remains in the balanceof the CommunityIssuance contract.\\n         *\\n         */\\n        if (totalZUSD == 0 || _SOVIssuance == 0) {\\n            return;\\n        }\\n\\n        uint256 SOVPerUnitStaked;\\n        SOVPerUnitStaked = _computeSOVPerUnitStaked(_SOVIssuance, totalZUSD);\\n\\n        uint256 marginalSOVGain = SOVPerUnitStaked.mul(P);\\n        epochToScaleToG[currentEpoch][currentScale] = epochToScaleToG[currentEpoch][currentScale]\\n            .add(marginalSOVGain);\\n\\n        emit G_Updated(epochToScaleToG[currentEpoch][currentScale], currentEpoch, currentScale);\\n    }\\n\\n    function _computeSOVPerUnitStaked(uint256 _SOVIssuance, uint256 _totalZUSDDeposits)\\n        internal\\n        returns (uint256)\\n    {\\n        /*\\n         * Calculate the SOV-per-unit staked.  Division uses a \\\"feedback\\\" error correction, to keep the\\n         * cumulative error low in the running total G:\\n         *\\n         * 1) Form a numerator which compensates for the floor division error that occurred the last time this\\n         * function was called.\\n         * 2) Calculate \\\"per-unit-staked\\\" ratio.\\n         * 3) Multiply the ratio back by its denominator, to reveal the current floor division error.\\n         * 4) Store this error for use in the next correction when this function is called.\\n         * 5) Note: static analysis tools complain about this \\\"division before multiplication\\\", however, it is intended.\\n         */\\n        uint256 SOVNumerator = _SOVIssuance.mul(DECIMAL_PRECISION).add(lastSOVError);\\n\\n        uint256 SOVPerUnitStaked = SOVNumerator.div(_totalZUSDDeposits);\\n        lastSOVError = SOVNumerator.sub(SOVPerUnitStaked.mul(_totalZUSDDeposits));\\n\\n        return SOVPerUnitStaked;\\n    }\\n\\n    // --- Liquidation functions ---\\n\\n    /**\\n     * Cancels out the specified debt against the ZUSD contained in the Stability Pool (as far as possible)\\n     * and transfers the Trove's ETH collateral from ActivePool to StabilityPool.\\n     * Only called by liquidation functions in the TroveManager.\\n     */\\n    function offset(uint256 _debtToOffset, uint256 _collToAdd) external override {\\n        _requireCallerIsTroveManager();\\n        uint256 totalZUSD = totalZUSDDeposits; // cached to save an SLOAD\\n        if (totalZUSD == 0 || _debtToOffset == 0) {\\n            return;\\n        }\\n\\n        _triggerSOVIssuance(communityIssuance);\\n\\n        (\\n            uint256 ETHGainPerUnitStaked,\\n            uint256 ZUSDLossPerUnitStaked\\n        ) = _computeRewardsPerUnitStaked(_collToAdd, _debtToOffset, totalZUSD);\\n\\n        _updateRewardSumAndProduct(ETHGainPerUnitStaked, ZUSDLossPerUnitStaked); // updates S and P\\n\\n        _moveOffsetCollAndDebt(_collToAdd, _debtToOffset);\\n    }\\n\\n    // --- Offset helper functions ---\\n\\n    function _computeRewardsPerUnitStaked(\\n        uint256 _collToAdd,\\n        uint256 _debtToOffset,\\n        uint256 _totalZUSDDeposits\\n    ) internal returns (uint256 ETHGainPerUnitStaked, uint256 ZUSDLossPerUnitStaked) {\\n        /*\\n         * Compute the ZUSD and ETH rewards. Uses a \\\"feedback\\\" error correction, to keep\\n         * the cumulative error in the P and S state variables low:\\n         *\\n         * 1) Form numerators which compensate for the floor division errors that occurred the last time this\\n         * function was called.\\n         * 2) Calculate \\\"per-unit-staked\\\" ratios.\\n         * 3) Multiply each ratio back by its denominator, to reveal the current floor division error.\\n         * 4) Store these errors for use in the next correction when this function is called.\\n         * 5) Note: static analysis tools complain about this \\\"division before multiplication\\\", however, it is intended.\\n         */\\n        uint256 ETHNumerator = _collToAdd.mul(DECIMAL_PRECISION).add(lastETHError_Offset);\\n\\n        assert(_debtToOffset <= _totalZUSDDeposits);\\n        if (_debtToOffset == _totalZUSDDeposits) {\\n            ZUSDLossPerUnitStaked = DECIMAL_PRECISION; // When the Pool depletes to 0, so does each deposit\\n            lastZUSDLossError_Offset = 0;\\n        } else {\\n            uint256 ZUSDLossNumerator = _debtToOffset.mul(DECIMAL_PRECISION).sub(\\n                lastZUSDLossError_Offset\\n            );\\n            /*\\n             * Add 1 to make error in quotient positive. We want \\\"slightly too much\\\" ZUSD loss,\\n             * which ensures the error in any given compoundedZUSDDeposit favors the Stability Pool.\\n             */\\n            ZUSDLossPerUnitStaked = (ZUSDLossNumerator.div(_totalZUSDDeposits)).add(1);\\n            lastZUSDLossError_Offset = (ZUSDLossPerUnitStaked.mul(_totalZUSDDeposits)).sub(\\n                ZUSDLossNumerator\\n            );\\n        }\\n\\n        ETHGainPerUnitStaked = ETHNumerator.div(_totalZUSDDeposits);\\n        lastETHError_Offset = ETHNumerator.sub(ETHGainPerUnitStaked.mul(_totalZUSDDeposits));\\n\\n        return (ETHGainPerUnitStaked, ZUSDLossPerUnitStaked);\\n    }\\n\\n    /// Update the Stability Pool reward sum S and product P\\n    function _updateRewardSumAndProduct(\\n        uint256 _ETHGainPerUnitStaked,\\n        uint256 _ZUSDLossPerUnitStaked\\n    ) internal {\\n        uint256 currentP = P;\\n        uint256 newP;\\n\\n        assert(_ZUSDLossPerUnitStaked <= DECIMAL_PRECISION);\\n        /*\\n         * The newProductFactor is the factor by which to change all deposits, due to the depletion of Stability Pool ZUSD in the liquidation.\\n         * We make the product factor 0 if there was a pool-emptying. Otherwise, it is (1 - ZUSDLossPerUnitStaked)\\n         */\\n        uint256 newProductFactor = uint256(DECIMAL_PRECISION).sub(_ZUSDLossPerUnitStaked);\\n\\n        uint128 currentScaleCached = currentScale;\\n        uint128 currentEpochCached = currentEpoch;\\n        uint256 currentS = epochToScaleToSum[currentEpochCached][currentScaleCached];\\n\\n        /*\\n         * Calculate the new S first, before we update P.\\n         * The ETH gain for any given depositor from a liquidation depends on the value of their deposit\\n         * (and the value of totalDeposits) prior to the Stability being depleted by the debt in the liquidation.\\n         *\\n         * Since S corresponds to ETH gain, and P to deposit loss, we update S first.\\n         */\\n        uint256 marginalETHGain = _ETHGainPerUnitStaked.mul(currentP);\\n        uint256 newS = currentS.add(marginalETHGain);\\n        epochToScaleToSum[currentEpochCached][currentScaleCached] = newS;\\n        emit S_Updated(newS, currentEpochCached, currentScaleCached);\\n\\n        // If the Stability Pool was emptied, increment the epoch, and reset the scale and product P\\n        if (newProductFactor == 0) {\\n            currentEpoch = currentEpochCached.add(1);\\n            emit EpochUpdated(currentEpoch);\\n            currentScale = 0;\\n            emit ScaleUpdated(currentScale);\\n            newP = DECIMAL_PRECISION;\\n\\n            // If multiplying P by a non-zero product factor would reduce P below the scale boundary, increment the scale\\n        } else if (currentP.mul(newProductFactor).div(DECIMAL_PRECISION) < SCALE_FACTOR) {\\n            newP = currentP.mul(newProductFactor).mul(SCALE_FACTOR).div(DECIMAL_PRECISION);\\n            currentScale = currentScaleCached.add(1);\\n            emit ScaleUpdated(currentScale);\\n        } else {\\n            newP = currentP.mul(newProductFactor).div(DECIMAL_PRECISION);\\n        }\\n\\n        assert(newP > 0);\\n        P = newP;\\n\\n        emit P_Updated(newP);\\n    }\\n\\n    function _moveOffsetCollAndDebt(uint256 _collToAdd, uint256 _debtToOffset) internal {\\n        IActivePool activePoolCached = activePool;\\n\\n        // Cancel the liquidated ZUSD debt with the ZUSD in the stability pool\\n        activePoolCached.decreaseZUSDDebt(_debtToOffset);\\n        _decreaseZUSD(_debtToOffset);\\n\\n        // Burn the debt that was successfully offset\\n        zusdToken.burn(address(this), _debtToOffset);\\n\\n        activePoolCached.sendETH(address(this), _collToAdd);\\n    }\\n\\n    function _decreaseZUSD(uint256 _amount) internal {\\n        uint256 newTotalZUSDDeposits = totalZUSDDeposits.sub(_amount);\\n        totalZUSDDeposits = newTotalZUSDDeposits;\\n        emit StabilityPoolZUSDBalanceUpdated(newTotalZUSDDeposits);\\n    }\\n\\n    // --- Reward calculator functions for depositor and front end ---\\n\\n    /** Calculates the ETH gain earned by the deposit since its last snapshots were taken.\\n     * Given by the formula:  E = d0 * (S - S(0))/P(0)\\n     * where S(0) and P(0) are the depositor's snapshots of the sum S and product P, respectively.\\n     * d0 is the last recorded deposit value.\\n     */\\n    function getDepositorETHGain(address _depositor) public view override returns (uint256) {\\n        uint256 initialDeposit = deposits[_depositor].initialValue;\\n\\n        if (initialDeposit == 0) {\\n            return 0;\\n        }\\n\\n        Snapshots memory snapshots = depositSnapshots[_depositor];\\n\\n        uint256 ETHGain = _getETHGainFromSnapshots(initialDeposit, snapshots);\\n        return ETHGain;\\n    }\\n\\n    function _getETHGainFromSnapshots(uint256 initialDeposit, Snapshots memory snapshots)\\n        internal\\n        view\\n        returns (uint256)\\n    {\\n        /*\\n         * Grab the sum 'S' from the epoch at which the stake was made. The ETH gain may span up to one scale change.\\n         * If it does, the second portion of the ETH gain is scaled by 1e9.\\n         * If the gain spans no scale change, the second portion will be 0.\\n         */\\n        uint128 epochSnapshot = snapshots.epoch;\\n        uint128 scaleSnapshot = snapshots.scale;\\n        uint256 S_Snapshot = snapshots.S;\\n        uint256 P_Snapshot = snapshots.P;\\n\\n        uint256 firstPortion = epochToScaleToSum[epochSnapshot][scaleSnapshot].sub(S_Snapshot);\\n        uint256 secondPortion = epochToScaleToSum[epochSnapshot][scaleSnapshot.add(1)].div(\\n            SCALE_FACTOR\\n        );\\n\\n        uint256 ETHGain = initialDeposit.mul(firstPortion.add(secondPortion)).div(P_Snapshot).div(\\n            DECIMAL_PRECISION\\n        );\\n\\n        return ETHGain;\\n    }\\n\\n    /**\\n     * Calculate the SOV gain earned by a deposit since its last snapshots were taken.\\n     * Given by the formula:  SOV = d0 * (G - G(0))/P(0)\\n     * where G(0) and P(0) are the depositor's snapshots of the sum G and product P, respectively.\\n     * d0 is the last recorded deposit value.\\n     */\\n    function getDepositorSOVGain(address _depositor) public view override returns (uint256) {\\n        uint256 initialDeposit = deposits[_depositor].initialValue;\\n        if (initialDeposit == 0) {\\n            return 0;\\n        }\\n\\n        address frontEndTag = deposits[_depositor].frontEndTag;\\n\\n        /*\\n         * If not tagged with a front end, the depositor gets a 100% cut of what their deposit earned.\\n         * Otherwise, their cut of the deposit's earnings is equal to the kickbackRate, set by the front end through\\n         * which they made their deposit.\\n         */\\n        uint256 kickbackRate = frontEndTag == ADDRESS_ZERO\\n            ? DECIMAL_PRECISION\\n            : frontEnds[frontEndTag].kickbackRate;\\n\\n        Snapshots memory snapshots = depositSnapshots[_depositor];\\n\\n        uint256 SOVGain = kickbackRate\\n            .mul(_getSOVGainFromSnapshots(initialDeposit, snapshots))\\n            .div(DECIMAL_PRECISION);\\n\\n        return SOVGain;\\n    }\\n\\n    /**\\n     * Return the SOV gain earned by the front end. Given by the formula:  E = D0 * (G - G(0))/P(0)\\n     * where G(0) and P(0) are the depositor's snapshots of the sum G and product P, respectively.\\n     *\\n     * D0 is the last recorded value of the front end's total tagged deposits.\\n     */\\n    function getFrontEndSOVGain(address _frontEnd) public view override returns (uint256) {\\n        uint256 frontEndStake = frontEndStakes[_frontEnd];\\n        if (frontEndStake == 0) {\\n            return 0;\\n        }\\n\\n        uint256 kickbackRate = frontEnds[_frontEnd].kickbackRate;\\n        uint256 frontEndShare = uint256(DECIMAL_PRECISION).sub(kickbackRate);\\n\\n        Snapshots memory snapshots = frontEndSnapshots[_frontEnd];\\n\\n        uint256 SOVGain = frontEndShare\\n            .mul(_getSOVGainFromSnapshots(frontEndStake, snapshots))\\n            .div(DECIMAL_PRECISION);\\n        return SOVGain;\\n    }\\n\\n    function _getSOVGainFromSnapshots(uint256 initialStake, Snapshots memory snapshots)\\n        internal\\n        view\\n        returns (uint256)\\n    {\\n        /*\\n         * Grab the sum 'G' from the epoch at which the stake was made. The SOV gain may span up to one scale change.\\n         * If it does, the second portion of the SOV gain is scaled by 1e9.\\n         * If the gain spans no scale change, the second portion will be 0.\\n         */\\n        uint128 epochSnapshot = snapshots.epoch;\\n        uint128 scaleSnapshot = snapshots.scale;\\n        uint256 G_Snapshot = snapshots.G;\\n        uint256 P_Snapshot = snapshots.P;\\n\\n        uint256 firstPortion = epochToScaleToG[epochSnapshot][scaleSnapshot].sub(G_Snapshot);\\n        uint256 secondPortion = epochToScaleToG[epochSnapshot][scaleSnapshot.add(1)].div(\\n            SCALE_FACTOR\\n        );\\n\\n        uint256 SOVGain = initialStake.mul(firstPortion.add(secondPortion)).div(P_Snapshot).div(\\n            DECIMAL_PRECISION\\n        );\\n\\n        return SOVGain;\\n    }\\n\\n    // --- Compounded deposit and compounded front end stake ---\\n\\n    /**\\n     * Return the user's compounded deposit. Given by the formula:  d = d0 * P/P(0)\\n     * where P(0) is the depositor's snapshot of the product P, taken when they last updated their deposit.\\n     */\\n    function getCompoundedZUSDDeposit(address _depositor) public view override returns (uint256) {\\n        uint256 initialDeposit = deposits[_depositor].initialValue;\\n        if (initialDeposit == 0) {\\n            return 0;\\n        }\\n\\n        Snapshots memory snapshots = depositSnapshots[_depositor];\\n\\n        uint256 compoundedDeposit = _getCompoundedStakeFromSnapshots(initialDeposit, snapshots);\\n        return compoundedDeposit;\\n    }\\n\\n    /**\\n     * Return the front end's compounded stake. Given by the formula:  D = D0 * P/P(0)\\n     * where P(0) is the depositor's snapshot of the product P, taken at the last time\\n     * when one of the front end's tagged deposits updated their deposit.\\n     *\\n     * The front end's compounded stake is equal to the sum of its depositors' compounded deposits.\\n     */\\n    function getCompoundedFrontEndStake(address _frontEnd) public view override returns (uint256) {\\n        uint256 frontEndStake = frontEndStakes[_frontEnd];\\n        if (frontEndStake == 0) {\\n            return 0;\\n        }\\n\\n        Snapshots memory snapshots = frontEndSnapshots[_frontEnd];\\n\\n        uint256 compoundedFrontEndStake = _getCompoundedStakeFromSnapshots(\\n            frontEndStake,\\n            snapshots\\n        );\\n        return compoundedFrontEndStake;\\n    }\\n\\n    // Internal function, used to calculcate compounded deposits and compounded front end stakes.\\n    function _getCompoundedStakeFromSnapshots(uint256 initialStake, Snapshots memory snapshots)\\n        internal\\n        view\\n        returns (uint256)\\n    {\\n        uint256 snapshot_P = snapshots.P;\\n        uint128 scaleSnapshot = snapshots.scale;\\n        uint128 epochSnapshot = snapshots.epoch;\\n\\n        // If stake was made before a pool-emptying event, then it has been fully cancelled with debt -- so, return 0\\n        if (epochSnapshot < currentEpoch) {\\n            return 0;\\n        }\\n\\n        uint256 compoundedStake;\\n        uint128 scaleDiff = currentScale.sub(scaleSnapshot);\\n\\n        /* Compute the compounded stake. If a scale change in P was made during the stake's lifetime,\\n         * account for it. If more than one scale change was made, then the stake has decreased by a factor of\\n         * at least 1e-9 -- so return 0.\\n         */\\n        if (scaleDiff == 0) {\\n            compoundedStake = initialStake.mul(P).div(snapshot_P);\\n        } else if (scaleDiff == 1) {\\n            compoundedStake = initialStake.mul(P).div(snapshot_P).div(SCALE_FACTOR);\\n        } else {\\n            // if scaleDiff >= 2\\n            compoundedStake = 0;\\n        }\\n\\n        /*\\n         * If compounded deposit is less than a billionth of the initial deposit, return 0.\\n         *\\n         * NOTE: originally, this line was in place to stop rounding errors making the deposit too large. However, the error\\n         * corrections should ensure the error in P \\\"favors the Pool\\\", i.e. any given compounded deposit should slightly less\\n         * than it's theoretical value.\\n         *\\n         * Thus it's unclear whether this line is still really needed.\\n         */\\n        if (compoundedStake < initialStake.div(1e9)) {\\n            return 0;\\n        }\\n\\n        return compoundedStake;\\n    }\\n\\n    // --- Sender functions for ZUSD deposit, ETH gains and SOV gains ---\\n\\n    /// Transfer the ZUSD tokens from the user to the Stability Pool's address, and update its recorded ZUSD\\n    function _sendZUSDtoStabilityPool(address _address, uint256 _amount) internal {\\n        zusdToken.sendToPool(_address, address(this), _amount);\\n        uint256 newTotalZUSDDeposits = totalZUSDDeposits.add(_amount);\\n        totalZUSDDeposits = newTotalZUSDDeposits;\\n        emit StabilityPoolZUSDBalanceUpdated(newTotalZUSDDeposits);\\n    }\\n\\n    function _sendETHGainToDepositor(uint256 _amount) internal {\\n        _sendETHGainTo(_amount, msg.sender);\\n    }\\n\\n    function _sendETHGainTo(uint256 _amount, address _receiver) internal {\\n        require(_receiver != address(0), \\\"SP::_sendETHGainTo: _receiver is zero address\\\");\\n        if (_amount == 0) {\\n            return;\\n        }\\n        uint256 newETH = ETH.sub(_amount);\\n        ETH = newETH;\\n        emit StabilityPoolETHBalanceUpdated(newETH);\\n        emit EtherSent(msg.sender, _amount);\\n\\n        (bool success, ) = msg.sender.call{ value: _amount }(\\\"\\\");\\n        require(success, \\\"StabilityPool: sending ETH failed\\\");\\n    }\\n\\n    /// Send ZUSD to user and decrease ZUSD in Pool\\n    function _sendZUSDToDepositor(address _depositor, uint256 ZUSDWithdrawal) internal {\\n        if (ZUSDWithdrawal == 0) {\\n            return;\\n        }\\n\\n        zusdToken.returnFromPool(address(this), _depositor, ZUSDWithdrawal);\\n        _decreaseZUSD(ZUSDWithdrawal);\\n    }\\n\\n    // --- External Front End functions ---\\n\\n    /// Front end makes a one-time selection of kickback rate upon registering\\n    function registerFrontEnd(uint256 _kickbackRate) external override {\\n        _requireFrontEndNotRegistered(msg.sender);\\n        _requireUserHasNoDeposit(msg.sender);\\n        _requireValidKickbackRate(_kickbackRate);\\n\\n        frontEnds[msg.sender].kickbackRate = _kickbackRate;\\n        frontEnds[msg.sender].registered = true;\\n\\n        emit FrontEndRegistered(msg.sender, _kickbackRate);\\n    }\\n\\n    // --- Stability Pool Deposit Functionality ---\\n\\n    function _setFrontEndTag(address _depositor, address _frontEndTag) internal {\\n        deposits[_depositor].frontEndTag = _frontEndTag;\\n        emit FrontEndTagSet(_depositor, _frontEndTag);\\n    }\\n\\n    function _updateDepositAndSnapshots(address _depositor, uint256 _newValue) internal {\\n        deposits[_depositor].initialValue = _newValue;\\n\\n        if (_newValue == 0) {\\n            delete deposits[_depositor].frontEndTag;\\n            delete depositSnapshots[_depositor];\\n            emit DepositSnapshotUpdated(_depositor, 0, 0, 0);\\n            return;\\n        }\\n        uint128 currentScaleCached = currentScale;\\n        uint128 currentEpochCached = currentEpoch;\\n        uint256 currentP = P;\\n\\n        // Get S and G for the current epoch and current scale\\n        uint256 currentS = epochToScaleToSum[currentEpochCached][currentScaleCached];\\n        uint256 currentG = epochToScaleToG[currentEpochCached][currentScaleCached];\\n\\n        // Record new snapshots of the latest running product P, sum S, and sum G, for the depositor\\n        depositSnapshots[_depositor].P = currentP;\\n        depositSnapshots[_depositor].S = currentS;\\n        depositSnapshots[_depositor].G = currentG;\\n        depositSnapshots[_depositor].scale = currentScaleCached;\\n        depositSnapshots[_depositor].epoch = currentEpochCached;\\n\\n        emit DepositSnapshotUpdated(_depositor, currentP, currentS, currentG);\\n    }\\n\\n    function _updateFrontEndStakeAndSnapshots(address _frontEnd, uint256 _newValue) internal {\\n        frontEndStakes[_frontEnd] = _newValue;\\n\\n        if (_newValue == 0) {\\n            delete frontEndSnapshots[_frontEnd];\\n            emit FrontEndSnapshotUpdated(_frontEnd, 0, 0);\\n            return;\\n        }\\n\\n        uint128 currentScaleCached = currentScale;\\n        uint128 currentEpochCached = currentEpoch;\\n        uint256 currentP = P;\\n\\n        // Get G for the current epoch and current scale\\n        uint256 currentG = epochToScaleToG[currentEpochCached][currentScaleCached];\\n\\n        // Record new snapshots of the latest running product P and sum G for the front end\\n        frontEndSnapshots[_frontEnd].P = currentP;\\n        frontEndSnapshots[_frontEnd].G = currentG;\\n        frontEndSnapshots[_frontEnd].scale = currentScaleCached;\\n        frontEndSnapshots[_frontEnd].epoch = currentEpochCached;\\n\\n        emit FrontEndSnapshotUpdated(_frontEnd, currentP, currentG);\\n    }\\n\\n    function _payOutSOVGains(\\n        ICommunityIssuance _communityIssuance,\\n        address _depositor,\\n        address _frontEnd\\n    ) internal {\\n        // Pay out front end's SOV gain\\n        if (_frontEnd != ADDRESS_ZERO) {\\n            uint256 frontEndSOVGain = getFrontEndSOVGain(_frontEnd);\\n            _communityIssuance.sendSOV(_frontEnd, frontEndSOVGain);\\n            emit SOVPaidToFrontEnd(_frontEnd, frontEndSOVGain);\\n        }\\n\\n        // Pay out depositor's SOV gain\\n        uint256 depositorSOVGain = getDepositorSOVGain(_depositor);\\n        _communityIssuance.sendSOV(_depositor, depositorSOVGain);\\n        emit SOVPaidToDepositor(_depositor, depositorSOVGain);\\n    }\\n\\n    // --- 'require' functions ---\\n\\n    function _requireCallerIsActivePool() internal view {\\n        require(msg.sender == address(activePool), \\\"StabilityPool: Caller is not ActivePool\\\");\\n    }\\n\\n    function _requireCallerIsTroveManager() internal view {\\n        require(msg.sender == address(troveManager), \\\"StabilityPool: Caller is not TroveManager\\\");\\n    }\\n\\n    function _requireNoUnderCollateralizedTroves() internal {\\n        uint256 price = priceFeed.fetchPrice();\\n        address lowestTrove = sortedTroves.getLast();\\n        uint256 ICR = troveManager.getCurrentICR(lowestTrove, price);\\n        require(\\n            ICR >= liquityBaseParams.MCR(),\\n            \\\"StabilityPool: Cannot withdraw while there are troves with ICR < MCR\\\"\\n        );\\n    }\\n\\n    function _requireUserHasDeposit(uint256 _initialDeposit) internal pure {\\n        require(_initialDeposit > 0, \\\"StabilityPool: User must have a non-zero deposit\\\");\\n    }\\n\\n    function _requireUserHasNoDeposit(address _address) internal view {\\n        uint256 initialDeposit = deposits[_address].initialValue;\\n        require(initialDeposit == 0, \\\"StabilityPool: User must have no deposit\\\");\\n    }\\n\\n    function _requireNonZeroAmount(uint256 _amount) internal pure {\\n        require(_amount > 0, \\\"StabilityPool: Amount must be non-zero\\\");\\n    }\\n\\n    function _requireUserHasTrove(address _depositor) internal view {\\n        require(\\n            troveManager.getTroveStatus(_depositor) == 1,\\n            \\\"StabilityPool: caller must have an active trove to withdraw ETHGain to\\\"\\n        );\\n    }\\n\\n    function _requireUserHasETHGain(address _depositor) internal view {\\n        uint256 ETHGain = getDepositorETHGain(_depositor);\\n        require(ETHGain > 0, \\\"StabilityPool: caller must have non-zero ETH Gain\\\");\\n    }\\n\\n    function _requireFrontEndNotRegistered(address _address) internal view {\\n        require(\\n            !frontEnds[_address].registered,\\n            \\\"StabilityPool: must not already be a registered front end\\\"\\n        );\\n    }\\n\\n    function _requireFrontEndIsRegisteredOrZero(address _address) internal view {\\n        require(\\n            frontEnds[_address].registered || _address == ADDRESS_ZERO,\\n            \\\"StabilityPool: Tag must be a registered front end, or the zero address\\\"\\n        );\\n    }\\n\\n    function _requireValidKickbackRate(uint256 _kickbackRate) internal pure {\\n        require(\\n            _kickbackRate <= DECIMAL_PRECISION,\\n            \\\"StabilityPool: Kickback rate must be in range [0,1]\\\"\\n        );\\n    }\\n\\n    // --- Fallback function ---\\n\\n    receive() external payable {\\n        _requireCallerIsActivePool();\\n        ETH = ETH.add(msg.value);\\n        StabilityPoolETHBalanceUpdated(ETH);\\n    }\\n}\\n\",\"keccak256\":\"0xba9a1f4ef8bf737262b6aa77fac2247ea1ae68d51267496c46ad817bfc9f7acd\",\"license\":\"MIT\"},\"contracts/StabilityPoolStorage.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.6.11;\\n\\nimport \\\"./Interfaces/IBorrowerOperations.sol\\\";\\nimport \\\"./Interfaces/IStabilityPool.sol\\\";\\nimport \\\"./Interfaces/IBorrowerOperations.sol\\\";\\nimport \\\"./Interfaces/ITroveManager.sol\\\";\\nimport \\\"./Interfaces/IZUSDToken.sol\\\";\\nimport \\\"./Interfaces/ISortedTroves.sol\\\";\\nimport \\\"./Interfaces/ICommunityIssuance.sol\\\";\\nimport \\\"./Dependencies/Ownable.sol\\\";\\nimport \\\"./Dependencies/BaseMath.sol\\\";\\n\\ncontract StabilityPoolStorage is Ownable, BaseMath {\\n    string public constant NAME = \\\"StabilityPool\\\";\\n\\n    IBorrowerOperations public borrowerOperations;\\n\\n    ITroveManager public troveManager;\\n\\n    IZUSDToken public zusdToken;\\n\\n    // Needed to check if there are pending liquidations\\n    ISortedTroves public sortedTroves;\\n\\n    ICommunityIssuance public communityIssuance;\\n\\n    uint256 internal ETH; // deposited ether tracker\\n\\n    // Tracker for ZUSD held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset.\\n    uint256 internal totalZUSDDeposits;\\n\\n    // --- Data structures ---\\n\\n    struct FrontEnd {\\n        uint256 kickbackRate;\\n        bool registered;\\n    }\\n\\n    struct Deposit {\\n        uint256 initialValue;\\n        address frontEndTag;\\n    }\\n\\n    struct Snapshots {\\n        uint256 S;\\n        uint256 P;\\n        uint256 G;\\n        uint128 scale;\\n        uint128 epoch;\\n    }\\n\\n    mapping(address => Deposit) public deposits; // depositor address -> Deposit struct\\n    mapping(address => Snapshots) public depositSnapshots; // depositor address -> snapshots struct\\n\\n    mapping(address => FrontEnd) public frontEnds; // front end address -> FrontEnd struct\\n    mapping(address => uint256) public frontEndStakes; // front end address -> last recorded total deposits, tagged with that front end\\n    mapping(address => Snapshots) public frontEndSnapshots; // front end address -> snapshots struct\\n\\n    /*  Product 'P': Running product by which to multiply an initial deposit, in order to find the current compounded deposit,\\n     * after a series of liquidations have occurred, each of which cancel some ZUSD debt with the deposit.\\n     *\\n     * During its lifetime, a deposit's value evolves from d_t to d_t * P / P_t , where P_t\\n     * is the snapshot of P taken at the instant the deposit was made. 18-digit decimal.\\n     */\\n    uint256 public P;\\n\\n    uint256 public constant SCALE_FACTOR = 1e9;\\n\\n    // Each time the scale of P shifts by SCALE_FACTOR, the scale is incremented by 1\\n    uint128 public currentScale;\\n\\n    // With each offset that fully empties the Pool, the epoch is incremented by 1\\n    uint128 public currentEpoch;\\n\\n    /* ETH Gain sum 'S': During its lifetime, each deposit d_t earns an ETH gain of ( d_t * [S - S_t] )/P_t, where S_t\\n     * is the depositor's snapshot of S taken at the time t when the deposit was made.\\n     *\\n     * The 'S' sums are stored in a nested mapping (epoch => scale => sum):\\n     *\\n     * - The inner mapping records the sum S at different scales\\n     * - The outer mapping records the (scale => sum) mappings, for different epochs.\\n     */\\n    mapping(uint128 => mapping(uint128 => uint256)) public epochToScaleToSum;\\n\\n    /*\\n     * Similarly, the sum 'G' is used to calculate SOV gains. During it's lifetime, each deposit d_t earns a SOV gain of\\n     *  ( d_t * [G - G_t] )/P_t, where G_t is the depositor's snapshot of G taken at time t when  the deposit was made.\\n     *\\n     *  SOV reward events occur are triggered by depositor operations (new deposit, topup, withdrawal), and liquidations.\\n     *  In each case, the SOV reward is issued (i.e. G is updated), before other state changes are made.\\n     */\\n    mapping(uint128 => mapping(uint128 => uint256)) public epochToScaleToG;\\n\\n    // Error tracker for the error correction in the SOV issuance calculation\\n    uint256 public lastSOVError;\\n    // Error trackers for the error correction in the offset calculation\\n    uint256 public lastETHError_Offset;\\n    uint256 public lastZUSDLossError_Offset;\\n}\\n\",\"keccak256\":\"0x046ee6c1e461c41f97120bec0380f90c35dfc6042ff10249ab3ed75f2217b7d0\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x60a06040523480156200001157600080fd5b5060405162004b8c38038062004b8c833981016040819052620000349162000123565b62000048336001600160e01b036200005e16565b60601b6001600160601b031916608052620001b2565b6001600160a01b038116620000905760405162461bcd60e51b8152600401620000879062000170565b60405180910390fd5b6001600160a01b038116620000ad6001600160e01b036200010216565b6001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000604051620000f29062000153565b6040519081900390209190915550565b600080604051620001139062000153565b6040519081900390205492915050565b60006020828403121562000135578081fd5b81516001600160a01b03811681146200014c578182fd5b9392505050565b7035b2bc9737bbb730b136329737bbb732b960791b815260110190565b60208082526022908201527f4f776e61626c653a3a7365744f776e65723a20696e76616c6964206164647265604082015261737360f01b606082015260800190565b60805160601c6149b7620001d560003980610ad0528061189a52506149b76000f3fe6080604052600436106102ad5760003560e01c806382e0a57411610165578063b31ee965116100cc578063de13da3c11610085578063de13da3c14610788578063df9cd84f146107a8578063e49d3667146107c8578063ec9f7d46146107e8578063fc7e286d146107fd578063fce6b7341461082b578063fda0101a1461084b576102f8565b8063b31ee965146106f4578063bdaf37ea14610709578063c3a34a0e1461071e578063ce4b5bbe1461073e578063d733cfd014610753578063d7fb044314610773576102f8565b80639f0706701161011e5780639f07067014610665578063a20baee614610531578063a3f4df7e1461067a578063a4e59ac81461069c578063a7bfff97146106b1578063ae918754146106df576102f8565b806382e0a574146105d157806386da0824146105f1578063887105d314610611578063893d20e8146106265780638b8fbd921461063b57806395fb16bb14610650576102f8565b80633d83908a1161021457806372fe25aa116101cd57806372fe25aa14610531578063741bef1a14610546578063759b30341461055b578063766718081461057057806377553ad414610592578063795d26c3146105a75780637f7dde4a146105bc576102f8565b80633d83908a1461048757806340ed1afd1461049c578063556be101146104bc5780635d2de642146104dc5780635f788d65146104fc57806370f1b5721461051c576102f8565b80632199b66f116102665780632199b66f146103d257806328a0a04d146103f25780632e54bf9514610412578063335525ad14610432578063389e92a5146104525780633cc7422514610472576102f8565b80630fbfe38b146102fd57806312261ee71461031f57806313af40351461034a57806314f6c3be1461036a57806316b9d3c51461038c5780631bf43555146103bd576102f8565b366102f8576102ba61086b565b6009546102cd903463ffffffff6108a016565b6009819055604051600080516020614902833981519152916102ee91614847565b60405180910390a1005b600080fd5b34801561030957600080fd5b5061031d610318366004613d86565b6108ce565b005b34801561032b57600080fd5b50610334610ace565b6040516103419190613f43565b60405180910390f35b34801561035657600080fd5b5061031d610365366004613c1a565b610af2565b34801561037657600080fd5b5061037f610b36565b6040516103419190614847565b34801561039857600080fd5b506103ac6103a7366004613c1a565b610b3c565b604051610341959493929190614896565b3480156103c957600080fd5b5061037f610b77565b3480156103de57600080fd5b5061031d6103ed366004613c1a565b610b84565b3480156103fe57600080fd5b5061037f61040d366004613d52565b610c1b565b34801561041e57600080fd5b5061031d61042d366004613d86565b610c38565b34801561043e57600080fd5b5061031d61044d366004613ec9565b610c46565b34801561045e57600080fd5b5061037f61046d366004613c1a565b610ca9565b34801561047e57600080fd5b50610334610d51565b34801561049357600080fd5b50610334610d60565b3480156104a857600080fd5b5061037f6104b7366004613c1a565b610d6f565b3480156104c857600080fd5b5061031d6104d7366004613d86565b610e0c565b3480156104e857600080fd5b5061037f6104f7366004613c1a565b610e84565b34801561050857600080fd5b5061031d610517366004613db6565b610e96565b34801561052857600080fd5b5061037f610ea0565b34801561053d57600080fd5b5061037f610ea6565b34801561055257600080fd5b50610334610eb2565b34801561056757600080fd5b5061037f610ec1565b34801561057c57600080fd5b50610585610ece565b6040516103419190614833565b34801561059e57600080fd5b50610334610ee4565b3480156105b357600080fd5b5061037f610ef3565b3480156105c857600080fd5b50610334611012565b3480156105dd57600080fd5b5061037f6105ec366004613d52565b611021565b3480156105fd57600080fd5b506103ac61060c366004613c1a565b61103e565b34801561061d57600080fd5b5061037f611079565b34801561063257600080fd5b50610334611148565b34801561064757600080fd5b5061037f611167565b34801561065c57600080fd5b5061033461116d565b34801561067157600080fd5b5061033461117c565b34801561068657600080fd5b5061068f61118b565b6040516103419190614060565b3480156106a857600080fd5b506105856111b4565b3480156106bd57600080fd5b506106d16106cc366004613c1a565b6111c3565b604051610341929190614867565b3480156106eb57600080fd5b506103346111df565b34801561070057600080fd5b5061037f6111ee565b34801561071557600080fd5b5061037f6111f4565b34801561072a57600080fd5b5061031d610739366004613dda565b6111fa565b34801561074a57600080fd5b5061037f61129e565b34801561075f57600080fd5b5061031d61076e366004613c8a565b6112a6565b34801561077f57600080fd5b5061037f611538565b34801561079457600080fd5b5061037f6107a3366004613c1a565b61153e565b3480156107b457600080fd5b5061037f6107c3366004613c1a565b611642565b3480156107d457600080fd5b5061037f6107e3366004613c1a565b6116df565b3480156107f457600080fd5b506103346117dc565b34801561080957600080fd5b5061081d610818366004613c1a565b6117eb565b604051610341929190614850565b34801561083757600080fd5b5061031d610846366004613e10565b61180d565b34801561085757600080fd5b5061031d610866366004613c52565b6118cd565b6000546001600160a01b0316331461089e5760405162461bcd60e51b815260040161089590614258565b60405180910390fd5b565b6000828201838110156108c55760405162461bcd60e51b815260040161089590614168565b90505b92915050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663e9fc34616040518163ffffffff1660e01b815260040160206040518083038186803b15801561091e57600080fd5b505afa158015610932573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109569190613c36565b905060006109648330611b13565b60065460405163095ea7b360e01b81529192506001600160a01b03169063095ea7b3906109979085908590600401613fdf565b602060405180830381600087803b1580156109b157600080fd5b505af11580156109c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e99190613d32565b610a055760405162461bcd60e51b8152600401610895906145ef565b60065460405163438b1b4b60e01b81526001600160a01b038481169263438b1b4b92610a3b929091169085903390600401614019565b602060405180830381600087803b158015610a5557600080fd5b505af1158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190613d9e565b507f2b0fbec1c4e7e30517f196a714775ffe72770d2348f5d586854bb3c0fdf41df8338483604051610ac193929190613ff8565b60405180910390a1505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610afa611148565b6001600160a01b0316336001600160a01b031614610b2a5760405162461bcd60e51b81526004016108959061451d565b610b3381611cde565b50565b60095490565b600f602052600090815260409020805460018201546002830154600390930154919290916001600160801b0380821691600160801b90041685565b6809c2007651b250000081565b610b8c611148565b6001600160a01b0316336001600160a01b031614610bbc5760405162461bcd60e51b81526004016108959061451d565b610bc581611d69565b600880546001600160a01b0319166001600160a01b0383161790556040517f3055265812fb8447b9ada4a5d804ec43bd528ec40e89c952bbc7b85dc5ac681190610c10908390613f43565b60405180910390a150565b601260209081526000928352604080842090915290825290205481565b610c428133611b13565b5050565b610c4e611dae565b600a54801580610c5c575082155b15610c675750610c42565b600854610c7c906001600160a01b0316611dd8565b600080610c8a848685611e65565b91509150610c988282611f5e565b610ca2848661225f565b5050505050565b6001600160a01b0381166000908152600b602052604081205480610cd1576000915050610d4c565b610cd9613b64565b506001600160a01b0383166000908152600c60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290610d468383612395565b93505050505b919050565b6001546001600160a01b031681565b6005546001600160a01b031681565b6001600160a01b0381166000908152600b602052604081205480610d97576000915050610d4c565b610d9f613b64565b506001600160a01b0383166000908152600c60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290610d468383612486565b610e1533612582565b610e1e336125be565b610e27816125f5565b336000818152600d6020526040908190208381556001908101805460ff19169091179055517f19bc932fb9e16a8b5a1e41be9f4c2de59d5ddd7567b8b81405f532ca00a9880e90610e79908490614847565b60405180910390a250565b600e6020526000908152604090205481565b610c42828261261d565b60145481565b670de0b6b3a764000081565b6002546001600160a01b031681565b6801158e460913d0000081565b601154600160801b90046001600160801b031681565b6004546001600160a01b031681565b60008054604080516272c7d360e71b8152905183926001600160a01b031691633963e980916004808301926020929190829003018186803b158015610f3757600080fd5b505afa158015610f4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6f9190613d9e565b90506000600160009054906101000a90046001600160a01b03166001600160a01b0316633963e9806040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc157600080fd5b505afa158015610fd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff99190613d9e565b905061100b828263ffffffff6108a016565b9250505090565b6000546001600160a01b031681565b601360209081526000928352604080842090915290825290205481565b600c602052600090815260409020805460018201546002830154600390930154919290916001600160801b0380821691600160801b90041685565b6000805460408051630a7b61df60e11b8152905183926001600160a01b0316916314f6c3be916004808301926020929190829003018186803b1580156110be57600080fd5b505afa1580156110d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f69190613d9e565b90506000600160009054906101000a90046001600160a01b03166001600160a01b03166314f6c3be6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc157600080fd5b60008060405161115790613f26565b6040519081900390205492915050565b60105481565b6008546001600160a01b031681565b6003546001600160a01b031681565b6040518060400160405280600d81526020016c14dd18589a5b1a5d1e541bdbdb609a1b81525081565b6011546001600160801b031681565b600d602052600090815260409020805460019091015460ff1682565b6007546001600160a01b031681565b60165481565b600a5490565b600480546040805163e9fc346160e01b8152905160009361128c936001600160a01b03169263e9fc34619281830192602092829003018186803b15801561124057600080fd5b505afa158015611254573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112789190613c36565b60065485906001600160a01b0316856127c0565b905061129981600061261d565b505050565b633b9aca0081565b6112ae611148565b6001600160a01b0316336001600160a01b0316146112de5760405162461bcd60e51b81526004016108959061451d565b6112e788611d69565b6112f087611d69565b6112f986611d69565b61130285611d69565b61130b84611d69565b61131483611d69565b61131d82611d69565b61132681611d69565b670de0b6b3a7640000601055600380546001600160a01b03199081166001600160a01b038b8116919091179092556004805482168a8416179055600580548216898416179055600080548216888416179055600680548216878416179055600780548216868416179055600280548216858416179055600880549091169183169190911790556040517f3ca631ffcd2a9b5d9ae18543fc82f58eb4ca33af9e6ab01b7a8e95331e6ed985906113dc908990613f43565b60405180910390a17f143219c9e69b09e07e095fcc889b43d8f46ca892bba65f08dc3a0050869a5678866040516114139190613f43565b60405180910390a17f78f058b189175430c48dc02699e3a0031ea4ff781536dc2fab847de4babdd8828560405161144a9190613f43565b60405180910390a17fcdf33850c44a1a874b5fefb51dae615ac6afebd581ef90d571f81b06541d8e9d846040516114819190613f43565b60405180910390a17f65f4cf077bc01e4742eb5ad98326f6e95b63548ea24b17f8d5e823111fe78800836040516114b89190613f43565b60405180910390a17f8c537274438aa850a330284665d81a85dd38267d09e4050d416bfc94142db264826040516114ef9190613f43565b60405180910390a17f3055265812fb8447b9ada4a5d804ec43bd528ec40e89c952bbc7b85dc5ac6811816040516115269190613f43565b60405180910390a15050505050505050565b60155481565b6001600160a01b0381166000908152600e602052604081205480611566576000915050610d4c565b6001600160a01b0383166000908152600d602052604081205490611598670de0b6b3a76400008363ffffffff612a6516565b90506115a2613b64565b506001600160a01b0385166000908152600f60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290611637670de0b6b3a764000061162b61161e8886612aa7565b869063ffffffff612b3316565b9063ffffffff612b6d16565b979650505050505050565b6001600160a01b0381166000908152600e60205260408120548061166a576000915050610d4c565b611672613b64565b506001600160a01b0383166000908152600f60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290610d468383612486565b6001600160a01b0381166000908152600b602052604081205480611707576000915050610d4c565b6001600160a01b038084166000908152600b602052604081206001015490911690811561174c576001600160a01b0382166000908152600d6020526040902054611756565b670de0b6b3a76400005b9050611760613b64565b506001600160a01b0385166000908152600c60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290611637670de0b6b3a764000061162b61161e8886612aa7565b6006546001600160a01b031681565b600b60205260009081526040902080546001909101546001600160a01b031682565b600480546040805163e9fc346160e01b815290516000936118c0936001600160a01b03169263e9fc34619281830192602092829003018186803b15801561185357600080fd5b505afa158015611867573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188b9190613c36565b6006546001600160a01b0316867f00000000000000000000000000000000000000000000000000000000000000008787612baf565b9050610ca281600061261d565b336000908152600b60205260409020546118e681612dfc565b6118ef33612e1c565b6118f833612ebb565b6008546001600160a01b031661190d81611dd8565b600061191833610ca9565b9050600061192533610d6f565b90506000611939858363ffffffff612a6516565b336000818152600b60205260409020600101549192506001600160a01b039091169061196790869083612ee8565b600061197282611642565b90508061197f838261305d565b826001600160a01b031660008051602061496283398151915282336040516119a8929190614850565b60405180910390a26119ba33866131a5565b336001600160a01b031660008051602061494283398151915287866040516119e392919061403c565b60405180910390a2336001600160a01b031660008051602061492283398151915286604051611a129190614847565b60405180910390a2600954611a2d908763ffffffff612a6516565b600981905560405160008051602061490283398151915291611a4e91614847565b60405180910390a17f6109e2559dfa766aaec7118351d48a523f0a4157f49c8d68749c8ac41318ad123387604051611a87929190613fdf565b60405180910390a1600460009054906101000a90046001600160a01b03166001600160a01b031663ea9638bf87338d8d6040518563ffffffff1660e01b8152600401611ad593929190613f57565b6000604051808303818588803b158015611aee57600080fd5b505af1158015611b02573d6000803e3d6000fd5b505050505050505050505050505050565b60006001600160a01b038216611b3b5760405162461bcd60e51b815260040161089590614434565b8215611b4957611b4961331a565b336000908152600b6020526040902054611b6281612dfc565b6008546001600160a01b0316611b7781611dd8565b6000611b8233610ca9565b90506000611b8f33610d6f565b90506000611b9d8883613551565b90506000611bb1868463ffffffff612a6516565b336000818152600b60205260409020600101549192506001600160a01b0390911690611bdf90879083612ee8565b6000611bea82611642565b90506000611bfe828663ffffffff612a6516565b9050611c0a838261305d565b826001600160a01b03166000805160206149628339815191528233604051611c33929190614850565b60405180910390a2611c458b86613567565b6000611c57878763ffffffff612a6516565b9050611c6333826131a5565b336001600160a01b031660008051602061492283398151915282604051611c8a9190614847565b60405180910390a2336001600160a01b03166000805160206149428339815191528987604051611cbb92919061403c565b60405180910390a2611ccd88336135e0565b50939b9a5050505050505050505050565b6001600160a01b038116611d045760405162461bcd60e51b81526004016108959061429f565b806001600160a01b0316611d16611148565b6001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000604051611d5990613f26565b6040519081900390209190915550565b6001600160a01b038116611d8f5760405162461bcd60e51b8152600401610895906142e1565b803b80610c425760405162461bcd60e51b815260040161089590614646565b6005546001600160a01b0316331461089e5760405162461bcd60e51b815260040161089590614369565b600a54604051636cbdcf4760e01b81526000916001600160a01b03841691636cbdcf4791611e0891600401614847565b602060405180830381600087803b158015611e2257600080fd5b505af1158015611e36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e5a9190613d9e565b9050610c428161370f565b6000806000611e97601554611e8b670de0b6b3a764000089612b3390919063ffffffff16565b9063ffffffff6108a016565b905083851115611ea357fe5b83851415611ec0576000601655670de0b6b3a76400009150611f20565b601654600090611eee90611ee288670de0b6b3a764000063ffffffff612b3316565b9063ffffffff612a6516565b9050611f056001611e8b838863ffffffff612b6d16565b9250611f1b81611ee2858863ffffffff612b3316565b601655505b611f30818563ffffffff612b6d16565b9250611f52611f45848663ffffffff612b3316565b829063ffffffff612a6516565b60155550935093915050565b6010546000670de0b6b3a7640000831115611f7557fe5b6000611f8f670de0b6b3a76400008563ffffffff612a6516565b6011546001600160801b03600160801b820481166000818152601260209081526040808320949095168083529390529283205493945090929091611fd38988612b33565b90506000611fe7838363ffffffff6108a016565b6001600160801b038086166000908152601260209081526040808320938a168352929052819020829055519091507fe12e2cd2c9afa8069203ca07e7eff1edce4a075686d0736a8e7e0d593597b2079061204690839087908990614877565b60405180910390a18561211f5761206d6001600160801b038516600163ffffffff61382016565b601180546001600160801b03908116600160801b938216840217918290556040517fb50f0f59e7cb5b421dc77581c3a9919e3806e076e5fa78a874c3f120cb7d874d936120be930490911690614833565b60405180910390a1601180546001600160801b03191690556040517f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe9061210790600090614833565b60405180910390a1670de0b6b3a7640000965061220c565b633b9aca00612140670de0b6b3a764000061162b8b8a63ffffffff612b3316565b10156121ed57612176670de0b6b3a764000061162b633b9aca0061216a8c8b63ffffffff612b3316565b9063ffffffff612b3316565b96506121926001600160801b038616600163ffffffff61382016565b601180546001600160801b0319166001600160801b0392831617908190556040517f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe926121e0921690614833565b60405180910390a161220c565b612209670de0b6b3a764000061162b8a8963ffffffff612b3316565b96505b6000871161221657fe5b60108790556040517fc1a9618cb59ebca77cbdbc2949f126823c407ff13edb285fd0262519a9c18e8c9061224b908990614847565b60405180910390a150505050505050505050565b60005460405163121cbc4d60e11b81526001600160a01b03909116908190632439789a90612291908590600401614847565b600060405180830381600087803b1580156122ab57600080fd5b505af11580156122bf573d6000803e3d6000fd5b505050506122cc82613851565b600654604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac906122fe9030908690600401613fdf565b600060405180830381600087803b15801561231857600080fd5b505af115801561232c573d6000803e3d6000fd5b50506040516364a197f360e01b81526001600160a01b03841692506364a197f3915061235e9030908790600401613fdf565b600060405180830381600087803b15801561237857600080fd5b505af115801561238c573d6000803e3d6000fd5b50505050505050565b6080810151606082015182516020808501516001600160801b038086166000908152601284526040808220928716825291909352822054919493929185906123e3908463ffffffff612a6516565b6001600160801b0380871660009081526012602052604081209293509161244691633b9aca0091908490612420908a16600163ffffffff61382016565b6001600160801b031681526020810191909152604001600020549063ffffffff612b6d16565b90506000612478670de0b6b3a764000061162b868161246b888863ffffffff6108a016565b8f9063ffffffff612b3316565b9a9950505050505050505050565b6020810151606082015160808301516011546000939291906001600160801b03600160801b909104811690821610156124c557600093505050506108c8565b60115460009081906124e6906001600160801b03168563ffffffff6138ab16565b90506001600160801b0381166125165761250f8561162b6010548b612b3390919063ffffffff16565b915061254e565b806001600160801b0316600114156125495761250f633b9aca0061162b8761162b6010548d612b3390919063ffffffff16565b600091505b61256288633b9aca0063ffffffff612b6d16565b821015612577576000955050505050506108c8565b509695505050505050565b6001600160a01b0381166000908152600d602052604090206001015460ff1615610b335760405162461bcd60e51b81526004016108959061454e565b6001600160a01b0381166000908152600b60205260409020548015610c425760405162461bcd60e51b8152600401610895906145a7565b670de0b6b3a7640000811115610b335760405162461bcd60e51b815260040161089590614484565b612626816138e5565b61262f33612582565b61263882613932565b336000908152600b60205260409020546008546001600160a01b031661265d81611dd8565b8161266c5761266c3384613952565b600061267733610ca9565b9050600061268433610d6f565b90506000612698858363ffffffff612a6516565b336000818152600b60205260409020600101549192506001600160a01b03909116906126c690869083612ee8565b60006126d182611642565b905060006126e5828b63ffffffff6108a016565b90506126f1838261305d565b826001600160a01b0316600080516020614962833981519152823360405161271a929190614850565b60405180910390a261272c338b6139ac565b600061273e868c63ffffffff6108a016565b905061274a33826131a5565b336001600160a01b0316600080516020614922833981519152826040516127719190614847565b60405180910390a2336001600160a01b031660008051602061494283398151915288876040516127a292919061403c565b60405180910390a26127b387613a60565b5050505050505050505050565b600080856001600160a01b03166321df0da76040518163ffffffff1660e01b815260040160206040518083038186803b1580156127fc57600080fd5b505afa158015612810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128349190613c36565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016128649190613f43565b60206040518083038186803b15801561287c57600080fd5b505afa158015612890573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128b49190613d9e565b9050306001600160a01b03831663605629d633838a89356128db60408c0160208d01613eea565b8b604001358c606001356040518863ffffffff1660e01b81526004016129079796959493929190613f9e565b600060405180830381600087803b15801561292157600080fd5b505af1158015612935573d6000803e3d6000fd5b50505050866129ba83856001600160a01b03166370a08231856040518263ffffffff1660e01b815260040161296a9190613f43565b60206040518083038186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee29190613d9e565b146129d75760405162461bcd60e51b81526004016108959061411f565b60405163fb2c922360e01b81526001600160a01b0389169063fb2c922390612a079089908b903390600401614019565b602060405180830381600087803b158015612a2157600080fd5b505af1158015612a35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a599190613d9e565b98975050505050505050565b60006108c583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613a6a565b608081015160608201516040808401516020808601516001600160801b03808716600090815260138452858120918716815292529281205490949392908590612af6908463ffffffff612a6516565b6001600160801b0380871660009081526013602052604081209293509161244691633b9aca0091908490612420908a16600163ffffffff61382016565b600082612b42575060006108c8565b82820282848281612b4f57fe5b04146108c55760405162461bcd60e51b8152600401610895906143f3565b60006108c583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613a96565b600080876001600160a01b03166321df0da76040518163ffffffff1660e01b815260040160206040518083038186803b158015612beb57600080fd5b505afa158015612bff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c239190613c36565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612c539190613f43565b60206040518083038186803b158015612c6b57600080fd5b505afa158015612c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca39190613d9e565b87516020015190915030906001600160a01b0388166330f28b7a8a612cc88585613acd565b338b8b6040518663ffffffff1660e01b8152600401612ceb9594939291906147c2565b600060405180830381600087803b158015612d0557600080fd5b505af1158015612d19573d6000803e3d6000fd5b5050505080612d4e84866001600160a01b03166370a08231866040518263ffffffff1660e01b815260040161296a9190613f43565b14612d6b5760405162461bcd60e51b81526004016108959061411f565b60405163fb2c922360e01b81526001600160a01b038c169063fb2c922390612d9b908d9085903390600401614019565b602060405180830381600087803b158015612db557600080fd5b505af1158015612dc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ded9190613d9e565b9b9a5050505050505050505050565b60008111610b335760405162461bcd60e51b81526004016108959061467b565b6005546040516321e3780160e01b81526001600160a01b03909116906321e3780190612e4c908490600401613f43565b60206040518083038186803b158015612e6457600080fd5b505afa158015612e78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e9c9190613d9e565b600114610b335760405162461bcd60e51b8152600401610895906140b3565b6000612ec682610ca9565b905060008111610c425760405162461bcd60e51b815260040161089590614318565b6001600160a01b03811615612fa8576000612f028261153e565b604051633e30771b60e21b81529091506001600160a01b0385169063f8c1dc6c90612f339085908590600401613fdf565b600060405180830381600087803b158015612f4d57600080fd5b505af1158015612f61573d6000803e3d6000fd5b50505050816001600160a01b03167f732e331072fe280a520929e5f2cc76c223389ff57d32a4e278cfded03e6f1caa82604051612f9e9190614847565b60405180910390a2505b6000612fb3836116df565b604051633e30771b60e21b81529091506001600160a01b0385169063f8c1dc6c90612fe49086908590600401613fdf565b600060405180830381600087803b158015612ffe57600080fd5b505af1158015613012573d6000803e3d6000fd5b50505050826001600160a01b03167fe9ac2dcd83e719358f1dc0c5c80491937f67d4ec61ef62c262bbe3b78578f92a8260405161304f9190614847565b60405180910390a250505050565b6001600160a01b0382166000908152600e60205260409020819055806130e8576001600160a01b0382166000818152600f60205260408082208281556001810183905560028101839055600301829055517fbb1322f85cc7cc8bac4e172a5bc5dcc0c1959007f9a030032abf9258205f0e45916130db91819061403c565b60405180910390a2610c42565b6011546010546001600160801b03600160801b80840482166000818152601360209081526040808320978616808452978252808320546001600160a01b038b16808552600f90935292819020600181018890556002810184905560030180546001600160801b0319168917909616948402949094179094559151909392907fbb1322f85cc7cc8bac4e172a5bc5dcc0c1959007f9a030032abf9258205f0e4590613195908590859061403c565b60405180910390a2505050505050565b6001600160a01b0382166000908152600b6020526040902081905580613243576001600160a01b0382166000818152600b60209081526040808320600190810180546001600160a01b0319169055600c909252808320838155918201839055600282018390556003909101829055517f2d6cc0bcdf72c9486f6451bde6b80f44066f4558f77f44dbfedbe7d8b295225a916130db918190819061404a565b6011546010546001600160801b03600160801b8084048216600081815260126020908152604080832097861680845297825280832054848452601383528184208985528352818420546001600160a01b038c16808652600c90945293829020600181018990558181556002810185905560030180546001600160801b0319168a1790971695850295909517909555935191949390917f2d6cc0bcdf72c9486f6451bde6b80f44066f4558f77f44dbfedbe7d8b295225a906133099086908690869061404a565b60405180910390a250505050505050565b60025460408051630fdb11cf60e01b815290516000926001600160a01b031691630fdb11cf91600480830192602092919082900301818787803b15801561336057600080fd5b505af1158015613374573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133989190613d9e565b90506000600760009054906101000a90046001600160a01b03166001600160a01b0316634d6228316040518163ffffffff1660e01b815260040160206040518083038186803b1580156133ea57600080fd5b505afa1580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134229190613c36565b600554604051630d293c7160e41b81529192506000916001600160a01b039091169063d293c7109061345a9085908790600401613fdf565b60206040518083038186803b15801561347257600080fd5b505afa158015613486573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134aa9190613d9e565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663794e57246040518163ffffffff1660e01b815260040160206040518083038186803b1580156134fa57600080fd5b505afa15801561350e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135329190613d9e565b8110156112995760405162461bcd60e51b815260040161089590614758565b600081831061356057816108c5565b5090919050565b8061357157610c42565b600654604051631062c15f60e11b81526001600160a01b03909116906320c582be906135a590309086908690600401613f7a565b600060405180830381600087803b1580156135bf57600080fd5b505af11580156135d3573d6000803e3d6000fd5b50505050610c4281613851565b6001600160a01b0381166136065760405162461bcd60e51b81526004016108959061419f565b8161361057610c42565b600954600090613626908463ffffffff612a6516565b9050806009819055506000805160206149028339815191528160405161364c9190614847565b60405180910390a17f6109e2559dfa766aaec7118351d48a523f0a4157f49c8d68749c8ac41318ad123384604051613685929190613fdf565b60405180910390a16000336001600160a01b0316846040516136a690613f23565b60006040518083038185875af1925050503d80600081146136e3576040519150601f19603f3d011682016040523d82523d6000602084013e6136e8565b606091505b50509050806137095760405162461bcd60e51b8152600401610895906143b2565b50505050565b600a5480158061371d575081155b156137285750610b33565b60006137348383613aff565b9050600061374d60105483612b3390919063ffffffff16565b6011546001600160801b03600160801b820481166000908152601360209081526040808320939094168252919091522054909150613791908263ffffffff6108a016565b601180546001600160801b03600160801b80830482166000908152601360208181526040808420968616845295815285832097909755945491820483168082529486528381209190921680835294528190205490517f2d6127771b164a9cc8827d24b5955db2a77e7a81dac389107ebb8bce9fb64968936138129391614877565b60405180910390a150505050565b60008282016001600160801b0380851690821610156108c55760405162461bcd60e51b815260040161089590614713565b600a54600090613867908363ffffffff612a6516565b905080600a819055507ff3c69a10dcea5d744225cbe910fb39d6f8208bb8e21fff523d6756a7966093c78160405161389f9190614847565b60405180910390a15050565b6000826001600160801b0316826001600160801b031611156138df5760405162461bcd60e51b8152600401610895906146cb565b50900390565b6001600160a01b0381166000908152600d602052604090206001015460ff168061391657506001600160a01b038116155b610b335760405162461bcd60e51b8152600401610895906141ec565b60008111610b335760405162461bcd60e51b8152600401610895906144d7565b6001600160a01b038281166000818152600b602052604080822060010180546001600160a01b0319169486169485179055517f094c08e96a8890877a8390b4f967180a7507ad8622244d05fcd0f9f8e086564e9190a35050565b600654604051632ee65eeb60e21b81526001600160a01b039091169063bb997bac906139e090859030908690600401613f7a565b600060405180830381600087803b1580156139fa57600080fd5b505af1158015613a0e573d6000803e3d6000fd5b5050600a5460009250613a2891508363ffffffff6108a016565b905080600a819055507ff3c69a10dcea5d744225cbe910fb39d6f8208bb8e21fff523d6756a7966093c781604051610ac19190614847565b610b3381336135e0565b60008184841115613a8e5760405162461bcd60e51b81526004016108959190614060565b505050900390565b60008183613ab75760405162461bcd60e51b81526004016108959190614060565b506000838581613ac357fe5b0495945050505050565b613ad5613ba5565b613add613ba5565b5050604080518082019091526001600160a01b03929092168252602082015290565b600080613b23601454611e8b670de0b6b3a764000087612b3390919063ffffffff16565b90506000613b37828563ffffffff612b6d16565b9050613b59613b4c828663ffffffff612b3316565b839063ffffffff612a6516565b601455949350505050565b6040518060a0016040528060008152602001600081526020016000815260200160006001600160801b0316815260200160006001600160801b031681525090565b604080518082019091526000808252602082015290565b60008083601f840112613bcd578182fd5b50813567ffffffffffffffff811115613be4578182fd5b602083019150836020828501011115613bfc57600080fd5b9250929050565b80356001600160801b03811681146108c857600080fd5b600060208284031215613c2b578081fd5b81356108c5816148ec565b600060208284031215613c47578081fd5b81516108c5816148ec565b60008060408385031215613c64578081fd5b8235613c6f816148ec565b91506020830135613c7f816148ec565b809150509250929050565b600080600080600080600080610100898b031215613ca6578384fd5b8835613cb1816148ec565b97506020890135613cc1816148ec565b96506040890135613cd1816148ec565b95506060890135613ce1816148ec565b94506080890135613cf1816148ec565b935060a0890135613d01816148ec565b925060c0890135613d11816148ec565b915060e0890135613d21816148ec565b809150509295985092959890939650565b600060208284031215613d43578081fd5b815180151581146108c5578182fd5b60008060408385031215613d64578182fd5b613d6e8484613c03565b9150613d7d8460208501613c03565b90509250929050565b600060208284031215613d97578081fd5b5035919050565b600060208284031215613daf578081fd5b5051919050565b60008060408385031215613dc8578182fd5b823591506020830135613c7f816148ec565b60008082840360a0811215613ded578283fd5b833592506080601f1982011215613e02578182fd5b506020830190509250929050565b60008060008084860360c0811215613e26578485fd5b85359450601f1981016080811215613e3c578485fd5b613e4660606148c5565b91506040811215613e55578485fd5b50613e6060406148c5565b6020870135613e6e816148ec565b80825250604087013560208201528082525060608601356020820152608086013560408201528093505060a085013567ffffffffffffffff811115613eb1578283fd5b613ebd87828801613bbc565b95989497509550505050565b60008060408385031215613edb578182fd5b50508035926020909101359150565b600060208284031215613efb578081fd5b813560ff811681146108c5578182fd5b80516001600160a01b03168252602090810151910152565b90565b7035b2bc9737bbb730b136329737bbb732b960791b815260110190565b6001600160a01b0391909116815260200190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6000602080835283518082850152825b8181101561408c57858101830151858201604001528201614070565b8181111561409d5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526046908201527f53746162696c697479506f6f6c3a2063616c6c6572206d75737420686176652060408201527f616e206163746976652074726f766520746f207769746864726177204554484760608201526561696e20746f60d01b608082015260a00190565b60208082526029908201527f444c4c52207472616e7366657272656420616d6f756e742076616c69646174696040820152681bdb8819985a5b195960ba1b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252602d908201527f53503a3a5f73656e644554484761696e546f3a205f726563656976657220697360408201526c207a65726f206164647265737360981b606082015260800190565b60208082526046908201527f53746162696c697479506f6f6c3a20546167206d75737420626520612072656760408201527f697374657265642066726f6e7420656e642c206f7220746865207a65726f206160608201526564647265737360d01b608082015260a00190565b60208082526027908201527f53746162696c697479506f6f6c3a2043616c6c6572206973206e6f74204163746040820152661a5d99541bdbdb60ca1b606082015260800190565b60208082526022908201527f4f776e61626c653a3a7365744f776e65723a20696e76616c6964206164647265604082015261737360f01b606082015260800190565b6020808252601e908201527f4163636f756e742063616e6e6f74206265207a65726f20616464726573730000604082015260600190565b60208082526031908201527f53746162696c697479506f6f6c3a2063616c6c6572206d7573742068617665206040820152703737b716bd32b9379022aa241023b0b4b760791b606082015260800190565b60208082526029908201527f53746162696c697479506f6f6c3a2043616c6c6572206973206e6f742054726f6040820152683b32a6b0b730b3b2b960b91b606082015260800190565b60208082526021908201527f53746162696c697479506f6f6c3a2073656e64696e6720455448206661696c656040820152601960fa1b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526030908201527f53503a3a5f776974686472617746726f6d5370546f3a205f726563656976657260408201526f206973207a65726f206164647265737360801b606082015260800190565b60208082526033908201527f53746162696c697479506f6f6c3a204b69636b6261636b2072617465206d75736040820152727420626520696e2072616e6765205b302c315d60681b606082015260800190565b60208082526026908201527f53746162696c697479506f6f6c3a20416d6f756e74206d757374206265206e6f6040820152656e2d7a65726f60d01b606082015260800190565b60208082526017908201527613dddb98589b194e8e881858d8d95cdcc819195b9a5959604a1b604082015260600190565b60208082526039908201527f53746162696c697479506f6f6c3a206d757374206e6f7420616c72656164792060408201527818994818481c9959da5cdd195c995908199c9bdb9d08195b99603a1b606082015260800190565b60208082526028908201527f53746162696c697479506f6f6c3a2055736572206d7573742068617665206e6f6040820152670819195c1bdcda5d60c21b606082015260800190565b60208082526037908201527f4661696c656420746f20617070726f7665205a55534420616d6f756e7420666f60408201527672204d796e74206d417373657420746f2072656465656d60481b606082015260800190565b6020808252818101527f4163636f756e7420636f64652073697a652063616e6e6f74206265207a65726f604082015260600190565b60208082526030908201527f53746162696c697479506f6f6c3a2055736572206d757374206861766520612060408201526f1b9bdb8b5e995c9bc819195c1bdcda5d60821b606082015260800190565b60208082526028908201527f4c697175697479536166654d6174683132383a207375627472616374696f6e206040820152676f766572666c6f7760c01b606082015260800190565b60208082526025908201527f4c697175697479536166654d6174683132383a206164646974696f6e206f766560408201526472666c6f7760d81b606082015260800190565b60208082526044908201527f53746162696c697479506f6f6c3a2043616e6e6f74207769746864726177207760408201527f68696c65207468657265206172652074726f766573207769746820494352203c6060820152631026a1a960e11b608082015260a00190565b60006101006147d2838951613f0b565b60208801516040840152604088015160608401526147f36080840188613f0b565b6001600160a01b03861660c084015260e083018190528201839052610120838582850137828401810191909152601f909201601f19160101949350505050565b6001600160801b0391909116815260200190565b90815260200190565b9182526001600160a01b0316602082015260400190565b9182521515602082015260400190565b9283526001600160801b03918216602084015216604082015260600190565b948552602085019390935260408401919091526001600160801b03908116606084015216608082015260a00190565b60405181810167ffffffffffffffff811182821017156148e457600080fd5b604052919050565b6001600160a01b0381168114610b3357600080fdfeceb6d671277d4354fd29977ada70695fbd93a16612abf765d6b0e25c28dc6db3bce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c951457222ebca92c335c9c86e2baa1cc0e40ffaa9084a51452980d5ba8dec2f6399920012339b5a3368d3a04b8606ce412c46ed92b7dcd8602d41fc8862cb8f25a2646970667358221220b12079f570461c3902a02d925635ecefb92e70f4556abddd99509e1ecfffdece64736f6c634300060b0033",
  "deployedBytecode": "0x6080604052600436106102ad5760003560e01c806382e0a57411610165578063b31ee965116100cc578063de13da3c11610085578063de13da3c14610788578063df9cd84f146107a8578063e49d3667146107c8578063ec9f7d46146107e8578063fc7e286d146107fd578063fce6b7341461082b578063fda0101a1461084b576102f8565b8063b31ee965146106f4578063bdaf37ea14610709578063c3a34a0e1461071e578063ce4b5bbe1461073e578063d733cfd014610753578063d7fb044314610773576102f8565b80639f0706701161011e5780639f07067014610665578063a20baee614610531578063a3f4df7e1461067a578063a4e59ac81461069c578063a7bfff97146106b1578063ae918754146106df576102f8565b806382e0a574146105d157806386da0824146105f1578063887105d314610611578063893d20e8146106265780638b8fbd921461063b57806395fb16bb14610650576102f8565b80633d83908a1161021457806372fe25aa116101cd57806372fe25aa14610531578063741bef1a14610546578063759b30341461055b578063766718081461057057806377553ad414610592578063795d26c3146105a75780637f7dde4a146105bc576102f8565b80633d83908a1461048757806340ed1afd1461049c578063556be101146104bc5780635d2de642146104dc5780635f788d65146104fc57806370f1b5721461051c576102f8565b80632199b66f116102665780632199b66f146103d257806328a0a04d146103f25780632e54bf9514610412578063335525ad14610432578063389e92a5146104525780633cc7422514610472576102f8565b80630fbfe38b146102fd57806312261ee71461031f57806313af40351461034a57806314f6c3be1461036a57806316b9d3c51461038c5780631bf43555146103bd576102f8565b366102f8576102ba61086b565b6009546102cd903463ffffffff6108a016565b6009819055604051600080516020614902833981519152916102ee91614847565b60405180910390a1005b600080fd5b34801561030957600080fd5b5061031d610318366004613d86565b6108ce565b005b34801561032b57600080fd5b50610334610ace565b6040516103419190613f43565b60405180910390f35b34801561035657600080fd5b5061031d610365366004613c1a565b610af2565b34801561037657600080fd5b5061037f610b36565b6040516103419190614847565b34801561039857600080fd5b506103ac6103a7366004613c1a565b610b3c565b604051610341959493929190614896565b3480156103c957600080fd5b5061037f610b77565b3480156103de57600080fd5b5061031d6103ed366004613c1a565b610b84565b3480156103fe57600080fd5b5061037f61040d366004613d52565b610c1b565b34801561041e57600080fd5b5061031d61042d366004613d86565b610c38565b34801561043e57600080fd5b5061031d61044d366004613ec9565b610c46565b34801561045e57600080fd5b5061037f61046d366004613c1a565b610ca9565b34801561047e57600080fd5b50610334610d51565b34801561049357600080fd5b50610334610d60565b3480156104a857600080fd5b5061037f6104b7366004613c1a565b610d6f565b3480156104c857600080fd5b5061031d6104d7366004613d86565b610e0c565b3480156104e857600080fd5b5061037f6104f7366004613c1a565b610e84565b34801561050857600080fd5b5061031d610517366004613db6565b610e96565b34801561052857600080fd5b5061037f610ea0565b34801561053d57600080fd5b5061037f610ea6565b34801561055257600080fd5b50610334610eb2565b34801561056757600080fd5b5061037f610ec1565b34801561057c57600080fd5b50610585610ece565b6040516103419190614833565b34801561059e57600080fd5b50610334610ee4565b3480156105b357600080fd5b5061037f610ef3565b3480156105c857600080fd5b50610334611012565b3480156105dd57600080fd5b5061037f6105ec366004613d52565b611021565b3480156105fd57600080fd5b506103ac61060c366004613c1a565b61103e565b34801561061d57600080fd5b5061037f611079565b34801561063257600080fd5b50610334611148565b34801561064757600080fd5b5061037f611167565b34801561065c57600080fd5b5061033461116d565b34801561067157600080fd5b5061033461117c565b34801561068657600080fd5b5061068f61118b565b6040516103419190614060565b3480156106a857600080fd5b506105856111b4565b3480156106bd57600080fd5b506106d16106cc366004613c1a565b6111c3565b604051610341929190614867565b3480156106eb57600080fd5b506103346111df565b34801561070057600080fd5b5061037f6111ee565b34801561071557600080fd5b5061037f6111f4565b34801561072a57600080fd5b5061031d610739366004613dda565b6111fa565b34801561074a57600080fd5b5061037f61129e565b34801561075f57600080fd5b5061031d61076e366004613c8a565b6112a6565b34801561077f57600080fd5b5061037f611538565b34801561079457600080fd5b5061037f6107a3366004613c1a565b61153e565b3480156107b457600080fd5b5061037f6107c3366004613c1a565b611642565b3480156107d457600080fd5b5061037f6107e3366004613c1a565b6116df565b3480156107f457600080fd5b506103346117dc565b34801561080957600080fd5b5061081d610818366004613c1a565b6117eb565b604051610341929190614850565b34801561083757600080fd5b5061031d610846366004613e10565b61180d565b34801561085757600080fd5b5061031d610866366004613c52565b6118cd565b6000546001600160a01b0316331461089e5760405162461bcd60e51b815260040161089590614258565b60405180910390fd5b565b6000828201838110156108c55760405162461bcd60e51b815260040161089590614168565b90505b92915050565b6000600460009054906101000a90046001600160a01b03166001600160a01b031663e9fc34616040518163ffffffff1660e01b815260040160206040518083038186803b15801561091e57600080fd5b505afa158015610932573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109569190613c36565b905060006109648330611b13565b60065460405163095ea7b360e01b81529192506001600160a01b03169063095ea7b3906109979085908590600401613fdf565b602060405180830381600087803b1580156109b157600080fd5b505af11580156109c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e99190613d32565b610a055760405162461bcd60e51b8152600401610895906145ef565b60065460405163438b1b4b60e01b81526001600160a01b038481169263438b1b4b92610a3b929091169085903390600401614019565b602060405180830381600087803b158015610a5557600080fd5b505af1158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190613d9e565b507f2b0fbec1c4e7e30517f196a714775ffe72770d2348f5d586854bb3c0fdf41df8338483604051610ac193929190613ff8565b60405180910390a1505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610afa611148565b6001600160a01b0316336001600160a01b031614610b2a5760405162461bcd60e51b81526004016108959061451d565b610b3381611cde565b50565b60095490565b600f602052600090815260409020805460018201546002830154600390930154919290916001600160801b0380821691600160801b90041685565b6809c2007651b250000081565b610b8c611148565b6001600160a01b0316336001600160a01b031614610bbc5760405162461bcd60e51b81526004016108959061451d565b610bc581611d69565b600880546001600160a01b0319166001600160a01b0383161790556040517f3055265812fb8447b9ada4a5d804ec43bd528ec40e89c952bbc7b85dc5ac681190610c10908390613f43565b60405180910390a150565b601260209081526000928352604080842090915290825290205481565b610c428133611b13565b5050565b610c4e611dae565b600a54801580610c5c575082155b15610c675750610c42565b600854610c7c906001600160a01b0316611dd8565b600080610c8a848685611e65565b91509150610c988282611f5e565b610ca2848661225f565b5050505050565b6001600160a01b0381166000908152600b602052604081205480610cd1576000915050610d4c565b610cd9613b64565b506001600160a01b0383166000908152600c60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290610d468383612395565b93505050505b919050565b6001546001600160a01b031681565b6005546001600160a01b031681565b6001600160a01b0381166000908152600b602052604081205480610d97576000915050610d4c565b610d9f613b64565b506001600160a01b0383166000908152600c60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290610d468383612486565b610e1533612582565b610e1e336125be565b610e27816125f5565b336000818152600d6020526040908190208381556001908101805460ff19169091179055517f19bc932fb9e16a8b5a1e41be9f4c2de59d5ddd7567b8b81405f532ca00a9880e90610e79908490614847565b60405180910390a250565b600e6020526000908152604090205481565b610c42828261261d565b60145481565b670de0b6b3a764000081565b6002546001600160a01b031681565b6801158e460913d0000081565b601154600160801b90046001600160801b031681565b6004546001600160a01b031681565b60008054604080516272c7d360e71b8152905183926001600160a01b031691633963e980916004808301926020929190829003018186803b158015610f3757600080fd5b505afa158015610f4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6f9190613d9e565b90506000600160009054906101000a90046001600160a01b03166001600160a01b0316633963e9806040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc157600080fd5b505afa158015610fd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff99190613d9e565b905061100b828263ffffffff6108a016565b9250505090565b6000546001600160a01b031681565b601360209081526000928352604080842090915290825290205481565b600c602052600090815260409020805460018201546002830154600390930154919290916001600160801b0380821691600160801b90041685565b6000805460408051630a7b61df60e11b8152905183926001600160a01b0316916314f6c3be916004808301926020929190829003018186803b1580156110be57600080fd5b505afa1580156110d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f69190613d9e565b90506000600160009054906101000a90046001600160a01b03166001600160a01b03166314f6c3be6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fc157600080fd5b60008060405161115790613f26565b6040519081900390205492915050565b60105481565b6008546001600160a01b031681565b6003546001600160a01b031681565b6040518060400160405280600d81526020016c14dd18589a5b1a5d1e541bdbdb609a1b81525081565b6011546001600160801b031681565b600d602052600090815260409020805460019091015460ff1682565b6007546001600160a01b031681565b60165481565b600a5490565b600480546040805163e9fc346160e01b8152905160009361128c936001600160a01b03169263e9fc34619281830192602092829003018186803b15801561124057600080fd5b505afa158015611254573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112789190613c36565b60065485906001600160a01b0316856127c0565b905061129981600061261d565b505050565b633b9aca0081565b6112ae611148565b6001600160a01b0316336001600160a01b0316146112de5760405162461bcd60e51b81526004016108959061451d565b6112e788611d69565b6112f087611d69565b6112f986611d69565b61130285611d69565b61130b84611d69565b61131483611d69565b61131d82611d69565b61132681611d69565b670de0b6b3a7640000601055600380546001600160a01b03199081166001600160a01b038b8116919091179092556004805482168a8416179055600580548216898416179055600080548216888416179055600680548216878416179055600780548216868416179055600280548216858416179055600880549091169183169190911790556040517f3ca631ffcd2a9b5d9ae18543fc82f58eb4ca33af9e6ab01b7a8e95331e6ed985906113dc908990613f43565b60405180910390a17f143219c9e69b09e07e095fcc889b43d8f46ca892bba65f08dc3a0050869a5678866040516114139190613f43565b60405180910390a17f78f058b189175430c48dc02699e3a0031ea4ff781536dc2fab847de4babdd8828560405161144a9190613f43565b60405180910390a17fcdf33850c44a1a874b5fefb51dae615ac6afebd581ef90d571f81b06541d8e9d846040516114819190613f43565b60405180910390a17f65f4cf077bc01e4742eb5ad98326f6e95b63548ea24b17f8d5e823111fe78800836040516114b89190613f43565b60405180910390a17f8c537274438aa850a330284665d81a85dd38267d09e4050d416bfc94142db264826040516114ef9190613f43565b60405180910390a17f3055265812fb8447b9ada4a5d804ec43bd528ec40e89c952bbc7b85dc5ac6811816040516115269190613f43565b60405180910390a15050505050505050565b60155481565b6001600160a01b0381166000908152600e602052604081205480611566576000915050610d4c565b6001600160a01b0383166000908152600d602052604081205490611598670de0b6b3a76400008363ffffffff612a6516565b90506115a2613b64565b506001600160a01b0385166000908152600f60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290611637670de0b6b3a764000061162b61161e8886612aa7565b869063ffffffff612b3316565b9063ffffffff612b6d16565b979650505050505050565b6001600160a01b0381166000908152600e60205260408120548061166a576000915050610d4c565b611672613b64565b506001600160a01b0383166000908152600f60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290610d468383612486565b6001600160a01b0381166000908152600b602052604081205480611707576000915050610d4c565b6001600160a01b038084166000908152600b602052604081206001015490911690811561174c576001600160a01b0382166000908152600d6020526040902054611756565b670de0b6b3a76400005b9050611760613b64565b506001600160a01b0385166000908152600c60209081526040808320815160a08101835281548152600182015493810193909352600281015491830191909152600301546001600160801b038082166060840152600160801b90910416608082015290611637670de0b6b3a764000061162b61161e8886612aa7565b6006546001600160a01b031681565b600b60205260009081526040902080546001909101546001600160a01b031682565b600480546040805163e9fc346160e01b815290516000936118c0936001600160a01b03169263e9fc34619281830192602092829003018186803b15801561185357600080fd5b505afa158015611867573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188b9190613c36565b6006546001600160a01b0316867f00000000000000000000000000000000000000000000000000000000000000008787612baf565b9050610ca281600061261d565b336000908152600b60205260409020546118e681612dfc565b6118ef33612e1c565b6118f833612ebb565b6008546001600160a01b031661190d81611dd8565b600061191833610ca9565b9050600061192533610d6f565b90506000611939858363ffffffff612a6516565b336000818152600b60205260409020600101549192506001600160a01b039091169061196790869083612ee8565b600061197282611642565b90508061197f838261305d565b826001600160a01b031660008051602061496283398151915282336040516119a8929190614850565b60405180910390a26119ba33866131a5565b336001600160a01b031660008051602061494283398151915287866040516119e392919061403c565b60405180910390a2336001600160a01b031660008051602061492283398151915286604051611a129190614847565b60405180910390a2600954611a2d908763ffffffff612a6516565b600981905560405160008051602061490283398151915291611a4e91614847565b60405180910390a17f6109e2559dfa766aaec7118351d48a523f0a4157f49c8d68749c8ac41318ad123387604051611a87929190613fdf565b60405180910390a1600460009054906101000a90046001600160a01b03166001600160a01b031663ea9638bf87338d8d6040518563ffffffff1660e01b8152600401611ad593929190613f57565b6000604051808303818588803b158015611aee57600080fd5b505af1158015611b02573d6000803e3d6000fd5b505050505050505050505050505050565b60006001600160a01b038216611b3b5760405162461bcd60e51b815260040161089590614434565b8215611b4957611b4961331a565b336000908152600b6020526040902054611b6281612dfc565b6008546001600160a01b0316611b7781611dd8565b6000611b8233610ca9565b90506000611b8f33610d6f565b90506000611b9d8883613551565b90506000611bb1868463ffffffff612a6516565b336000818152600b60205260409020600101549192506001600160a01b0390911690611bdf90879083612ee8565b6000611bea82611642565b90506000611bfe828663ffffffff612a6516565b9050611c0a838261305d565b826001600160a01b03166000805160206149628339815191528233604051611c33929190614850565b60405180910390a2611c458b86613567565b6000611c57878763ffffffff612a6516565b9050611c6333826131a5565b336001600160a01b031660008051602061492283398151915282604051611c8a9190614847565b60405180910390a2336001600160a01b03166000805160206149428339815191528987604051611cbb92919061403c565b60405180910390a2611ccd88336135e0565b50939b9a5050505050505050505050565b6001600160a01b038116611d045760405162461bcd60e51b81526004016108959061429f565b806001600160a01b0316611d16611148565b6001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000604051611d5990613f26565b6040519081900390209190915550565b6001600160a01b038116611d8f5760405162461bcd60e51b8152600401610895906142e1565b803b80610c425760405162461bcd60e51b815260040161089590614646565b6005546001600160a01b0316331461089e5760405162461bcd60e51b815260040161089590614369565b600a54604051636cbdcf4760e01b81526000916001600160a01b03841691636cbdcf4791611e0891600401614847565b602060405180830381600087803b158015611e2257600080fd5b505af1158015611e36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e5a9190613d9e565b9050610c428161370f565b6000806000611e97601554611e8b670de0b6b3a764000089612b3390919063ffffffff16565b9063ffffffff6108a016565b905083851115611ea357fe5b83851415611ec0576000601655670de0b6b3a76400009150611f20565b601654600090611eee90611ee288670de0b6b3a764000063ffffffff612b3316565b9063ffffffff612a6516565b9050611f056001611e8b838863ffffffff612b6d16565b9250611f1b81611ee2858863ffffffff612b3316565b601655505b611f30818563ffffffff612b6d16565b9250611f52611f45848663ffffffff612b3316565b829063ffffffff612a6516565b60155550935093915050565b6010546000670de0b6b3a7640000831115611f7557fe5b6000611f8f670de0b6b3a76400008563ffffffff612a6516565b6011546001600160801b03600160801b820481166000818152601260209081526040808320949095168083529390529283205493945090929091611fd38988612b33565b90506000611fe7838363ffffffff6108a016565b6001600160801b038086166000908152601260209081526040808320938a168352929052819020829055519091507fe12e2cd2c9afa8069203ca07e7eff1edce4a075686d0736a8e7e0d593597b2079061204690839087908990614877565b60405180910390a18561211f5761206d6001600160801b038516600163ffffffff61382016565b601180546001600160801b03908116600160801b938216840217918290556040517fb50f0f59e7cb5b421dc77581c3a9919e3806e076e5fa78a874c3f120cb7d874d936120be930490911690614833565b60405180910390a1601180546001600160801b03191690556040517f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe9061210790600090614833565b60405180910390a1670de0b6b3a7640000965061220c565b633b9aca00612140670de0b6b3a764000061162b8b8a63ffffffff612b3316565b10156121ed57612176670de0b6b3a764000061162b633b9aca0061216a8c8b63ffffffff612b3316565b9063ffffffff612b3316565b96506121926001600160801b038616600163ffffffff61382016565b601180546001600160801b0319166001600160801b0392831617908190556040517f1f9dfc70cd666adb18a39d60a797518f7b4febf4b6e24ef37d44f6e1e7219fbe926121e0921690614833565b60405180910390a161220c565b612209670de0b6b3a764000061162b8a8963ffffffff612b3316565b96505b6000871161221657fe5b60108790556040517fc1a9618cb59ebca77cbdbc2949f126823c407ff13edb285fd0262519a9c18e8c9061224b908990614847565b60405180910390a150505050505050505050565b60005460405163121cbc4d60e11b81526001600160a01b03909116908190632439789a90612291908590600401614847565b600060405180830381600087803b1580156122ab57600080fd5b505af11580156122bf573d6000803e3d6000fd5b505050506122cc82613851565b600654604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac906122fe9030908690600401613fdf565b600060405180830381600087803b15801561231857600080fd5b505af115801561232c573d6000803e3d6000fd5b50506040516364a197f360e01b81526001600160a01b03841692506364a197f3915061235e9030908790600401613fdf565b600060405180830381600087803b15801561237857600080fd5b505af115801561238c573d6000803e3d6000fd5b50505050505050565b6080810151606082015182516020808501516001600160801b038086166000908152601284526040808220928716825291909352822054919493929185906123e3908463ffffffff612a6516565b6001600160801b0380871660009081526012602052604081209293509161244691633b9aca0091908490612420908a16600163ffffffff61382016565b6001600160801b031681526020810191909152604001600020549063ffffffff612b6d16565b90506000612478670de0b6b3a764000061162b868161246b888863ffffffff6108a016565b8f9063ffffffff612b3316565b9a9950505050505050505050565b6020810151606082015160808301516011546000939291906001600160801b03600160801b909104811690821610156124c557600093505050506108c8565b60115460009081906124e6906001600160801b03168563ffffffff6138ab16565b90506001600160801b0381166125165761250f8561162b6010548b612b3390919063ffffffff16565b915061254e565b806001600160801b0316600114156125495761250f633b9aca0061162b8761162b6010548d612b3390919063ffffffff16565b600091505b61256288633b9aca0063ffffffff612b6d16565b821015612577576000955050505050506108c8565b509695505050505050565b6001600160a01b0381166000908152600d602052604090206001015460ff1615610b335760405162461bcd60e51b81526004016108959061454e565b6001600160a01b0381166000908152600b60205260409020548015610c425760405162461bcd60e51b8152600401610895906145a7565b670de0b6b3a7640000811115610b335760405162461bcd60e51b815260040161089590614484565b612626816138e5565b61262f33612582565b61263882613932565b336000908152600b60205260409020546008546001600160a01b031661265d81611dd8565b8161266c5761266c3384613952565b600061267733610ca9565b9050600061268433610d6f565b90506000612698858363ffffffff612a6516565b336000818152600b60205260409020600101549192506001600160a01b03909116906126c690869083612ee8565b60006126d182611642565b905060006126e5828b63ffffffff6108a016565b90506126f1838261305d565b826001600160a01b0316600080516020614962833981519152823360405161271a929190614850565b60405180910390a261272c338b6139ac565b600061273e868c63ffffffff6108a016565b905061274a33826131a5565b336001600160a01b0316600080516020614922833981519152826040516127719190614847565b60405180910390a2336001600160a01b031660008051602061494283398151915288876040516127a292919061403c565b60405180910390a26127b387613a60565b5050505050505050505050565b600080856001600160a01b03166321df0da76040518163ffffffff1660e01b815260040160206040518083038186803b1580156127fc57600080fd5b505afa158015612810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128349190613c36565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016128649190613f43565b60206040518083038186803b15801561287c57600080fd5b505afa158015612890573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128b49190613d9e565b9050306001600160a01b03831663605629d633838a89356128db60408c0160208d01613eea565b8b604001358c606001356040518863ffffffff1660e01b81526004016129079796959493929190613f9e565b600060405180830381600087803b15801561292157600080fd5b505af1158015612935573d6000803e3d6000fd5b50505050866129ba83856001600160a01b03166370a08231856040518263ffffffff1660e01b815260040161296a9190613f43565b60206040518083038186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee29190613d9e565b146129d75760405162461bcd60e51b81526004016108959061411f565b60405163fb2c922360e01b81526001600160a01b0389169063fb2c922390612a079089908b903390600401614019565b602060405180830381600087803b158015612a2157600080fd5b505af1158015612a35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a599190613d9e565b98975050505050505050565b60006108c583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613a6a565b608081015160608201516040808401516020808601516001600160801b03808716600090815260138452858120918716815292529281205490949392908590612af6908463ffffffff612a6516565b6001600160801b0380871660009081526013602052604081209293509161244691633b9aca0091908490612420908a16600163ffffffff61382016565b600082612b42575060006108c8565b82820282848281612b4f57fe5b04146108c55760405162461bcd60e51b8152600401610895906143f3565b60006108c583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613a96565b600080876001600160a01b03166321df0da76040518163ffffffff1660e01b815260040160206040518083038186803b158015612beb57600080fd5b505afa158015612bff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c239190613c36565b90506000816001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612c539190613f43565b60206040518083038186803b158015612c6b57600080fd5b505afa158015612c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca39190613d9e565b87516020015190915030906001600160a01b0388166330f28b7a8a612cc88585613acd565b338b8b6040518663ffffffff1660e01b8152600401612ceb9594939291906147c2565b600060405180830381600087803b158015612d0557600080fd5b505af1158015612d19573d6000803e3d6000fd5b5050505080612d4e84866001600160a01b03166370a08231866040518263ffffffff1660e01b815260040161296a9190613f43565b14612d6b5760405162461bcd60e51b81526004016108959061411f565b60405163fb2c922360e01b81526001600160a01b038c169063fb2c922390612d9b908d9085903390600401614019565b602060405180830381600087803b158015612db557600080fd5b505af1158015612dc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ded9190613d9e565b9b9a5050505050505050505050565b60008111610b335760405162461bcd60e51b81526004016108959061467b565b6005546040516321e3780160e01b81526001600160a01b03909116906321e3780190612e4c908490600401613f43565b60206040518083038186803b158015612e6457600080fd5b505afa158015612e78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e9c9190613d9e565b600114610b335760405162461bcd60e51b8152600401610895906140b3565b6000612ec682610ca9565b905060008111610c425760405162461bcd60e51b815260040161089590614318565b6001600160a01b03811615612fa8576000612f028261153e565b604051633e30771b60e21b81529091506001600160a01b0385169063f8c1dc6c90612f339085908590600401613fdf565b600060405180830381600087803b158015612f4d57600080fd5b505af1158015612f61573d6000803e3d6000fd5b50505050816001600160a01b03167f732e331072fe280a520929e5f2cc76c223389ff57d32a4e278cfded03e6f1caa82604051612f9e9190614847565b60405180910390a2505b6000612fb3836116df565b604051633e30771b60e21b81529091506001600160a01b0385169063f8c1dc6c90612fe49086908590600401613fdf565b600060405180830381600087803b158015612ffe57600080fd5b505af1158015613012573d6000803e3d6000fd5b50505050826001600160a01b03167fe9ac2dcd83e719358f1dc0c5c80491937f67d4ec61ef62c262bbe3b78578f92a8260405161304f9190614847565b60405180910390a250505050565b6001600160a01b0382166000908152600e60205260409020819055806130e8576001600160a01b0382166000818152600f60205260408082208281556001810183905560028101839055600301829055517fbb1322f85cc7cc8bac4e172a5bc5dcc0c1959007f9a030032abf9258205f0e45916130db91819061403c565b60405180910390a2610c42565b6011546010546001600160801b03600160801b80840482166000818152601360209081526040808320978616808452978252808320546001600160a01b038b16808552600f90935292819020600181018890556002810184905560030180546001600160801b0319168917909616948402949094179094559151909392907fbb1322f85cc7cc8bac4e172a5bc5dcc0c1959007f9a030032abf9258205f0e4590613195908590859061403c565b60405180910390a2505050505050565b6001600160a01b0382166000908152600b6020526040902081905580613243576001600160a01b0382166000818152600b60209081526040808320600190810180546001600160a01b0319169055600c909252808320838155918201839055600282018390556003909101829055517f2d6cc0bcdf72c9486f6451bde6b80f44066f4558f77f44dbfedbe7d8b295225a916130db918190819061404a565b6011546010546001600160801b03600160801b8084048216600081815260126020908152604080832097861680845297825280832054848452601383528184208985528352818420546001600160a01b038c16808652600c90945293829020600181018990558181556002810185905560030180546001600160801b0319168a1790971695850295909517909555935191949390917f2d6cc0bcdf72c9486f6451bde6b80f44066f4558f77f44dbfedbe7d8b295225a906133099086908690869061404a565b60405180910390a250505050505050565b60025460408051630fdb11cf60e01b815290516000926001600160a01b031691630fdb11cf91600480830192602092919082900301818787803b15801561336057600080fd5b505af1158015613374573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133989190613d9e565b90506000600760009054906101000a90046001600160a01b03166001600160a01b0316634d6228316040518163ffffffff1660e01b815260040160206040518083038186803b1580156133ea57600080fd5b505afa1580156133fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134229190613c36565b600554604051630d293c7160e41b81529192506000916001600160a01b039091169063d293c7109061345a9085908790600401613fdf565b60206040518083038186803b15801561347257600080fd5b505afa158015613486573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134aa9190613d9e565b9050600360009054906101000a90046001600160a01b03166001600160a01b031663794e57246040518163ffffffff1660e01b815260040160206040518083038186803b1580156134fa57600080fd5b505afa15801561350e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135329190613d9e565b8110156112995760405162461bcd60e51b815260040161089590614758565b600081831061356057816108c5565b5090919050565b8061357157610c42565b600654604051631062c15f60e11b81526001600160a01b03909116906320c582be906135a590309086908690600401613f7a565b600060405180830381600087803b1580156135bf57600080fd5b505af11580156135d3573d6000803e3d6000fd5b50505050610c4281613851565b6001600160a01b0381166136065760405162461bcd60e51b81526004016108959061419f565b8161361057610c42565b600954600090613626908463ffffffff612a6516565b9050806009819055506000805160206149028339815191528160405161364c9190614847565b60405180910390a17f6109e2559dfa766aaec7118351d48a523f0a4157f49c8d68749c8ac41318ad123384604051613685929190613fdf565b60405180910390a16000336001600160a01b0316846040516136a690613f23565b60006040518083038185875af1925050503d80600081146136e3576040519150601f19603f3d011682016040523d82523d6000602084013e6136e8565b606091505b50509050806137095760405162461bcd60e51b8152600401610895906143b2565b50505050565b600a5480158061371d575081155b156137285750610b33565b60006137348383613aff565b9050600061374d60105483612b3390919063ffffffff16565b6011546001600160801b03600160801b820481166000908152601360209081526040808320939094168252919091522054909150613791908263ffffffff6108a016565b601180546001600160801b03600160801b80830482166000908152601360208181526040808420968616845295815285832097909755945491820483168082529486528381209190921680835294528190205490517f2d6127771b164a9cc8827d24b5955db2a77e7a81dac389107ebb8bce9fb64968936138129391614877565b60405180910390a150505050565b60008282016001600160801b0380851690821610156108c55760405162461bcd60e51b815260040161089590614713565b600a54600090613867908363ffffffff612a6516565b905080600a819055507ff3c69a10dcea5d744225cbe910fb39d6f8208bb8e21fff523d6756a7966093c78160405161389f9190614847565b60405180910390a15050565b6000826001600160801b0316826001600160801b031611156138df5760405162461bcd60e51b8152600401610895906146cb565b50900390565b6001600160a01b0381166000908152600d602052604090206001015460ff168061391657506001600160a01b038116155b610b335760405162461bcd60e51b8152600401610895906141ec565b60008111610b335760405162461bcd60e51b8152600401610895906144d7565b6001600160a01b038281166000818152600b602052604080822060010180546001600160a01b0319169486169485179055517f094c08e96a8890877a8390b4f967180a7507ad8622244d05fcd0f9f8e086564e9190a35050565b600654604051632ee65eeb60e21b81526001600160a01b039091169063bb997bac906139e090859030908690600401613f7a565b600060405180830381600087803b1580156139fa57600080fd5b505af1158015613a0e573d6000803e3d6000fd5b5050600a5460009250613a2891508363ffffffff6108a016565b905080600a819055507ff3c69a10dcea5d744225cbe910fb39d6f8208bb8e21fff523d6756a7966093c781604051610ac19190614847565b610b3381336135e0565b60008184841115613a8e5760405162461bcd60e51b81526004016108959190614060565b505050900390565b60008183613ab75760405162461bcd60e51b81526004016108959190614060565b506000838581613ac357fe5b0495945050505050565b613ad5613ba5565b613add613ba5565b5050604080518082019091526001600160a01b03929092168252602082015290565b600080613b23601454611e8b670de0b6b3a764000087612b3390919063ffffffff16565b90506000613b37828563ffffffff612b6d16565b9050613b59613b4c828663ffffffff612b3316565b839063ffffffff612a6516565b601455949350505050565b6040518060a0016040528060008152602001600081526020016000815260200160006001600160801b0316815260200160006001600160801b031681525090565b604080518082019091526000808252602082015290565b60008083601f840112613bcd578182fd5b50813567ffffffffffffffff811115613be4578182fd5b602083019150836020828501011115613bfc57600080fd5b9250929050565b80356001600160801b03811681146108c857600080fd5b600060208284031215613c2b578081fd5b81356108c5816148ec565b600060208284031215613c47578081fd5b81516108c5816148ec565b60008060408385031215613c64578081fd5b8235613c6f816148ec565b91506020830135613c7f816148ec565b809150509250929050565b600080600080600080600080610100898b031215613ca6578384fd5b8835613cb1816148ec565b97506020890135613cc1816148ec565b96506040890135613cd1816148ec565b95506060890135613ce1816148ec565b94506080890135613cf1816148ec565b935060a0890135613d01816148ec565b925060c0890135613d11816148ec565b915060e0890135613d21816148ec565b809150509295985092959890939650565b600060208284031215613d43578081fd5b815180151581146108c5578182fd5b60008060408385031215613d64578182fd5b613d6e8484613c03565b9150613d7d8460208501613c03565b90509250929050565b600060208284031215613d97578081fd5b5035919050565b600060208284031215613daf578081fd5b5051919050565b60008060408385031215613dc8578182fd5b823591506020830135613c7f816148ec565b60008082840360a0811215613ded578283fd5b833592506080601f1982011215613e02578182fd5b506020830190509250929050565b60008060008084860360c0811215613e26578485fd5b85359450601f1981016080811215613e3c578485fd5b613e4660606148c5565b91506040811215613e55578485fd5b50613e6060406148c5565b6020870135613e6e816148ec565b80825250604087013560208201528082525060608601356020820152608086013560408201528093505060a085013567ffffffffffffffff811115613eb1578283fd5b613ebd87828801613bbc565b95989497509550505050565b60008060408385031215613edb578182fd5b50508035926020909101359150565b600060208284031215613efb578081fd5b813560ff811681146108c5578182fd5b80516001600160a01b03168252602090810151910152565b90565b7035b2bc9737bbb730b136329737bbb732b960791b815260110190565b6001600160a01b0391909116815260200190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b6000602080835283518082850152825b8181101561408c57858101830151858201604001528201614070565b8181111561409d5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526046908201527f53746162696c697479506f6f6c3a2063616c6c6572206d75737420686176652060408201527f616e206163746976652074726f766520746f207769746864726177204554484760608201526561696e20746f60d01b608082015260a00190565b60208082526029908201527f444c4c52207472616e7366657272656420616d6f756e742076616c69646174696040820152681bdb8819985a5b195960ba1b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252602d908201527f53503a3a5f73656e644554484761696e546f3a205f726563656976657220697360408201526c207a65726f206164647265737360981b606082015260800190565b60208082526046908201527f53746162696c697479506f6f6c3a20546167206d75737420626520612072656760408201527f697374657265642066726f6e7420656e642c206f7220746865207a65726f206160608201526564647265737360d01b608082015260a00190565b60208082526027908201527f53746162696c697479506f6f6c3a2043616c6c6572206973206e6f74204163746040820152661a5d99541bdbdb60ca1b606082015260800190565b60208082526022908201527f4f776e61626c653a3a7365744f776e65723a20696e76616c6964206164647265604082015261737360f01b606082015260800190565b6020808252601e908201527f4163636f756e742063616e6e6f74206265207a65726f20616464726573730000604082015260600190565b60208082526031908201527f53746162696c697479506f6f6c3a2063616c6c6572206d7573742068617665206040820152703737b716bd32b9379022aa241023b0b4b760791b606082015260800190565b60208082526029908201527f53746162696c697479506f6f6c3a2043616c6c6572206973206e6f742054726f6040820152683b32a6b0b730b3b2b960b91b606082015260800190565b60208082526021908201527f53746162696c697479506f6f6c3a2073656e64696e6720455448206661696c656040820152601960fa1b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526030908201527f53503a3a5f776974686472617746726f6d5370546f3a205f726563656976657260408201526f206973207a65726f206164647265737360801b606082015260800190565b60208082526033908201527f53746162696c697479506f6f6c3a204b69636b6261636b2072617465206d75736040820152727420626520696e2072616e6765205b302c315d60681b606082015260800190565b60208082526026908201527f53746162696c697479506f6f6c3a20416d6f756e74206d757374206265206e6f6040820152656e2d7a65726f60d01b606082015260800190565b60208082526017908201527613dddb98589b194e8e881858d8d95cdcc819195b9a5959604a1b604082015260600190565b60208082526039908201527f53746162696c697479506f6f6c3a206d757374206e6f7420616c72656164792060408201527818994818481c9959da5cdd195c995908199c9bdb9d08195b99603a1b606082015260800190565b60208082526028908201527f53746162696c697479506f6f6c3a2055736572206d7573742068617665206e6f6040820152670819195c1bdcda5d60c21b606082015260800190565b60208082526037908201527f4661696c656420746f20617070726f7665205a55534420616d6f756e7420666f60408201527672204d796e74206d417373657420746f2072656465656d60481b606082015260800190565b6020808252818101527f4163636f756e7420636f64652073697a652063616e6e6f74206265207a65726f604082015260600190565b60208082526030908201527f53746162696c697479506f6f6c3a2055736572206d757374206861766520612060408201526f1b9bdb8b5e995c9bc819195c1bdcda5d60821b606082015260800190565b60208082526028908201527f4c697175697479536166654d6174683132383a207375627472616374696f6e206040820152676f766572666c6f7760c01b606082015260800190565b60208082526025908201527f4c697175697479536166654d6174683132383a206164646974696f6e206f766560408201526472666c6f7760d81b606082015260800190565b60208082526044908201527f53746162696c697479506f6f6c3a2043616e6e6f74207769746864726177207760408201527f68696c65207468657265206172652074726f766573207769746820494352203c6060820152631026a1a960e11b608082015260a00190565b60006101006147d2838951613f0b565b60208801516040840152604088015160608401526147f36080840188613f0b565b6001600160a01b03861660c084015260e083018190528201839052610120838582850137828401810191909152601f909201601f19160101949350505050565b6001600160801b0391909116815260200190565b90815260200190565b9182526001600160a01b0316602082015260400190565b9182521515602082015260400190565b9283526001600160801b03918216602084015216604082015260600190565b948552602085019390935260408401919091526001600160801b03908116606084015216608082015260a00190565b60405181810167ffffffffffffffff811182821017156148e457600080fd5b604052919050565b6001600160a01b0381168114610b3357600080fdfeceb6d671277d4354fd29977ada70695fbd93a16612abf765d6b0e25c28dc6db3bce78369dccab09eec1986f4d409ab09ffbb47d65423e5148fcf98411c5111c951457222ebca92c335c9c86e2baa1cc0e40ffaa9084a51452980d5ba8dec2f6399920012339b5a3368d3a04b8606ce412c46ed92b7dcd8602d41fc8862cb8f25a2646970667358221220b12079f570461c3902a02d925635ecefb92e70f4556abddd99509e1ecfffdece64736f6c634300060b0033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "getETH()": {
        "returns": {
          "_0": "the total amount of ETH held by the pool, accounted in an internal variable instead of `balance`, to exclude edge cases like ETH received from a self-destruct."
        }
      },
      "getOwner()": {
        "returns": {
          "_owner": "Address of the owner. "
        }
      },
      "getTotalZUSDDeposits()": {
        "returns": {
          "_0": "ZUSD held in the pool. Changes when users deposit/withdraw, and when Trove debt is offset."
        }
      },
      "setAddresses(address,address,address,address,address,address,address,address)": {
        "details": "initializer function, checks addresses are contracts",
        "params": {
          "_activePoolAddress": "ActivePool contract address",
          "_borrowerOperationsAddress": "BorrowerOperations contract address",
          "_communityIssuanceAddress": "CommunityIssuanceAddress",
          "_liquityBaseParamsAddress": "LiquidityBaseParams contract address",
          "_priceFeedAddress": "PriceFeed contract address",
          "_sortedTrovesAddress": "SortedTroves contract address",
          "_troveManagerAddress": "TroveManager contract address",
          "_zusdTokenAddress": "ZUSDToken contract address"
        }
      },
      "setCommunityIssuanceAddress(address)": {
        "details": "setter function specific for community issuance contract.",
        "params": {
          "_communityIssuanceAddress": "address of new community issuance contract."
        }
      },
      "setOwner(address)": {
        "params": {
          "_owner": "Address of the owner. "
        }
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {
      "MIN_NET_DEBT()": {
        "notice": "Minimum amount of net ZUSD debt a trove must have"
      },
      "ZUSD_GAS_COMPENSATION()": {
        "notice": "Amount of ZUSD to be locked in gas pool on opening troves"
      },
      "constructor": "Constructor ",
      "getCompoundedFrontEndStake(address)": {
        "notice": "Return the front end's compounded stake. Given by the formula:  D = D0 * P/P(0) where P(0) is the depositor's snapshot of the product P, taken at the last time when one of the front end's tagged deposits updated their deposit. The front end's compounded stake is equal to the sum of its depositors' compounded deposits."
      },
      "getCompoundedZUSDDeposit(address)": {
        "notice": "Return the user's compounded deposit. Given by the formula:  d = d0 * P/P(0) where P(0) is the depositor's snapshot of the product P, taken when they last updated their deposit."
      },
      "getDepositorETHGain(address)": {
        "notice": "Calculates the ETH gain earned by the deposit since its last snapshots were taken. Given by the formula:  E = d0 * (S - S(0))/P(0) where S(0) and P(0) are the depositor's snapshots of the sum S and product P, respectively. d0 is the last recorded deposit value."
      },
      "getDepositorSOVGain(address)": {
        "notice": "Calculate the SOV gain earned by a deposit since its last snapshots were taken. Given by the formula:  SOV = d0 * (G - G(0))/P(0) where G(0) and P(0) are the depositor's snapshots of the sum G and product P, respectively. d0 is the last recorded deposit value."
      },
      "getFrontEndSOVGain(address)": {
        "notice": "Return the SOV gain earned by the front end. Given by the formula:  E = D0 * (G - G(0))/P(0) where G(0) and P(0) are the depositor's snapshots of the sum G and product P, respectively. D0 is the last recorded value of the front end's total tagged deposits."
      },
      "getOwner()": {
        "notice": "Return address of the owner."
      },
      "offset(uint256,uint256)": {
        "notice": "Cancels out the specified debt against the ZUSD contained in the Stability Pool (as far as possible) and transfers the Trove's ETH collateral from ActivePool to StabilityPool. Only called by liquidation functions in the TroveManager."
      },
      "provideToSP(uint256,address)": {
        "notice": "provideToSP(): - Triggers a SOV issuance, based on time passed since the last issuance and total amount of deposited ZUSD. The SOV issuance is shared between *all* depositors and front ends - Tags the deposit with the provided front end tag param, if it's a new deposit - Sends depositor's accumulated gains (SOV, ETH) to depositor - Sends the tagged front end's accumulated SOV gains to the tagged front end - Increases deposit and tagged front end's stake, and takes new snapshots for each."
      },
      "provideToSpFromDLLR(uint256,(uint256,uint8,bytes32,bytes32))": {
        "notice": "DLLR _owner or _spender can convert a specified amount of DLLR into ZUSD via Sovryn Mynt and deposit the ZUSD into the Zero Stability Pool, all in a single transaction"
      },
      "provideToSpFromDllrWithPermit2(uint256,((address,uint256),uint256,uint256),bytes)": {
        "notice": "DLLR _owner or _spender can convert a specified amount of DLLR into ZUSD via Sovryn Mynt and deposit the ZUSD into the Zero Stability Pool, all in a single transaction"
      },
      "registerFrontEnd(uint256)": {
        "notice": "Front end makes a one-time selection of kickback rate upon registering"
      },
      "setAddresses(address,address,address,address,address,address,address,address)": {
        "notice": "Called only once on init, to set addresses of other Liquity contracts. Callable only by owner"
      },
      "setOwner(address)": {
        "notice": "Set address of the owner (only owner can call this function)"
      },
      "withdrawETHGainToTrove(address,address)": {
        "notice": "withdrawETHGainToTrove: - Triggers a SOV issuance, based on time passed since the last issuance. The SOV issuance is shared between *all* depositors and front ends - Sends all depositor's SOV gain to  depositor - Sends all tagged front end's SOV gain to the tagged front end - Transfers the depositor's entire ETH gain from the Stability Pool to the caller's trove - Leaves their compounded deposit in the Stability Pool - Updates snapshots for deposit and tagged front end stake "
      },
      "withdrawFromSP(uint256)": {
        "notice": "withdrawFromSP(): - Triggers a SOV issuance, based on time passed since the last issuance and total amount of ZUSD is deposited. The SOV issuance is shared between *all* depositors and front ends - Removes the deposit's front end tag if it is a full withdrawal - Sends all depositor's accumulated gains (SOV, ETH) to depositor - Sends the tagged front end's accumulated SOV gains to the tagged front end - Decreases deposit and tagged front end's stake, and takes new snapshots for each. If _amount > userDeposit, the user withdraws all of their compounded deposit."
      },
      "withdrawFromSpAndConvertToDLLR(uint256)": {
        "notice": "Stability Pool depositor can withdraw a specified amount of ZUSD from the Zero Stability Pool and convert the ZUSD to DLLR via Sovryn Mynt, all in a single transaction"
      }
    },
    "notice": "The Stability Pool holds ZUSD tokens deposited by Stability Pool depositors. When a trove is liquidated, then depending on system conditions, some of its ZUSD debt gets offset with ZUSD in the Stability Pool:  that is, the offset debt evaporates, and an equal amount of ZUSD tokens in the Stability Pool is burned. Thus, a liquidation causes each depositor to receive a ZUSD loss, in proportion to their deposit as a share of total deposits. They also receive an ETH gain, as the ETH collateral of the liquidated trove is distributed among Stability depositors, in the same proportion. When a liquidation occurs, it depletes every deposit by the same fraction: for example, a liquidation that depletes 40% of the total ZUSD in the Stability Pool, depletes 40% of each deposit. A deposit that has experienced a series of liquidations is termed a \"compounded deposit\": each liquidation depletes the deposit, multiplying it by some factor in range ]0,1[ --- IMPLEMENTATION --- We use a highly scalable method of tracking deposits and ETH gains that has O(1) complexity. When a liquidation occurs, rather than updating each depositor's deposit and ETH gain, we simply update two state variables: a product P, and a sum S. A mathematical manipulation allows us to factor out the initial deposit, and accurately track all depositors' compounded deposits and accumulated ETH gains over time, as liquidations occur, using just these two variables P and S. When depositors join the Stability Pool, they get a snapshot of the latest P and S: P_t and S_t, respectively. The formula for a depositor's accumulated ETH gain is derived here: https://github.com/liquity/dev/blob/main/packages/contracts/mathProofs/Scalable%20Compounding%20Stability%20Pool%20Deposits.pdf For a given deposit d_t, the ratio P/P_t tells us the factor by which a deposit has decreased since it joined the Stability Pool, and the term d_t * (S - S_t)/P_t gives us the deposit's total accumulated ETH gain. Each liquidation updates the product P and sum S. After a series of liquidations, a compounded deposit and corresponding ETH gain can be calculated using the initial deposit, the depositor’s snapshots of P and S, and the latest values of P and S. Any time a depositor updates their deposit (withdrawal, top-up) their accumulated ETH gain is paid out, their new deposit is recorded (based on their latest compounded deposit and modified by the withdrawal/top-up), and they receive new snapshots of the latest P and S. Essentially, they make a fresh deposit that overwrites the old one. --- SCALE FACTOR --- Since P is a running product in range ]0,1] that is always-decreasing, it should never reach 0 when multiplied by a number in range ]0,1[. Unfortunately, Solidity floor division always reaches 0, sooner or later. A series of liquidations that nearly empty the Pool (and thus each multiply P by a very small number in range ]0,1[ ) may push P to its 18 digit decimal limit, and round it to 0, when in fact the Pool hasn't been emptied: this would break deposit tracking. So, to track P accurately, we use a scale factor: if a liquidation would cause P to decrease to <1e-9 (and be rounded to 0 by Solidity), we first multiply P by 1e9, and increment a currentScale factor by 1. The added benefit of using 1e9 for the scale factor (rather than 1e18) is that it ensures negligible precision loss close to the scale boundary: when P is at its minimum value of 1e9, the relative precision loss in P due to floor division is only on the order of 1e-9. --- EPOCHS --- Whenever a liquidation fully empties the Stability Pool, all deposits should become 0. However, setting P to 0 would make P be 0 forever, and break all future reward calculations. So, every time the Stability Pool is emptied by a liquidation, we reset P = 1 and currentScale = 0, and increment the currentEpoch by 1. --- TRACKING DEPOSIT OVER SCALE CHANGES AND EPOCHS --- When a deposit is made, it gets snapshots of the currentEpoch and the currentScale. When calculating a compounded deposit, we compare the current epoch to the deposit's epoch snapshot. If the current epoch is newer, then the deposit was present during a pool-emptying liquidation, and necessarily has been depleted to 0. Otherwise, we then compare the current scale to the deposit's scale snapshot. If they're equal, the compounded deposit is given by d_t * P/P_t. If it spans one scale change, it is given by d_t * P/(P_t * 1e9). If it spans more than one scale change, we define the compounded deposit as 0, since it is now less than 1e-9'th of its initial value (e.g. a deposit of 1 billion ZUSD has depleted to < 1 ZUSD).  --- TRACKING DEPOSITOR'S ETH GAIN OVER SCALE CHANGES AND EPOCHS --- In the current epoch, the latest value of S is stored upon each scale change, and the mapping (scale -> S) is stored for each epoch. This allows us to calculate a deposit's accumulated ETH gain, during the epoch in which the deposit was non-zero and earned ETH. We calculate the depositor's accumulated ETH gain for the scale at which they made the deposit, using the ETH gain formula: e_1 = d_t * (S - S_t) / P_t and also for scale after, taking care to divide the latter by a factor of 1e9: e_2 = d_t * S / (P_t * 1e9) The gain in the second scale will be full, as the starting point was in the previous scale, thus no need to subtract anything. The deposit therefore was present for reward events from the beginning of that second scale.        S_i-S_t + S_{i+1}      .<--------.------------>      .         .      . S_i     .   S_{i+1}   <--.-------->.<----------->   S_t.         .   <->.         .      t         .  |---+---------|-------------|-----...         i            i+1 The sum of (e_1 + e_2) captures the depositor's total accumulated ETH gain, handling the case where their deposit spanned one scale change. We only care about gains across one scale change, since the compounded deposit is defined as being 0 once it has spanned more than one scale change. --- UPDATING P WHEN A LIQUIDATION OCCURS --- Please see the implementation spec in the proof document, which closely follows on from the compounded deposit / ETH gain derivations: https://github.com/liquity/liquity/blob/master/papers/Scalable_Reward_Distribution_with_Compounding_Stakes.pdf --- SOV ISSUANCE TO STABILITY POOL DEPOSITORS --- An SOV issuance event occurs at every deposit operation, and every liquidation. Each deposit is tagged with the address of the front end through which it was made. All deposits earn a share of the issued SOV in proportion to the deposit as a share of total deposits. The SOV earned by a given deposit, is split between the depositor and the front end through which the deposit was made, based on the front end's kickbackRate. Please see the system Readme for an overview: https://github.com/liquity/dev/blob/main/README.md#zero-issuance-to-stability-providers We use the same mathematical product-sum approach to track SOV gains for depositors, where 'G' is the sum corresponding to SOV gains. The product P (and snapshot P_t) is re-used, as the ratio P/P_t tracks a deposit's depletion due to liquidations.",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 5495,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "activePool",
        "offset": 0,
        "slot": "0",
        "type": "t_contract(IActivePool)19557"
      },
      {
        "astId": 5497,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "defaultPool",
        "offset": 0,
        "slot": "1",
        "type": "t_contract(IDefaultPool)20229"
      },
      {
        "astId": 5500,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "priceFeed",
        "offset": 0,
        "slot": "2",
        "type": "t_contract(IPriceFeed)20458"
      },
      {
        "astId": 5503,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "liquityBaseParams",
        "offset": 0,
        "slot": "3",
        "type": "t_contract(ILiquityBaseParams)20379"
      },
      {
        "astId": 28084,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "borrowerOperations",
        "offset": 0,
        "slot": "4",
        "type": "t_contract(IBorrowerOperations)20065"
      },
      {
        "astId": 28086,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "troveManager",
        "offset": 0,
        "slot": "5",
        "type": "t_contract(ITroveManager)21635"
      },
      {
        "astId": 28088,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "zusdToken",
        "offset": 0,
        "slot": "6",
        "type": "t_contract(IZUSDToken)21842"
      },
      {
        "astId": 28090,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "sortedTroves",
        "offset": 0,
        "slot": "7",
        "type": "t_contract(ISortedTroves)20817"
      },
      {
        "astId": 28092,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "communityIssuance",
        "offset": 0,
        "slot": "8",
        "type": "t_contract(ICommunityIssuance)20205"
      },
      {
        "astId": 28094,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "ETH",
        "offset": 0,
        "slot": "9",
        "type": "t_uint256"
      },
      {
        "astId": 28096,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "totalZUSDDeposits",
        "offset": 0,
        "slot": "10",
        "type": "t_uint256"
      },
      {
        "astId": 28121,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "deposits",
        "offset": 0,
        "slot": "11",
        "type": "t_mapping(t_address,t_struct(Deposit)28106_storage)"
      },
      {
        "astId": 28125,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "depositSnapshots",
        "offset": 0,
        "slot": "12",
        "type": "t_mapping(t_address,t_struct(Snapshots)28117_storage)"
      },
      {
        "astId": 28129,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "frontEnds",
        "offset": 0,
        "slot": "13",
        "type": "t_mapping(t_address,t_struct(FrontEnd)28101_storage)"
      },
      {
        "astId": 28133,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "frontEndStakes",
        "offset": 0,
        "slot": "14",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 28137,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "frontEndSnapshots",
        "offset": 0,
        "slot": "15",
        "type": "t_mapping(t_address,t_struct(Snapshots)28117_storage)"
      },
      {
        "astId": 28139,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "P",
        "offset": 0,
        "slot": "16",
        "type": "t_uint256"
      },
      {
        "astId": 28144,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "currentScale",
        "offset": 0,
        "slot": "17",
        "type": "t_uint128"
      },
      {
        "astId": 28146,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "currentEpoch",
        "offset": 16,
        "slot": "17",
        "type": "t_uint128"
      },
      {
        "astId": 28152,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "epochToScaleToSum",
        "offset": 0,
        "slot": "18",
        "type": "t_mapping(t_uint128,t_mapping(t_uint128,t_uint256))"
      },
      {
        "astId": 28158,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "epochToScaleToG",
        "offset": 0,
        "slot": "19",
        "type": "t_mapping(t_uint128,t_mapping(t_uint128,t_uint256))"
      },
      {
        "astId": 28160,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "lastSOVError",
        "offset": 0,
        "slot": "20",
        "type": "t_uint256"
      },
      {
        "astId": 28162,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "lastETHError_Offset",
        "offset": 0,
        "slot": "21",
        "type": "t_uint256"
      },
      {
        "astId": 28164,
        "contract": "contracts/StabilityPool.sol:StabilityPool",
        "label": "lastZUSDLossError_Offset",
        "offset": 0,
        "slot": "22",
        "type": "t_uint256"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_bool": {
        "encoding": "inplace",
        "label": "bool",
        "numberOfBytes": "1"
      },
      "t_contract(IActivePool)19557": {
        "encoding": "inplace",
        "label": "contract IActivePool",
        "numberOfBytes": "20"
      },
      "t_contract(IBorrowerOperations)20065": {
        "encoding": "inplace",
        "label": "contract IBorrowerOperations",
        "numberOfBytes": "20"
      },
      "t_contract(ICommunityIssuance)20205": {
        "encoding": "inplace",
        "label": "contract ICommunityIssuance",
        "numberOfBytes": "20"
      },
      "t_contract(IDefaultPool)20229": {
        "encoding": "inplace",
        "label": "contract IDefaultPool",
        "numberOfBytes": "20"
      },
      "t_contract(ILiquityBaseParams)20379": {
        "encoding": "inplace",
        "label": "contract ILiquityBaseParams",
        "numberOfBytes": "20"
      },
      "t_contract(IPriceFeed)20458": {
        "encoding": "inplace",
        "label": "contract IPriceFeed",
        "numberOfBytes": "20"
      },
      "t_contract(ISortedTroves)20817": {
        "encoding": "inplace",
        "label": "contract ISortedTroves",
        "numberOfBytes": "20"
      },
      "t_contract(ITroveManager)21635": {
        "encoding": "inplace",
        "label": "contract ITroveManager",
        "numberOfBytes": "20"
      },
      "t_contract(IZUSDToken)21842": {
        "encoding": "inplace",
        "label": "contract IZUSDToken",
        "numberOfBytes": "20"
      },
      "t_mapping(t_address,t_struct(Deposit)28106_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct StabilityPoolStorage.Deposit)",
        "numberOfBytes": "32",
        "value": "t_struct(Deposit)28106_storage"
      },
      "t_mapping(t_address,t_struct(FrontEnd)28101_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct StabilityPoolStorage.FrontEnd)",
        "numberOfBytes": "32",
        "value": "t_struct(FrontEnd)28101_storage"
      },
      "t_mapping(t_address,t_struct(Snapshots)28117_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct StabilityPoolStorage.Snapshots)",
        "numberOfBytes": "32",
        "value": "t_struct(Snapshots)28117_storage"
      },
      "t_mapping(t_address,t_uint256)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_mapping(t_uint128,t_mapping(t_uint128,t_uint256))": {
        "encoding": "mapping",
        "key": "t_uint128",
        "label": "mapping(uint128 => mapping(uint128 => uint256))",
        "numberOfBytes": "32",
        "value": "t_mapping(t_uint128,t_uint256)"
      },
      "t_mapping(t_uint128,t_uint256)": {
        "encoding": "mapping",
        "key": "t_uint128",
        "label": "mapping(uint128 => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_struct(Deposit)28106_storage": {
        "encoding": "inplace",
        "label": "struct StabilityPoolStorage.Deposit",
        "members": [
          {
            "astId": 28103,
            "contract": "contracts/StabilityPool.sol:StabilityPool",
            "label": "initialValue",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          },
          {
            "astId": 28105,
            "contract": "contracts/StabilityPool.sol:StabilityPool",
            "label": "frontEndTag",
            "offset": 0,
            "slot": "1",
            "type": "t_address"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_struct(FrontEnd)28101_storage": {
        "encoding": "inplace",
        "label": "struct StabilityPoolStorage.FrontEnd",
        "members": [
          {
            "astId": 28098,
            "contract": "contracts/StabilityPool.sol:StabilityPool",
            "label": "kickbackRate",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          },
          {
            "astId": 28100,
            "contract": "contracts/StabilityPool.sol:StabilityPool",
            "label": "registered",
            "offset": 0,
            "slot": "1",
            "type": "t_bool"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_struct(Snapshots)28117_storage": {
        "encoding": "inplace",
        "label": "struct StabilityPoolStorage.Snapshots",
        "members": [
          {
            "astId": 28108,
            "contract": "contracts/StabilityPool.sol:StabilityPool",
            "label": "S",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          },
          {
            "astId": 28110,
            "contract": "contracts/StabilityPool.sol:StabilityPool",
            "label": "P",
            "offset": 0,
            "slot": "1",
            "type": "t_uint256"
          },
          {
            "astId": 28112,
            "contract": "contracts/StabilityPool.sol:StabilityPool",
            "label": "G",
            "offset": 0,
            "slot": "2",
            "type": "t_uint256"
          },
          {
            "astId": 28114,
            "contract": "contracts/StabilityPool.sol:StabilityPool",
            "label": "scale",
            "offset": 0,
            "slot": "3",
            "type": "t_uint128"
          },
          {
            "astId": 28116,
            "contract": "contracts/StabilityPool.sol:StabilityPool",
            "label": "epoch",
            "offset": 16,
            "slot": "3",
            "type": "t_uint128"
          }
        ],
        "numberOfBytes": "128"
      },
      "t_uint128": {
        "encoding": "inplace",
        "label": "uint128",
        "numberOfBytes": "16"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      }
    }
  }
}