{
  "address": "0xE1edC4E2A2Bc9E69BE5E4C7E985742905cBd93A9",
  "abi": [
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "user",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "rewardToken",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "ClaimReward",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "user",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "fee",
          "type": "uint256"
        }
      ],
      "name": "Deposit",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "newFee",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "oldFee",
          "type": "uint256"
        }
      ],
      "name": "DepositFeeChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "user",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "EmergencyWithdraw",
      "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": "address",
          "name": "token",
          "type": "address"
        }
      ],
      "name": "RewardTokenAdded",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "token",
          "type": "address"
        }
      ],
      "name": "RewardTokenRemoved",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "user",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "Withdraw",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "ACC_REWARD_PER_SHARE_PRECISION",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "DEPOSIT_FEE_PERCENT_PRECISION",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "",
          "type": "address"
        }
      ],
      "name": "accRewardPerShare",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "_rewardToken",
          "type": "address"
        }
      ],
      "name": "addRewardToken",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        }
      ],
      "name": "deposit",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "depositFeePercent",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "emergencyWithdraw",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "feeCollector",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "_rewardToken",
          "type": "address"
        }
      ],
      "name": "getUserInfo",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "_rewardToken",
          "type": "address"
        },
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "_joe",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_feeCollector",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_depositFeePercent",
          "type": "uint256"
        }
      ],
      "name": "initialize",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "",
          "type": "address"
        }
      ],
      "name": "isRewardToken",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "joe",
      "outputs": [
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "",
          "type": "address"
        }
      ],
      "name": "lastRewardBalance",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "_token",
          "type": "address"
        }
      ],
      "name": "pendingReward",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "_rewardToken",
          "type": "address"
        }
      ],
      "name": "removeRewardToken",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "renounceOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "rewardTokens",
      "outputs": [
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "rewardTokensLength",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_depositFeePercent",
          "type": "uint256"
        }
      ],
      "name": "setDepositFeePercent",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "transferOwnership",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "contract IERC20Upgradeable",
          "name": "_token",
          "type": "address"
        }
      ],
      "name": "updateReward",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        }
      ],
      "name": "withdraw",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0x2097634609333d71dbb6c52e9843b0687f81c0f9045412f92334e198f1150049",
  "receipt": {
    "to": null,
    "from": "0x1d9D82344E76769EB727521822D1EacB834A9024",
    "contractAddress": "0xE1edC4E2A2Bc9E69BE5E4C7E985742905cBd93A9",
    "transactionIndex": 1,
    "gasUsed": "3332545",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x1b5293547e757a67eb2e13692577b3ffc12432c6e29c0849de2337434e900ca5",
    "transactionHash": "0x2097634609333d71dbb6c52e9843b0687f81c0f9045412f92334e198f1150049",
    "logs": [],
    "blockNumber": 10220590,
    "cumulativeGasUsed": "3471290",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "numDeployments": 2,
  "solcInputHash": "edb9a81c274146338d0a6aa4eeebdefd",
  "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ClaimReward\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFee\",\"type\":\"uint256\"}],\"name\":\"DepositFeeChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"EmergencyWithdraw\",\"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\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"RewardTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"RewardTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdraw\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ACC_REWARD_PER_SHARE_PRECISION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEPOSIT_FEE_PERCENT_PRECISION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"accRewardPerShare\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"_rewardToken\",\"type\":\"address\"}],\"name\":\"addRewardToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositFeePercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"emergencyWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeCollector\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"_rewardToken\",\"type\":\"address\"}],\"name\":\"getUserInfo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"_joe\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_feeCollector\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_depositFeePercent\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isRewardToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"joe\",\"outputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"lastRewardBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"pendingReward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"_rewardToken\",\"type\":\"address\"}],\"name\":\"removeRewardToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"rewardTokens\",\"outputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rewardTokensLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_depositFeePercent\",\"type\":\"uint256\"}],\"name\":\"setDepositFeePercent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20Upgradeable\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"updateReward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Trader Joe\",\"kind\":\"dev\",\"methods\":{\"addRewardToken(address)\":{\"params\":{\"_rewardToken\":\"The address of the reward token\"}},\"deposit(uint256)\":{\"params\":{\"_amount\":\"The amount of JOE to deposit\"}},\"getUserInfo(address,address)\":{\"params\":{\"_rewardToken\":\"The address of the reward token\",\"_user\":\"The address of the user\"},\"returns\":{\"_0\":\"The amount of JOE user has deposited\",\"_1\":\"The reward debt for the chosen token\"}},\"initialize(address,address,address,uint256)\":{\"details\":\"This contract needs to receive an ERC20 `_rewardToken` in order to distribute them (with MoneyMaker in our case)\",\"params\":{\"_depositFeePercent\":\"The deposit fee percent, scalled to 1e18, e.g. 3% is 3e16\",\"_feeCollector\":\"The address where deposit fees will be sent\",\"_joe\":\"The address of the JOE token\",\"_rewardToken\":\"The address of the ERC20 reward token\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingReward(address,address)\":{\"params\":{\"_token\":\"The address of the token\",\"_user\":\"The address of the user\"},\"returns\":{\"_0\":\"`_user`'s pending reward token\"}},\"removeRewardToken(address)\":{\"params\":{\"_rewardToken\":\"The address of the reward token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"rewardTokensLength()\":{\"returns\":{\"_0\":\"The length of the array\"}},\"setDepositFeePercent(uint256)\":{\"params\":{\"_depositFeePercent\":\"The new deposit fee percent\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"updateReward(address)\":{\"details\":\"Needs to be called before any deposit or withdrawal\",\"params\":{\"_token\":\"The address of the reward token\"}},\"withdraw(uint256)\":{\"params\":{\"_amount\":\"The amount of JOE to withdraw\"}}},\"stateVariables\":{\"internalJoeBalance\":{\"details\":\"Internal balance of JOE, this gets updated on user deposits / withdrawals this allows to reward users with JOE\"},\"userInfo\":{\"details\":\"Info of each user that stakes JOE\"}},\"title\":\"Stable JOE Staking\",\"version\":1},\"userdoc\":{\"events\":{\"ClaimReward(address,address,uint256)\":{\"notice\":\"Emitted when a user claims reward\"},\"Deposit(address,uint256,uint256)\":{\"notice\":\"Emitted when a user deposits JOE\"},\"DepositFeeChanged(uint256,uint256)\":{\"notice\":\"Emitted when owner changes the deposit fee percentage\"},\"EmergencyWithdraw(address,uint256)\":{\"notice\":\"Emitted when a user emergency withdraws its JOE\"},\"RewardTokenAdded(address)\":{\"notice\":\"Emitted when owner adds a token to the reward tokens list\"},\"RewardTokenRemoved(address)\":{\"notice\":\"Emitted when owner removes a token from the reward tokens list\"},\"Withdraw(address,uint256)\":{\"notice\":\"Emitted when a user withdraws JOE\"}},\"kind\":\"user\",\"methods\":{\"ACC_REWARD_PER_SHARE_PRECISION()\":{\"notice\":\"The precision of `accRewardPerShare`\"},\"DEPOSIT_FEE_PERCENT_PRECISION()\":{\"notice\":\"The precision of `depositFeePercent`\"},\"accRewardPerShare(address)\":{\"notice\":\"Accumulated `token` rewards per share, scaled to `ACC_REWARD_PER_SHARE_PRECISION`\"},\"addRewardToken(address)\":{\"notice\":\"Add a reward token\"},\"deposit(uint256)\":{\"notice\":\"Deposit JOE for reward token allocation\"},\"depositFeePercent()\":{\"notice\":\"The deposit fee, scaled to `DEPOSIT_FEE_PERCENT_PRECISION`\"},\"emergencyWithdraw()\":{\"notice\":\"Withdraw without caring about rewards. EMERGENCY ONLY\"},\"getUserInfo(address,address)\":{\"notice\":\"Get user info\"},\"initialize(address,address,address,uint256)\":{\"notice\":\"Initialize a new StableJoeStaking contract\"},\"lastRewardBalance(address)\":{\"notice\":\"Last reward balance of `token`\"},\"pendingReward(address,address)\":{\"notice\":\"View function to see pending reward token on frontend\"},\"removeRewardToken(address)\":{\"notice\":\"Remove a reward token\"},\"rewardTokens(uint256)\":{\"notice\":\"Array of tokens that users can claim\"},\"rewardTokensLength()\":{\"notice\":\"Get the number of reward tokens\"},\"setDepositFeePercent(uint256)\":{\"notice\":\"Set the deposit fee percent\"},\"updateReward(address)\":{\"notice\":\"Update reward variables\"},\"withdraw(uint256)\":{\"notice\":\"Withdraw JOE and harvest the rewards\"}},\"notice\":\"StableJoeStaking is a contract that allows JOE deposits and receives stablecoins sent by MoneyMaker's daily harvests. Users deposit JOE and receive a share of what has been sent by MoneyMaker based on their participation of the total deposited JOE. It is similar to a MasterChef, but we allow for claiming of different reward tokens (in case at some point we wish to change the stablecoin rewarded). Every time `updateReward(token)` is called, We distribute the balance of that tokens as rewards to users that are currently staking inside this contract, and they can claim it using `withdraw(0)`\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/StableJoeStaking.sol\":\"StableJoeStaking\"},\"evmVersion\":\"istanbul\",\"libraries\":{\":__CACHE_BREAKER__\":\"0x00000000d41867734bbee4c6863d9255b2b06ac1\"},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/GSN/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\nimport \\\"../proxy/Initializable.sol\\\";\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n    function __Context_init() internal initializer {\\n        __Context_init_unchained();\\n    }\\n\\n    function __Context_init_unchained() internal initializer {\\n    }\\n    function _msgSender() internal view virtual returns (address payable) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes memory) {\\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n        return msg.data;\\n    }\\n    uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0xbbf8a21b9a66c48d45ff771b8563c6df19ba451d63dfb8380a865c1e1f29d1a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../GSN/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/Initializable.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 * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\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 */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n    address private _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    function __Ownable_init() internal initializer {\\n        __Context_init_unchained();\\n        __Ownable_init_unchained();\\n    }\\n\\n    function __Ownable_init_unchained() internal initializer {\\n        address msgSender = _msgSender();\\n        _owner = msgSender;\\n        emit OwnershipTransferred(address(0), msgSender);\\n    }\\n\\n    /**\\n     * @dev Returns the address of the current owner.\\n     */\\n    function owner() public view returns (address) {\\n        return _owner;\\n    }\\n\\n    /**\\n     * @dev Throws if called by any account other than the owner.\\n     */\\n    modifier onlyOwner() {\\n        require(_owner == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n        _;\\n    }\\n\\n    /**\\n     * @dev Leaves the contract without owner. It will not be possible to call\\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\\n     *\\n     * NOTE: Renouncing ownership will leave the contract without an owner,\\n     * thereby removing any functionality that is only available to the owner.\\n     */\\n    function renounceOwnership() public virtual onlyOwner {\\n        emit OwnershipTransferred(_owner, address(0));\\n        _owner = address(0);\\n    }\\n\\n    /**\\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n     * Can only be called by the current owner.\\n     */\\n    function transferOwnership(address newOwner) public virtual onlyOwner {\\n        require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n        emit OwnershipTransferred(_owner, newOwner);\\n        _owner = newOwner;\\n    }\\n    uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0xe422bf8bc61fe71acb27de4631400cdbb9b532df4de4f255eab093ac356f9745\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\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 SafeMathUpgradeable {\\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     *\\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     *\\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     *\\n     * - Subtraction cannot overflow.\\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     *\\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     *\\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     *\\n     * - The divisor cannot be zero.\\n     */\\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\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     *\\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     *\\n     * - The divisor cannot be zero.\\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\":\"0xe9ecc18d06bcc5aa48c40a98333540248b6c1c18ecb6262329c06d3f0cbb45ae\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// solhint-disable-next-line compiler-version\\npragma solidity >=0.4.24 <0.8.0;\\n\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n * \\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\\n * \\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n */\\nabstract contract Initializable {\\n\\n    /**\\n     * @dev Indicates that the contract has been initialized.\\n     */\\n    bool private _initialized;\\n\\n    /**\\n     * @dev Indicates that the contract is in the process of being initialized.\\n     */\\n    bool private _initializing;\\n\\n    /**\\n     * @dev Modifier to protect an initializer function from being invoked twice.\\n     */\\n    modifier initializer() {\\n        require(_initializing || _isConstructor() || !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n        bool isTopLevelCall = !_initializing;\\n        if (isTopLevelCall) {\\n            _initializing = true;\\n            _initialized = true;\\n        }\\n\\n        _;\\n\\n        if (isTopLevelCall) {\\n            _initializing = false;\\n        }\\n    }\\n\\n    /// @dev Returns true if and only if the function is running in the constructor\\n    function _isConstructor() private view returns (bool) {\\n        // extcodesize checks the size of the code stored in an address, and\\n        // address returns the current address. Since the code is still not\\n        // deployed when running a constructor, any checks on its code size will\\n        // yield zero, making it an effective way to detect if a contract is\\n        // under construction or not.\\n        address self = address(this);\\n        uint256 cs;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { cs := extcodesize(self) }\\n        return cs == 0;\\n    }\\n}\\n\",\"keccak256\":\"0xae7044b7c89ed74327b0979ae6f317c65d87b8d17a42d0c62d698d77d5de5511\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20Upgradeable {\\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\\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    /**\\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}\\n\",\"keccak256\":\"0xa1931c47a617014f858580db625aa0dcf343796f39acd4b5b51effc092a1f0a9\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/SafeERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20Upgradeable.sol\\\";\\nimport \\\"../../math/SafeMathUpgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20Upgradeable {\\n    using SafeMathUpgradeable for uint256;\\n    using AddressUpgradeable for address;\\n\\n    function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n    }\\n\\n    /**\\n     * @dev Deprecated. This function has issues similar to the ones found in\\n     * {IERC20-approve}, and its usage is discouraged.\\n     *\\n     * Whenever possible, use {safeIncreaseAllowance} and\\n     * {safeDecreaseAllowance} instead.\\n     */\\n    function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\\n        // safeApprove should only be called when setting an initial allowance,\\n        // or when resetting it to zero. To increase and decrease it, use\\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n        // solhint-disable-next-line max-line-length\\n        require((value == 0) || (token.allowance(address(this), spender) == 0),\\n            \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n        );\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n    }\\n\\n    function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    /**\\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\\n     * @param token The token targeted by the call.\\n     * @param data The call data (encoded using abi.encode or one of its variants).\\n     */\\n    function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n        // the target address contains contract code and also asserts for success in the low-level call.\\n\\n        bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n        if (returndata.length > 0) { // Return data is optional\\n            // solhint-disable-next-line max-line-length\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x8457e15aa90badabe0d6ef6f572f1ebd47bebf156921c825ae6e009dda15b706\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        // solhint-disable-next-line no-inline-assembly\\n        assembly { size := extcodesize(account) }\\n        return size > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n        (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain`call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n      return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        // solhint-disable-next-line avoid-low-level-calls\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return _verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            // Look for revert reason and bubble it up if present\\n            if (returndata.length > 0) {\\n                // The easiest way to bubble the revert reason is using memory via assembly\\n\\n                // solhint-disable-next-line no-inline-assembly\\n                assembly {\\n                    let returndata_size := mload(returndata)\\n                    revert(add(32, returndata), returndata_size)\\n                }\\n            } else {\\n                revert(errorMessage);\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xfc5ea91fa9ceb1961023b2a6c978b902888c52b90847ac7813fe3b79524165f6\",\"license\":\"MIT\"},\"contracts/StableJoeStaking.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.7.6;\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/SafeERC20Upgradeable.sol\\\";\\n\\n/**\\n * @title Stable JOE Staking\\n * @author Trader Joe\\n * @notice StableJoeStaking is a contract that allows JOE deposits and receives stablecoins sent by MoneyMaker's daily\\n * harvests. Users deposit JOE and receive a share of what has been sent by MoneyMaker based on their participation of\\n * the total deposited JOE. It is similar to a MasterChef, but we allow for claiming of different reward tokens\\n * (in case at some point we wish to change the stablecoin rewarded).\\n * Every time `updateReward(token)` is called, We distribute the balance of that tokens as rewards to users that are\\n * currently staking inside this contract, and they can claim it using `withdraw(0)`\\n */\\ncontract StableJoeStaking is Initializable, OwnableUpgradeable {\\n    using SafeMathUpgradeable for uint256;\\n    using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n    /// @notice Info of each user\\n    struct UserInfo {\\n        uint256 amount;\\n        mapping(IERC20Upgradeable => uint256) rewardDebt;\\n        /**\\n         * @notice We do some fancy math here. Basically, any point in time, the amount of JOEs\\n         * entitled to a user but is pending to be distributed is:\\n         *\\n         *   pending reward = (user.amount * accRewardPerShare) - user.rewardDebt[token]\\n         *\\n         * Whenever a user deposits or withdraws JOE. Here's what happens:\\n         *   1. accRewardPerShare (and `lastRewardBalance`) gets updated\\n         *   2. User receives the pending reward sent to his/her address\\n         *   3. User's `amount` gets updated\\n         *   4. User's `rewardDebt[token]` gets updated\\n         */\\n    }\\n\\n    IERC20Upgradeable public joe;\\n\\n    /// @dev Internal balance of JOE, this gets updated on user deposits / withdrawals\\n    /// this allows to reward users with JOE\\n    uint256 internalJoeBalance;\\n    /// @notice Array of tokens that users can claim\\n    IERC20Upgradeable[] public rewardTokens;\\n    mapping(IERC20Upgradeable => bool) public isRewardToken;\\n    /// @notice Last reward balance of `token`\\n    mapping(IERC20Upgradeable => uint256) public lastRewardBalance;\\n\\n    address public feeCollector;\\n\\n    /// @notice The deposit fee, scaled to `DEPOSIT_FEE_PERCENT_PRECISION`\\n    uint256 public depositFeePercent;\\n    /// @notice The precision of `depositFeePercent`\\n    uint256 public DEPOSIT_FEE_PERCENT_PRECISION;\\n\\n    /// @notice Accumulated `token` rewards per share, scaled to `ACC_REWARD_PER_SHARE_PRECISION`\\n    mapping(IERC20Upgradeable => uint256) public accRewardPerShare;\\n    /// @notice The precision of `accRewardPerShare`\\n    uint256 public ACC_REWARD_PER_SHARE_PRECISION;\\n\\n    /// @dev Info of each user that stakes JOE\\n    mapping(address => UserInfo) private userInfo;\\n\\n    /// @notice Emitted when a user deposits JOE\\n    event Deposit(address indexed user, uint256 amount, uint256 fee);\\n\\n    /// @notice Emitted when owner changes the deposit fee percentage\\n    event DepositFeeChanged(uint256 newFee, uint256 oldFee);\\n\\n    /// @notice Emitted when a user withdraws JOE\\n    event Withdraw(address indexed user, uint256 amount);\\n\\n    /// @notice Emitted when a user claims reward\\n    event ClaimReward(address indexed user, address indexed rewardToken, uint256 amount);\\n\\n    /// @notice Emitted when a user emergency withdraws its JOE\\n    event EmergencyWithdraw(address indexed user, uint256 amount);\\n\\n    /// @notice Emitted when owner adds a token to the reward tokens list\\n    event RewardTokenAdded(address token);\\n\\n    /// @notice Emitted when owner removes a token from the reward tokens list\\n    event RewardTokenRemoved(address token);\\n\\n    /**\\n     * @notice Initialize a new StableJoeStaking contract\\n     * @dev This contract needs to receive an ERC20 `_rewardToken` in order to distribute them\\n     * (with MoneyMaker in our case)\\n     * @param _rewardToken The address of the ERC20 reward token\\n     * @param _joe The address of the JOE token\\n     * @param _feeCollector The address where deposit fees will be sent\\n     * @param _depositFeePercent The deposit fee percent, scalled to 1e18, e.g. 3% is 3e16\\n     */\\n    function initialize(\\n        IERC20Upgradeable _rewardToken,\\n        IERC20Upgradeable _joe,\\n        address _feeCollector,\\n        uint256 _depositFeePercent\\n    ) external initializer {\\n        __Ownable_init();\\n        require(address(_rewardToken) != address(0), \\\"StableJoeStaking: reward token can't be address(0)\\\");\\n        require(address(_joe) != address(0), \\\"StableJoeStaking: joe can't be address(0)\\\");\\n        require(_feeCollector != address(0), \\\"StableJoeStaking: fee collector can't be address(0)\\\");\\n        require(_depositFeePercent <= 5e17, \\\"StableJoeStaking: max deposit fee can't be greater than 50%\\\");\\n\\n        joe = _joe;\\n        depositFeePercent = _depositFeePercent;\\n        feeCollector = _feeCollector;\\n\\n        isRewardToken[_rewardToken] = true;\\n        rewardTokens.push(_rewardToken);\\n        DEPOSIT_FEE_PERCENT_PRECISION = 1e18;\\n        ACC_REWARD_PER_SHARE_PRECISION = 1e24;\\n    }\\n\\n    /**\\n     * @notice Deposit JOE for reward token allocation\\n     * @param _amount The amount of JOE to deposit\\n     */\\n    function deposit(uint256 _amount) external {\\n        UserInfo storage user = userInfo[_msgSender()];\\n\\n        uint256 _fee = _amount.mul(depositFeePercent).div(DEPOSIT_FEE_PERCENT_PRECISION);\\n        uint256 _amountMinusFee = _amount.sub(_fee);\\n\\n        uint256 _previousAmount = user.amount;\\n        uint256 _newAmount = user.amount.add(_amountMinusFee);\\n        user.amount = _newAmount;\\n\\n        uint256 _len = rewardTokens.length;\\n        for (uint256 i; i < _len; i++) {\\n            IERC20Upgradeable _token = rewardTokens[i];\\n            updateReward(_token);\\n\\n            uint256 _previousRewardDebt = user.rewardDebt[_token];\\n            user.rewardDebt[_token] = _newAmount.mul(accRewardPerShare[_token]).div(ACC_REWARD_PER_SHARE_PRECISION);\\n\\n            if (_previousAmount != 0) {\\n                uint256 _pending = _previousAmount\\n                    .mul(accRewardPerShare[_token])\\n                    .div(ACC_REWARD_PER_SHARE_PRECISION)\\n                    .sub(_previousRewardDebt);\\n                if (_pending != 0) {\\n                    safeTokenTransfer(_token, _msgSender(), _pending);\\n                    emit ClaimReward(_msgSender(), address(_token), _pending);\\n                }\\n            }\\n        }\\n\\n        internalJoeBalance = internalJoeBalance.add(_amountMinusFee);\\n        joe.safeTransferFrom(_msgSender(), feeCollector, _fee);\\n        joe.safeTransferFrom(_msgSender(), address(this), _amountMinusFee);\\n        emit Deposit(_msgSender(), _amountMinusFee, _fee);\\n    }\\n\\n    /**\\n     * @notice Get user info\\n     * @param _user The address of the user\\n     * @param _rewardToken The address of the reward token\\n     * @return The amount of JOE user has deposited\\n     * @return The reward debt for the chosen token\\n     */\\n    function getUserInfo(address _user, IERC20Upgradeable _rewardToken) external view returns (uint256, uint256) {\\n        UserInfo storage user = userInfo[_user];\\n        return (user.amount, user.rewardDebt[_rewardToken]);\\n    }\\n\\n    /**\\n     * @notice Get the number of reward tokens\\n     * @return The length of the array\\n     */\\n    function rewardTokensLength() external view returns (uint256) {\\n        return rewardTokens.length;\\n    }\\n\\n    /**\\n     * @notice Add a reward token\\n     * @param _rewardToken The address of the reward token\\n     */\\n    function addRewardToken(IERC20Upgradeable _rewardToken) external onlyOwner {\\n        require(\\n            !isRewardToken[_rewardToken] && address(_rewardToken) != address(0),\\n            \\\"StableJoeStaking: token can't be added\\\"\\n        );\\n        require(rewardTokens.length < 25, \\\"StableJoeStaking: list of token too big\\\");\\n        rewardTokens.push(_rewardToken);\\n        isRewardToken[_rewardToken] = true;\\n        updateReward(_rewardToken);\\n        emit RewardTokenAdded(address(_rewardToken));\\n    }\\n\\n    /**\\n     * @notice Remove a reward token\\n     * @param _rewardToken The address of the reward token\\n     */\\n    function removeRewardToken(IERC20Upgradeable _rewardToken) external onlyOwner {\\n        require(isRewardToken[_rewardToken], \\\"StableJoeStaking: token can't be removed\\\");\\n        updateReward(_rewardToken);\\n        isRewardToken[_rewardToken] = false;\\n        uint256 _len = rewardTokens.length;\\n        for (uint256 i; i < _len; i++) {\\n            if (rewardTokens[i] == _rewardToken) {\\n                rewardTokens[i] = rewardTokens[_len - 1];\\n                rewardTokens.pop();\\n                break;\\n            }\\n        }\\n        emit RewardTokenRemoved(address(_rewardToken));\\n    }\\n\\n    /**\\n     * @notice Set the deposit fee percent\\n     * @param _depositFeePercent The new deposit fee percent\\n     */\\n    function setDepositFeePercent(uint256 _depositFeePercent) external onlyOwner {\\n        require(_depositFeePercent <= 5e17, \\\"StableJoeStaking: deposit fee can't be greater than 50%\\\");\\n        uint256 oldFee = depositFeePercent;\\n        depositFeePercent = _depositFeePercent;\\n        emit DepositFeeChanged(_depositFeePercent, oldFee);\\n    }\\n\\n    /**\\n     * @notice View function to see pending reward token on frontend\\n     * @param _user The address of the user\\n     * @param _token The address of the token\\n     * @return `_user`'s pending reward token\\n     */\\n    function pendingReward(address _user, IERC20Upgradeable _token) external view returns (uint256) {\\n        require(isRewardToken[_token], \\\"StableJoeStaking: wrong reward token\\\");\\n        UserInfo storage user = userInfo[_user];\\n        uint256 _totalJoe = internalJoeBalance;\\n        uint256 _accRewardTokenPerShare = accRewardPerShare[_token];\\n\\n        uint256 _currRewardBalance = _token.balanceOf(address(this));\\n        uint256 _rewardBalance = _token == joe ? _currRewardBalance.sub(_totalJoe) : _currRewardBalance;\\n\\n        if (_rewardBalance != lastRewardBalance[_token] && _totalJoe != 0) {\\n            uint256 _accruedReward = _rewardBalance.sub(lastRewardBalance[_token]);\\n            _accRewardTokenPerShare = _accRewardTokenPerShare.add(\\n                _accruedReward.mul(ACC_REWARD_PER_SHARE_PRECISION).div(_totalJoe)\\n            );\\n        }\\n        return\\n            user.amount.mul(_accRewardTokenPerShare).div(ACC_REWARD_PER_SHARE_PRECISION).sub(user.rewardDebt[_token]);\\n    }\\n\\n    /**\\n     * @notice Withdraw JOE and harvest the rewards\\n     * @param _amount The amount of JOE to withdraw\\n     */\\n    function withdraw(uint256 _amount) external {\\n        UserInfo storage user = userInfo[_msgSender()];\\n        uint256 _previousAmount = user.amount;\\n        require(_amount <= _previousAmount, \\\"StableJoeStaking: withdraw amount exceeds balance\\\");\\n        uint256 _newAmount = user.amount.sub(_amount);\\n        user.amount = _newAmount;\\n\\n        uint256 _len = rewardTokens.length;\\n        if (_previousAmount != 0) {\\n            for (uint256 i; i < _len; i++) {\\n                IERC20Upgradeable _token = rewardTokens[i];\\n                updateReward(_token);\\n\\n                uint256 _pending = _previousAmount\\n                    .mul(accRewardPerShare[_token])\\n                    .div(ACC_REWARD_PER_SHARE_PRECISION)\\n                    .sub(user.rewardDebt[_token]);\\n                user.rewardDebt[_token] = _newAmount.mul(accRewardPerShare[_token]).div(ACC_REWARD_PER_SHARE_PRECISION);\\n\\n                if (_pending != 0) {\\n                    safeTokenTransfer(_token, _msgSender(), _pending);\\n                    emit ClaimReward(_msgSender(), address(_token), _pending);\\n                }\\n            }\\n        }\\n\\n        internalJoeBalance = internalJoeBalance.sub(_amount);\\n        joe.safeTransfer(_msgSender(), _amount);\\n        emit Withdraw(_msgSender(), _amount);\\n    }\\n\\n    /**\\n     * @notice Withdraw without caring about rewards. EMERGENCY ONLY\\n     */\\n    function emergencyWithdraw() external {\\n        UserInfo storage user = userInfo[_msgSender()];\\n\\n        uint256 _amount = user.amount;\\n        user.amount = 0;\\n        uint256 _len = rewardTokens.length;\\n        for (uint256 i; i < _len; i++) {\\n            IERC20Upgradeable _token = rewardTokens[i];\\n            user.rewardDebt[_token] = 0;\\n        }\\n        joe.safeTransfer(_msgSender(), _amount);\\n        emit EmergencyWithdraw(_msgSender(), _amount);\\n    }\\n\\n    /**\\n     * @notice Update reward variables\\n     * @param _token The address of the reward token\\n     * @dev Needs to be called before any deposit or withdrawal\\n     */\\n    function updateReward(IERC20Upgradeable _token) public {\\n        require(isRewardToken[_token], \\\"StableJoeStaking: wrong reward token\\\");\\n\\n        uint256 _totalJoe = internalJoeBalance;\\n\\n        uint256 _currRewardBalance = _token.balanceOf(address(this));\\n        uint256 _rewardBalance = _token == joe ? _currRewardBalance.sub(_totalJoe) : _currRewardBalance;\\n\\n        // Did StableJoeStaking receive any token\\n        if (_rewardBalance == lastRewardBalance[_token] || _totalJoe == 0) {\\n            return;\\n        }\\n\\n        uint256 _accruedReward = _rewardBalance.sub(lastRewardBalance[_token]);\\n\\n        accRewardPerShare[_token] = accRewardPerShare[_token].add(\\n            _accruedReward.mul(ACC_REWARD_PER_SHARE_PRECISION).div(_totalJoe)\\n        );\\n        lastRewardBalance[_token] = _rewardBalance;\\n    }\\n\\n    /**\\n     * @notice Safe token transfer function, just in case if rounding error\\n     * causes pool to not have enough reward tokens\\n     * @param _token The address of then token to transfer\\n     * @param _to The address that will receive `_amount` `rewardToken`\\n     * @param _amount The amount to send to `_to`\\n     */\\n    function safeTokenTransfer(\\n        IERC20Upgradeable _token,\\n        address _to,\\n        uint256 _amount\\n    ) internal {\\n        uint256 _currRewardBalance = _token.balanceOf(address(this));\\n        uint256 _rewardBalance = _token == joe ? _currRewardBalance.sub(internalJoeBalance) : _currRewardBalance;\\n\\n        if (_amount > _rewardBalance) {\\n            lastRewardBalance[_token] = lastRewardBalance[_token].sub(_rewardBalance);\\n            _token.safeTransfer(_to, _rewardBalance);\\n        } else {\\n            lastRewardBalance[_token] = lastRewardBalance[_token].sub(_amount);\\n            _token.safeTransfer(_to, _amount);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xbdcd087cef629941eab10cf7989e457e5f415a6c79382ea5dc908e1447ab7145\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b50613b81806100206000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c80639ced7e76116100c3578063c415b95c1161007c578063c415b95c1461054e578063cc1252ae14610582578063cf756fdf146105a0578063db2e21bc1461062e578063f2801fe714610638578063f2fde38b146106b75761014d565b80639ced7e76146103de578063a610708a14610456578063b5fd73f814610474578063b6b55f25146104ce578063b985a3a0146104fc578063bf199e62146105305761014d565b80635dcea4d4116101155780635dcea4d4146102545780635fc0d9e0146102ac578063632447c914610304578063715018a6146103485780637bb7bed1146103525780638da5cb5b146103aa5761014d565b80631c03e6cc146101525780632052eb77146101965780632e1a7d4d146101c45780633c97d5ae146101f25780633d509c9714610210575b600080fd5b6101946004803603602081101561016857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506106fb565b005b6101c2600480360360208110156101ac57600080fd5b8101908080359060200190929190505050610a13565b005b6101f0600480360360208110156101da57600080fd5b8101908080359060200190929190505050610b8f565b005b6101fa610f8c565b6040518082815260200191505060405180910390f35b6102526004803603602081101561022657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f92565b005b6102966004803603602081101561026a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611313565b6040518082815260200191505060405180910390f35b6102ee600480360360208110156102c257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061132b565b6040518082815260200191505060405180910390f35b6103466004803603602081101561031a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611343565b005b6103506116bc565b005b61037e6004803603602081101561036857600080fd5b8101908080359060200190929190505050611847565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103b2611886565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610440600480360360408110156103f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506118b0565b6040518082815260200191505060405180910390f35b61045e611c6e565b6040518082815260200191505060405180910390f35b6104b66004803603602081101561048a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c74565b60405180821515815260200191505060405180910390f35b6104fa600480360360208110156104e457600080fd5b8101908080359060200190929190505050611c94565b005b610504612106565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61053861212c565b6040518082815260200191505060405180910390f35b610556612139565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61058a61215f565b6040518082815260200191505060405180910390f35b61062c600480360360808110156105b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612165565b005b6106366125c6565b005b61069a6004803603604081101561064e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612778565b604051808381526020018281526020019250505060405180910390f35b6106f9600480360360208110156106cd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612811565b005b610703612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615801561084c5750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b6108a1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613a2b6026913960400191505060405180910390fd5b6019606780549050106108ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806138bd6027913960400191505060405180910390fd5b6067819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506109c381611343565b7ff3e4c2c64e71e6ba2eaab9a599bced62f9eb91d2cda610bf41aa8c80ff2cf82681604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b610a1b612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610add576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6706f05b59d3b20000811115610b3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603781526020018061397d6037913960400191505060405180910390fd5b6000606b54905081606b819055507f6be5411ea11f30380402ca68832d060d744cbc5f62d2344495c10256ba93904a8282604051808381526020018281526020019250505060405180910390a15050565b6000606f6000610b9d612a21565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154905080831115610c3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526031815260200180613abe6031913960400191505060405180910390fd5b6000610c54848460000154612a2990919063ffffffff16565b90508083600001819055506000606780549050905060008314610ec15760005b81811015610ebf57600060678281548110610c8b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610cc181611343565b6000610d7c8760010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610d6e606e54610d60606d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548b612a7390919063ffffffff16565b612af990919063ffffffff16565b612a2990919063ffffffff16565b9050610de4606e54610dd6606d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205488612a7390919063ffffffff16565b612af990919063ffffffff16565b8760010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060008114610eb057610e4382610e3d612a21565b83612b43565b8173ffffffffffffffffffffffffffffffffffffffff16610e62612a21565b73ffffffffffffffffffffffffffffffffffffffff167f7e77f685b38c861064cb08f2776eb5dfd3c82f652ed9f21221b8c53b75628e51836040518082815260200191505060405180910390a35b50508080600101915050610c74565b505b610ed685606654612a2990919063ffffffff16565b606681905550610f30610ee7612a21565b86606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612df39092919063ffffffff16565b610f38612a21565b73ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364866040518082815260200191505060405180910390a25050505050565b606e5481565b610f9a612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461105c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806139e26028913960400191505060405180910390fd5b61110781611343565b6000606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000606780549050905060005b818110156112c1578273ffffffffffffffffffffffffffffffffffffffff166067828154811061119857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156112b457606760018303815481106111ef57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166067828154811061122757fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606780548061127a57fe5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590556112c1565b808060010191505061116c565b507f66257bcef574219c04f7c05f7a1c78d599da10491294c92a5805c48b4cdf500982604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b606d6020528060005260406000206000915090505481565b60696020528060005260406000206000915090505481565b606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166113e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806139596024913960400191505060405180910390fd5b6000606654905060008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561145557600080fd5b505afa158015611469573d6000803e3d6000fd5b505050506040513d602081101561147f57600080fd5b810190808051906020019092919050505090506000606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146114ef5781611503565b6115028383612a2990919063ffffffff16565b5b9050606960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548114806115525750600083145b1561155f575050506116b9565b60006115b3606960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483612a2990919063ffffffff16565b905061162d6115df856115d1606e5485612a7390919063ffffffff16565b612af990919063ffffffff16565b606d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612e9590919063ffffffff16565b606d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081606960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050505b50565b6116c4612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611786576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6067818154811061185757600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611954576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806139596024913960400191505060405180910390fd5b6000606f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600060665490506000606d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a4b57600080fd5b505afa158015611a5f573d6000803e3d6000fd5b505050506040513d6020811015611a7557600080fd5b810190808051906020019092919050505090506000606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614611ae55781611af9565b611af88483612a2990919063ffffffff16565b5b9050606960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548114158015611b4b575060008414155b15611be3576000611ba4606960008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483612a2990919063ffffffff16565b9050611bdf611bd086611bc2606e5485612a7390919063ffffffff16565b612af990919063ffffffff16565b85612e9590919063ffffffff16565b9350505b611c618560010160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611c53606e54611c45878a60000154612a7390919063ffffffff16565b612af990919063ffffffff16565b612a2990919063ffffffff16565b9550505050505092915050565b606c5481565b60686020528060005260406000206000915054906101000a900460ff1681565b6000606f6000611ca2612a21565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000611d09606c54611cfb606b5486612a7390919063ffffffff16565b612af990919063ffffffff16565b90506000611d208285612a2990919063ffffffff16565b90506000836000015490506000611d44838660000154612e9590919063ffffffff16565b90508085600001819055506000606780549050905060005b81811015611fb657600060678281548110611d7357fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050611da981611343565b60008860010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050611e55606e54611e47606d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205488612a7390919063ffffffff16565b612af990919063ffffffff16565b8960010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060008614611fa7576000611f1c82611f0e606e54611f00606d60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548c612a7390919063ffffffff16565b612af990919063ffffffff16565b612a2990919063ffffffff16565b905060008114611fa557611f3883611f32612a21565b83612b43565b8273ffffffffffffffffffffffffffffffffffffffff16611f57612a21565b73ffffffffffffffffffffffffffffffffffffffff167f7e77f685b38c861064cb08f2776eb5dfd3c82f652ed9f21221b8c53b75628e51836040518082815260200191505060405180910390a35b505b50508080600101915050611d5c565b50611fcc84606654612e9590919063ffffffff16565b60668190555061204a611fdd612a21565b606a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612f1d909392919063ffffffff16565b6120a0612055612a21565b3086606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612f1d909392919063ffffffff16565b6120a8612a21565b73ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158587604051808381526020018281526020019250505060405180910390a250505050505050565b606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000606780549050905090565b606a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606b5481565b600060019054906101000a900460ff16806121845750612183612fde565b5b8061219a575060008054906101000a900460ff16155b6121ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806139b4602e913960400191505060405180910390fd5b60008060019054906101000a900460ff16159050801561223f576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b612247612ff5565b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156122cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180613a8c6032913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612353576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061390a6029913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156123d9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526033815260200180613b196033913960400191505060405180910390fd5b6706f05b59d3b2000082111561243a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b815260200180613a51603b913960400191505060405180910390fd5b83606560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081606b8190555082606a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001606860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506067859080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550670de0b6b3a7640000606c8190555069d3c21bcecceda1000000606e8190555080156125bf5760008060016101000a81548160ff0219169083151502179055505b5050505050565b6000606f60006125d4612a21565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600001549050600082600001819055506000606780549050905060005b818110156126c95760006067828154811061264757fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008560010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550508080600101915050612630565b5061271e6126d5612a21565b83606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612df39092919063ffffffff16565b612726612a21565b73ffffffffffffffffffffffffffffffffffffffff167f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd9695836040518082815260200191505060405180910390a2505050565b6000806000606f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905080600001548160010160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205492509250509250929050565b612819612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146128db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612961576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806138e46026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b6000612a6b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613103565b905092915050565b600080831415612a865760009050612af3565b6000828402905082848281612a9757fe5b0414612aee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613a0a6021913960400191505060405180910390fd5b809150505b92915050565b6000612b3b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506131c3565b905092915050565b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612bac57600080fd5b505afa158015612bc0573d6000803e3d6000fd5b505050506040513d6020811015612bd657600080fd5b810190808051906020019092919050505090506000606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612c465781612c5c565b612c5b60665483612a2990919063ffffffff16565b5b905080831115612d2b57612cb881606960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612a2990919063ffffffff16565b606960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612d2684828773ffffffffffffffffffffffffffffffffffffffff16612df39092919063ffffffff16565b612dec565b612d7d83606960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612a2990919063ffffffff16565b606960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612deb84848773ffffffffffffffffffffffffffffffffffffffff16612df39092919063ffffffff16565b5b5050505050565b612e908363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613289565b505050565b600080828401905083811015612f13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b612fd8846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613289565b50505050565b6000803090506000813b9050600081149250505090565b600060019054906101000a900460ff16806130145750613013612fde565b5b8061302a575060008054906101000a900460ff16155b61307f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806139b4602e913960400191505060405180910390fd5b60008060019054906101000a900460ff1615905080156130cf576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b6130d7613378565b6130df613476565b80156131005760008060016101000a81548160ff0219169083151502179055505b50565b60008383111582906131b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561317557808201518184015260208101905061315a565b50505050905090810190601f1680156131a25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000808311829061326f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613234578082015181840152602081019050613219565b50505050905090810190601f1680156132615780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161327b57fe5b049050809150509392505050565b60006132eb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661361d9092919063ffffffff16565b90506000815111156133735780806020019051602081101561330c57600080fd5b8101908080519060200190929190505050613372576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613aef602a913960400191505060405180910390fd5b5b505050565b600060019054906101000a900460ff16806133975750613396612fde565b5b806133ad575060008054906101000a900460ff16155b613402576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806139b4602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015613452576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b80156134735760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff16806134955750613494612fde565b5b806134ab575060008054906101000a900460ff16155b613500576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806139b4602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015613550576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b600061355a612a21565b905080603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350801561361a5760008060016101000a81548160ff0219169083151502179055505b50565b606061362c8484600085613635565b90509392505050565b606082471015613690576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806139336026913960400191505060405180910390fd5b613699856137dd565b61370b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061375a5780518252602082019150602081019050602083039250613737565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146137bc576040519150601f19603f3d011682016040523d82523d6000602084013e6137c1565b606091505b50915091506137d18282866137f0565b92505050949350505050565b600080823b905060008111915050919050565b60608315613800578290506138b5565b6000835111156138135782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561387a57808201518184015260208101905061385f565b50505050905090810190601f1680156138a75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe537461626c654a6f655374616b696e673a206c697374206f6620746f6b656e20746f6f206269674f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373537461626c654a6f655374616b696e673a206a6f652063616e27742062652061646472657373283029416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c537461626c654a6f655374616b696e673a2077726f6e672072657761726420746f6b656e537461626c654a6f655374616b696e673a206465706f736974206665652063616e27742062652067726561746572207468616e20353025496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564537461626c654a6f655374616b696e673a20746f6b656e2063616e27742062652072656d6f766564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77537461626c654a6f655374616b696e673a20746f6b656e2063616e2774206265206164646564537461626c654a6f655374616b696e673a206d6178206465706f736974206665652063616e27742062652067726561746572207468616e20353025537461626c654a6f655374616b696e673a2072657761726420746f6b656e2063616e27742062652061646472657373283029537461626c654a6f655374616b696e673a20776974686472617720616d6f756e7420657863656564732062616c616e63655361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564537461626c654a6f655374616b696e673a2066656520636f6c6c6563746f722063616e27742062652061646472657373283029a264697066735822122081118658bc6fd7c6ddd272a224d356b4c41e9ba77e42825488ca0942d4f54f9764736f6c63430007060033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061014d5760003560e01c80639ced7e76116100c3578063c415b95c1161007c578063c415b95c1461054e578063cc1252ae14610582578063cf756fdf146105a0578063db2e21bc1461062e578063f2801fe714610638578063f2fde38b146106b75761014d565b80639ced7e76146103de578063a610708a14610456578063b5fd73f814610474578063b6b55f25146104ce578063b985a3a0146104fc578063bf199e62146105305761014d565b80635dcea4d4116101155780635dcea4d4146102545780635fc0d9e0146102ac578063632447c914610304578063715018a6146103485780637bb7bed1146103525780638da5cb5b146103aa5761014d565b80631c03e6cc146101525780632052eb77146101965780632e1a7d4d146101c45780633c97d5ae146101f25780633d509c9714610210575b600080fd5b6101946004803603602081101561016857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506106fb565b005b6101c2600480360360208110156101ac57600080fd5b8101908080359060200190929190505050610a13565b005b6101f0600480360360208110156101da57600080fd5b8101908080359060200190929190505050610b8f565b005b6101fa610f8c565b6040518082815260200191505060405180910390f35b6102526004803603602081101561022657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f92565b005b6102966004803603602081101561026a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611313565b6040518082815260200191505060405180910390f35b6102ee600480360360208110156102c257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061132b565b6040518082815260200191505060405180910390f35b6103466004803603602081101561031a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611343565b005b6103506116bc565b005b61037e6004803603602081101561036857600080fd5b8101908080359060200190929190505050611847565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103b2611886565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610440600480360360408110156103f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506118b0565b6040518082815260200191505060405180910390f35b61045e611c6e565b6040518082815260200191505060405180910390f35b6104b66004803603602081101561048a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c74565b60405180821515815260200191505060405180910390f35b6104fa600480360360208110156104e457600080fd5b8101908080359060200190929190505050611c94565b005b610504612106565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61053861212c565b6040518082815260200191505060405180910390f35b610556612139565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61058a61215f565b6040518082815260200191505060405180910390f35b61062c600480360360808110156105b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612165565b005b6106366125c6565b005b61069a6004803603604081101561064e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612778565b604051808381526020018281526020019250505060405180910390f35b6106f9600480360360208110156106cd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612811565b005b610703612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615801561084c5750600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b6108a1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613a2b6026913960400191505060405180910390fd5b6019606780549050106108ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806138bd6027913960400191505060405180910390fd5b6067819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506109c381611343565b7ff3e4c2c64e71e6ba2eaab9a599bced62f9eb91d2cda610bf41aa8c80ff2cf82681604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b610a1b612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610add576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6706f05b59d3b20000811115610b3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603781526020018061397d6037913960400191505060405180910390fd5b6000606b54905081606b819055507f6be5411ea11f30380402ca68832d060d744cbc5f62d2344495c10256ba93904a8282604051808381526020018281526020019250505060405180910390a15050565b6000606f6000610b9d612a21565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000154905080831115610c3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526031815260200180613abe6031913960400191505060405180910390fd5b6000610c54848460000154612a2990919063ffffffff16565b90508083600001819055506000606780549050905060008314610ec15760005b81811015610ebf57600060678281548110610c8b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610cc181611343565b6000610d7c8760010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610d6e606e54610d60606d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548b612a7390919063ffffffff16565b612af990919063ffffffff16565b612a2990919063ffffffff16565b9050610de4606e54610dd6606d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205488612a7390919063ffffffff16565b612af990919063ffffffff16565b8760010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060008114610eb057610e4382610e3d612a21565b83612b43565b8173ffffffffffffffffffffffffffffffffffffffff16610e62612a21565b73ffffffffffffffffffffffffffffffffffffffff167f7e77f685b38c861064cb08f2776eb5dfd3c82f652ed9f21221b8c53b75628e51836040518082815260200191505060405180910390a35b50508080600101915050610c74565b505b610ed685606654612a2990919063ffffffff16565b606681905550610f30610ee7612a21565b86606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612df39092919063ffffffff16565b610f38612a21565b73ffffffffffffffffffffffffffffffffffffffff167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364866040518082815260200191505060405180910390a25050505050565b606e5481565b610f9a612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461105c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166110fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806139e26028913960400191505060405180910390fd5b61110781611343565b6000606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506000606780549050905060005b818110156112c1578273ffffffffffffffffffffffffffffffffffffffff166067828154811061119857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156112b457606760018303815481106111ef57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166067828154811061122757fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606780548061127a57fe5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590556112c1565b808060010191505061116c565b507f66257bcef574219c04f7c05f7a1c78d599da10491294c92a5805c48b4cdf500982604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b606d6020528060005260406000206000915090505481565b60696020528060005260406000206000915090505481565b606860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166113e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806139596024913960400191505060405180910390fd5b6000606654905060008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561145557600080fd5b505afa158015611469573d6000803e3d6000fd5b505050506040513d602081101561147f57600080fd5b810190808051906020019092919050505090506000606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146114ef5781611503565b6115028383612a2990919063ffffffff16565b5b9050606960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548114806115525750600083145b1561155f575050506116b9565b60006115b3606960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483612a2990919063ffffffff16565b905061162d6115df856115d1606e5485612a7390919063ffffffff16565b612af990919063ffffffff16565b606d60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612e9590919063ffffffff16565b606d60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555081606960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050505b50565b6116c4612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611786576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6067818154811061185757600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000606860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611954576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806139596024913960400191505060405180910390fd5b6000606f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600060665490506000606d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905060008573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a4b57600080fd5b505afa158015611a5f573d6000803e3d6000fd5b505050506040513d6020811015611a7557600080fd5b810190808051906020019092919050505090506000606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614611ae55781611af9565b611af88483612a2990919063ffffffff16565b5b9050606960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548114158015611b4b575060008414155b15611be3576000611ba4606960008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483612a2990919063ffffffff16565b9050611bdf611bd086611bc2606e5485612a7390919063ffffffff16565b612af990919063ffffffff16565b85612e9590919063ffffffff16565b9350505b611c618560010160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054611c53606e54611c45878a60000154612a7390919063ffffffff16565b612af990919063ffffffff16565b612a2990919063ffffffff16565b9550505050505092915050565b606c5481565b60686020528060005260406000206000915054906101000a900460ff1681565b6000606f6000611ca2612a21565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000611d09606c54611cfb606b5486612a7390919063ffffffff16565b612af990919063ffffffff16565b90506000611d208285612a2990919063ffffffff16565b90506000836000015490506000611d44838660000154612e9590919063ffffffff16565b90508085600001819055506000606780549050905060005b81811015611fb657600060678281548110611d7357fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050611da981611343565b60008860010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050611e55606e54611e47606d60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205488612a7390919063ffffffff16565b612af990919063ffffffff16565b8960010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060008614611fa7576000611f1c82611f0e606e54611f00606d60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548c612a7390919063ffffffff16565b612af990919063ffffffff16565b612a2990919063ffffffff16565b905060008114611fa557611f3883611f32612a21565b83612b43565b8273ffffffffffffffffffffffffffffffffffffffff16611f57612a21565b73ffffffffffffffffffffffffffffffffffffffff167f7e77f685b38c861064cb08f2776eb5dfd3c82f652ed9f21221b8c53b75628e51836040518082815260200191505060405180910390a35b505b50508080600101915050611d5c565b50611fcc84606654612e9590919063ffffffff16565b60668190555061204a611fdd612a21565b606a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1687606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612f1d909392919063ffffffff16565b6120a0612055612a21565b3086606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612f1d909392919063ffffffff16565b6120a8612a21565b73ffffffffffffffffffffffffffffffffffffffff167f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a158587604051808381526020018281526020019250505060405180910390a250505050505050565b606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000606780549050905090565b606a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606b5481565b600060019054906101000a900460ff16806121845750612183612fde565b5b8061219a575060008054906101000a900460ff16155b6121ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806139b4602e913960400191505060405180910390fd5b60008060019054906101000a900460ff16159050801561223f576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b612247612ff5565b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156122cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180613a8c6032913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415612353576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061390a6029913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156123d9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526033815260200180613b196033913960400191505060405180910390fd5b6706f05b59d3b2000082111561243a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b815260200180613a51603b913960400191505060405180910390fd5b83606560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081606b8190555082606a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001606860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506067859080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550670de0b6b3a7640000606c8190555069d3c21bcecceda1000000606e8190555080156125bf5760008060016101000a81548160ff0219169083151502179055505b5050505050565b6000606f60006125d4612a21565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600001549050600082600001819055506000606780549050905060005b818110156126c95760006067828154811061264757fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008560010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550508080600101915050612630565b5061271e6126d5612a21565b83606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612df39092919063ffffffff16565b612726612a21565b73ffffffffffffffffffffffffffffffffffffffff167f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd9695836040518082815260200191505060405180910390a2505050565b6000806000606f60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905080600001548160010160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205492509250509250929050565b612819612a21565b73ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146128db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612961576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806138e46026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b6000612a6b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613103565b905092915050565b600080831415612a865760009050612af3565b6000828402905082848281612a9757fe5b0414612aee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613a0a6021913960400191505060405180910390fd5b809150505b92915050565b6000612b3b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506131c3565b905092915050565b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612bac57600080fd5b505afa158015612bc0573d6000803e3d6000fd5b505050506040513d6020811015612bd657600080fd5b810190808051906020019092919050505090506000606560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612c465781612c5c565b612c5b60665483612a2990919063ffffffff16565b5b905080831115612d2b57612cb881606960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612a2990919063ffffffff16565b606960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612d2684828773ffffffffffffffffffffffffffffffffffffffff16612df39092919063ffffffff16565b612dec565b612d7d83606960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612a2990919063ffffffff16565b606960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612deb84848773ffffffffffffffffffffffffffffffffffffffff16612df39092919063ffffffff16565b5b5050505050565b612e908363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613289565b505050565b600080828401905083811015612f13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b612fd8846323b872dd60e01b858585604051602401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613289565b50505050565b6000803090506000813b9050600081149250505090565b600060019054906101000a900460ff16806130145750613013612fde565b5b8061302a575060008054906101000a900460ff16155b61307f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806139b4602e913960400191505060405180910390fd5b60008060019054906101000a900460ff1615905080156130cf576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b6130d7613378565b6130df613476565b80156131005760008060016101000a81548160ff0219169083151502179055505b50565b60008383111582906131b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561317557808201518184015260208101905061315a565b50505050905090810190601f1680156131a25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000808311829061326f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613234578082015181840152602081019050613219565b50505050905090810190601f1680156132615780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161327b57fe5b049050809150509392505050565b60006132eb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661361d9092919063ffffffff16565b90506000815111156133735780806020019051602081101561330c57600080fd5b8101908080519060200190929190505050613372576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613aef602a913960400191505060405180910390fd5b5b505050565b600060019054906101000a900460ff16806133975750613396612fde565b5b806133ad575060008054906101000a900460ff16155b613402576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806139b4602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015613452576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b80156134735760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff16806134955750613494612fde565b5b806134ab575060008054906101000a900460ff16155b613500576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806139b4602e913960400191505060405180910390fd5b60008060019054906101000a900460ff161590508015613550576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b600061355a612a21565b905080603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350801561361a5760008060016101000a81548160ff0219169083151502179055505b50565b606061362c8484600085613635565b90509392505050565b606082471015613690576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806139336026913960400191505060405180910390fd5b613699856137dd565b61370b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061375a5780518252602082019150602081019050602083039250613737565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146137bc576040519150601f19603f3d011682016040523d82523d6000602084013e6137c1565b606091505b50915091506137d18282866137f0565b92505050949350505050565b600080823b905060008111915050919050565b60608315613800578290506138b5565b6000835111156138135782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561387a57808201518184015260208101905061385f565b50505050905090810190601f1680156138a75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe537461626c654a6f655374616b696e673a206c697374206f6620746f6b656e20746f6f206269674f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373537461626c654a6f655374616b696e673a206a6f652063616e27742062652061646472657373283029416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c537461626c654a6f655374616b696e673a2077726f6e672072657761726420746f6b656e537461626c654a6f655374616b696e673a206465706f736974206665652063616e27742062652067726561746572207468616e20353025496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564537461626c654a6f655374616b696e673a20746f6b656e2063616e27742062652072656d6f766564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77537461626c654a6f655374616b696e673a20746f6b656e2063616e2774206265206164646564537461626c654a6f655374616b696e673a206d6178206465706f736974206665652063616e27742062652067726561746572207468616e20353025537461626c654a6f655374616b696e673a2072657761726420746f6b656e2063616e27742062652061646472657373283029537461626c654a6f655374616b696e673a20776974686472617720616d6f756e7420657863656564732062616c616e63655361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564537461626c654a6f655374616b696e673a2066656520636f6c6c6563746f722063616e27742062652061646472657373283029a264697066735822122081118658bc6fd7c6ddd272a224d356b4c41e9ba77e42825488ca0942d4f54f9764736f6c63430007060033",
  "devdoc": {
    "author": "Trader Joe",
    "kind": "dev",
    "methods": {
      "addRewardToken(address)": {
        "params": {
          "_rewardToken": "The address of the reward token"
        }
      },
      "deposit(uint256)": {
        "params": {
          "_amount": "The amount of JOE to deposit"
        }
      },
      "getUserInfo(address,address)": {
        "params": {
          "_rewardToken": "The address of the reward token",
          "_user": "The address of the user"
        },
        "returns": {
          "_0": "The amount of JOE user has deposited",
          "_1": "The reward debt for the chosen token"
        }
      },
      "initialize(address,address,address,uint256)": {
        "details": "This contract needs to receive an ERC20 `_rewardToken` in order to distribute them (with MoneyMaker in our case)",
        "params": {
          "_depositFeePercent": "The deposit fee percent, scalled to 1e18, e.g. 3% is 3e16",
          "_feeCollector": "The address where deposit fees will be sent",
          "_joe": "The address of the JOE token",
          "_rewardToken": "The address of the ERC20 reward token"
        }
      },
      "owner()": {
        "details": "Returns the address of the current owner."
      },
      "pendingReward(address,address)": {
        "params": {
          "_token": "The address of the token",
          "_user": "The address of the user"
        },
        "returns": {
          "_0": "`_user`'s pending reward token"
        }
      },
      "removeRewardToken(address)": {
        "params": {
          "_rewardToken": "The address of the reward token"
        }
      },
      "renounceOwnership()": {
        "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner."
      },
      "rewardTokensLength()": {
        "returns": {
          "_0": "The length of the array"
        }
      },
      "setDepositFeePercent(uint256)": {
        "params": {
          "_depositFeePercent": "The new deposit fee percent"
        }
      },
      "transferOwnership(address)": {
        "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."
      },
      "updateReward(address)": {
        "details": "Needs to be called before any deposit or withdrawal",
        "params": {
          "_token": "The address of the reward token"
        }
      },
      "withdraw(uint256)": {
        "params": {
          "_amount": "The amount of JOE to withdraw"
        }
      }
    },
    "stateVariables": {
      "internalJoeBalance": {
        "details": "Internal balance of JOE, this gets updated on user deposits / withdrawals this allows to reward users with JOE"
      },
      "userInfo": {
        "details": "Info of each user that stakes JOE"
      }
    },
    "title": "Stable JOE Staking",
    "version": 1
  },
  "userdoc": {
    "events": {
      "ClaimReward(address,address,uint256)": {
        "notice": "Emitted when a user claims reward"
      },
      "Deposit(address,uint256,uint256)": {
        "notice": "Emitted when a user deposits JOE"
      },
      "DepositFeeChanged(uint256,uint256)": {
        "notice": "Emitted when owner changes the deposit fee percentage"
      },
      "EmergencyWithdraw(address,uint256)": {
        "notice": "Emitted when a user emergency withdraws its JOE"
      },
      "RewardTokenAdded(address)": {
        "notice": "Emitted when owner adds a token to the reward tokens list"
      },
      "RewardTokenRemoved(address)": {
        "notice": "Emitted when owner removes a token from the reward tokens list"
      },
      "Withdraw(address,uint256)": {
        "notice": "Emitted when a user withdraws JOE"
      }
    },
    "kind": "user",
    "methods": {
      "ACC_REWARD_PER_SHARE_PRECISION()": {
        "notice": "The precision of `accRewardPerShare`"
      },
      "DEPOSIT_FEE_PERCENT_PRECISION()": {
        "notice": "The precision of `depositFeePercent`"
      },
      "accRewardPerShare(address)": {
        "notice": "Accumulated `token` rewards per share, scaled to `ACC_REWARD_PER_SHARE_PRECISION`"
      },
      "addRewardToken(address)": {
        "notice": "Add a reward token"
      },
      "deposit(uint256)": {
        "notice": "Deposit JOE for reward token allocation"
      },
      "depositFeePercent()": {
        "notice": "The deposit fee, scaled to `DEPOSIT_FEE_PERCENT_PRECISION`"
      },
      "emergencyWithdraw()": {
        "notice": "Withdraw without caring about rewards. EMERGENCY ONLY"
      },
      "getUserInfo(address,address)": {
        "notice": "Get user info"
      },
      "initialize(address,address,address,uint256)": {
        "notice": "Initialize a new StableJoeStaking contract"
      },
      "lastRewardBalance(address)": {
        "notice": "Last reward balance of `token`"
      },
      "pendingReward(address,address)": {
        "notice": "View function to see pending reward token on frontend"
      },
      "removeRewardToken(address)": {
        "notice": "Remove a reward token"
      },
      "rewardTokens(uint256)": {
        "notice": "Array of tokens that users can claim"
      },
      "rewardTokensLength()": {
        "notice": "Get the number of reward tokens"
      },
      "setDepositFeePercent(uint256)": {
        "notice": "Set the deposit fee percent"
      },
      "updateReward(address)": {
        "notice": "Update reward variables"
      },
      "withdraw(uint256)": {
        "notice": "Withdraw JOE and harvest the rewards"
      }
    },
    "notice": "StableJoeStaking is a contract that allows JOE deposits and receives stablecoins sent by MoneyMaker's daily harvests. Users deposit JOE and receive a share of what has been sent by MoneyMaker based on their participation of the total deposited JOE. It is similar to a MasterChef, but we allow for claiming of different reward tokens (in case at some point we wish to change the stablecoin rewarded). Every time `updateReward(token)` is called, We distribute the balance of that tokens as rewards to users that are currently staking inside this contract, and they can claim it using `withdraw(0)`",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 376,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "_initialized",
        "offset": 0,
        "slot": "0",
        "type": "t_bool"
      },
      {
        "astId": 379,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "_initializing",
        "offset": 1,
        "slot": "0",
        "type": "t_bool"
      },
      {
        "astId": 43,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "__gap",
        "offset": 0,
        "slot": "1",
        "type": "t_array(t_uint256)50_storage"
      },
      {
        "astId": 55,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "_owner",
        "offset": 0,
        "slot": "51",
        "type": "t_address"
      },
      {
        "astId": 173,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "__gap",
        "offset": 0,
        "slot": "52",
        "type": "t_array(t_uint256)49_storage"
      },
      {
        "astId": 3783,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "joe",
        "offset": 0,
        "slot": "101",
        "type": "t_contract(IERC20Upgradeable)519"
      },
      {
        "astId": 3786,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "internalJoeBalance",
        "offset": 0,
        "slot": "102",
        "type": "t_uint256"
      },
      {
        "astId": 3790,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "rewardTokens",
        "offset": 0,
        "slot": "103",
        "type": "t_array(t_contract(IERC20Upgradeable)519)dyn_storage"
      },
      {
        "astId": 3794,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "isRewardToken",
        "offset": 0,
        "slot": "104",
        "type": "t_mapping(t_contract(IERC20Upgradeable)519,t_bool)"
      },
      {
        "astId": 3799,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "lastRewardBalance",
        "offset": 0,
        "slot": "105",
        "type": "t_mapping(t_contract(IERC20Upgradeable)519,t_uint256)"
      },
      {
        "astId": 3801,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "feeCollector",
        "offset": 0,
        "slot": "106",
        "type": "t_address"
      },
      {
        "astId": 3804,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "depositFeePercent",
        "offset": 0,
        "slot": "107",
        "type": "t_uint256"
      },
      {
        "astId": 3807,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "DEPOSIT_FEE_PERCENT_PRECISION",
        "offset": 0,
        "slot": "108",
        "type": "t_uint256"
      },
      {
        "astId": 3812,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "accRewardPerShare",
        "offset": 0,
        "slot": "109",
        "type": "t_mapping(t_contract(IERC20Upgradeable)519,t_uint256)"
      },
      {
        "astId": 3815,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "ACC_REWARD_PER_SHARE_PRECISION",
        "offset": 0,
        "slot": "110",
        "type": "t_uint256"
      },
      {
        "astId": 3820,
        "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
        "label": "userInfo",
        "offset": 0,
        "slot": "111",
        "type": "t_mapping(t_address,t_struct(UserInfo)3781_storage)"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_array(t_contract(IERC20Upgradeable)519)dyn_storage": {
        "base": "t_contract(IERC20Upgradeable)519",
        "encoding": "dynamic_array",
        "label": "contract IERC20Upgradeable[]",
        "numberOfBytes": "32"
      },
      "t_array(t_uint256)49_storage": {
        "base": "t_uint256",
        "encoding": "inplace",
        "label": "uint256[49]",
        "numberOfBytes": "1568"
      },
      "t_array(t_uint256)50_storage": {
        "base": "t_uint256",
        "encoding": "inplace",
        "label": "uint256[50]",
        "numberOfBytes": "1600"
      },
      "t_bool": {
        "encoding": "inplace",
        "label": "bool",
        "numberOfBytes": "1"
      },
      "t_contract(IERC20Upgradeable)519": {
        "encoding": "inplace",
        "label": "contract IERC20Upgradeable",
        "numberOfBytes": "20"
      },
      "t_mapping(t_address,t_struct(UserInfo)3781_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct StableJoeStaking.UserInfo)",
        "numberOfBytes": "32",
        "value": "t_struct(UserInfo)3781_storage"
      },
      "t_mapping(t_contract(IERC20Upgradeable)519,t_bool)": {
        "encoding": "mapping",
        "key": "t_contract(IERC20Upgradeable)519",
        "label": "mapping(contract IERC20Upgradeable => bool)",
        "numberOfBytes": "32",
        "value": "t_bool"
      },
      "t_mapping(t_contract(IERC20Upgradeable)519,t_uint256)": {
        "encoding": "mapping",
        "key": "t_contract(IERC20Upgradeable)519",
        "label": "mapping(contract IERC20Upgradeable => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_struct(UserInfo)3781_storage": {
        "encoding": "inplace",
        "label": "struct StableJoeStaking.UserInfo",
        "members": [
          {
            "astId": 3776,
            "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
            "label": "amount",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          },
          {
            "astId": 3780,
            "contract": "contracts/StableJoeStaking.sol:StableJoeStaking",
            "label": "rewardDebt",
            "offset": 0,
            "slot": "1",
            "type": "t_mapping(t_contract(IERC20Upgradeable)519,t_uint256)"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      }
    }
  }
}