{"compiler":{"version":"0.8.4+commit.c7e474f2"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"_want","type":"address"},{"internalType":"address","name":"_chef","type":"address"},{"components":[{"internalType":"address","name":"keeper","type":"address"},{"internalType":"address","name":"strategist","type":"address"},{"internalType":"address","name":"unirouter","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"harvester","type":"address"},{"internalType":"address","name":"autocompFeeRecipient","type":"address"}],"internalType":"struct StratManager.StratMgr","name":"stratMgr","type":"tuple"},{"internalType":"address[]","name":"_outputToNativeRoute","type":"address[]"},{"internalType":"address[]","name":"_outputToLp0Route","type":"address[]"},{"internalType":"address[]","name":"_outputToLp1Route","type":"address[]"},{"internalType":"address[]","name":"_output2ToOutputRoute","type":"address[]"},{"internalType":"address[]","name":"_output3ToOutputRoute","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"harvester","type":"address"}],"name":"StratHarvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountInMax","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"path","type":"address[]"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"_SafeSwap","type":"event"},{"inputs":[],"name":"MAX_CALL_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STRATEGIST_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAWAL_FEE_CAP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WITHDRAWAL_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"autocompFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"autocompFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOfPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOfWant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beforeDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"callFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chef","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvestOnDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"callFeeRecipient","type":"address"}],"name":"harvestWithCallFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"harvester","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastHarvest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpToken0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpToken1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managerHarvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"native","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"output","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"output2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"output2ToOutputRoute","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"output3","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"output3ToOutputRoute","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"outputToLp0Route","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"outputToLp1Route","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"outputToNativeRoute","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"panic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"retireStrat","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_autocompFeeRecipient","type":"address"}],"name":"setAutocompFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setCallFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_harvestOnDeposit","type":"bool"}],"name":"setHarvestOnDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_harvester","type":"address"}],"name":"setHarvester","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"setKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategist","type":"address"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_unirouter","type":"address"}],"name":"setUnirouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"setVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setWithdrawalFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unirouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"want","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"devdoc":{"events":{"_SafeSwap(uint256,uint256,address[],address,uint256)":{"details":"Event that is fired each time someone harvests the strat."}},"kind":"dev","methods":{"beforeDeposit()":{"details":"Function to synchronize balances before new user deposit. Can be overridden in the strategy."},"owner()":{"details":"Returns the address of the current owner."},"paused()":{"details":"Returns true if the contract is paused, and false otherwise."},"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."},"setAutocompFeeRecipient(address)":{"details":"Updates autocomp fee recipient.","params":{"_autocompFeeRecipient":"new autocomp fee recipient address."}},"setHarvester(address)":{"details":"Updates address of the strat harvester.","params":{"_harvester":"new harvester address."}},"setKeeper(address)":{"details":"Updates address of the strat keeper.","params":{"_keeper":"new keeper address."}},"setStrategist(address)":{"details":"Updates address where strategist fee earnings will go.","params":{"_strategist":"new strategist address."}},"setUnirouter(address)":{"details":"Updates router that will be used for swaps.","params":{"_unirouter":"new unirouter address."}},"setVault(address)":{"details":"Updates parent vault.","params":{"_vault":"new vault address."}},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."}},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"contracts/ACFI/strategies/ubeswap/StrategyStakingTripleRewardLP.sol":"StrategyStakingTripleRewardLP"},"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs","useLiteralContent":true},"optimizer":{"enabled":true,"runs":200},"remappings":[]},"sources":{"@openzeppelin/contracts/access/Ownable.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\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 Ownable is Context {\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    constructor() {\n        _setOwner(_msgSender());\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual 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        _setOwner(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        _setOwner(newOwner);\n    }\n\n    function _setOwner(address newOwner) private {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n","keccak256":"0x6bb804a310218875e89d12c053e94a13a4607cdf7cc2052f3e52bd32a0dc50a1","license":"MIT"},"@openzeppelin/contracts/security/Pausable.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        require(!paused(), \"Pausable: paused\");\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        require(paused(), \"Pausable: not paused\");\n        _;\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n","keccak256":"0xa35b1f2a670cd2a701a52c398032c9fed72df1909fe394d77ceacbf074e8937b","license":"MIT"},"@openzeppelin/contracts/token/ERC20/ERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * The default value of {decimals} is 18. To select a different value for\n     * {decimals} you should overload it.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\n     * overridden;\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `recipient` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n        _transfer(_msgSender(), recipient, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        _approve(_msgSender(), spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * Requirements:\n     *\n     * - `sender` and `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``sender``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) public virtual override returns (bool) {\n        _transfer(sender, recipient, amount);\n\n        uint256 currentAllowance = _allowances[sender][_msgSender()];\n        require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n        unchecked {\n            _approve(sender, _msgSender(), currentAllowance - amount);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        uint256 currentAllowance = _allowances[_msgSender()][spender];\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `sender` to `recipient`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `sender` cannot be the zero address.\n     * - `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     */\n    function _transfer(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) internal virtual {\n        require(sender != address(0), \"ERC20: transfer from the zero address\");\n        require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(sender, recipient, amount);\n\n        uint256 senderBalance = _balances[sender];\n        require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[sender] = senderBalance - amount;\n        }\n        _balances[recipient] += amount;\n\n        emit Transfer(sender, recipient, amount);\n\n        _afterTokenTransfer(sender, recipient, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        _balances[account] += amount;\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n        }\n        _totalSupply -= amount;\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n}\n","keccak256":"0xb03df8481a954604ad0c9125680893b2e3f7ff770fe470e38b89ac61b84e8072","license":"MIT"},"@openzeppelin/contracts/token/ERC20/IERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\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(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) 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":"0x027b891937d20ccf213fdb9c31531574256de774bda99d3a70ecef6e1913ed2a","license":"MIT"},"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n","keccak256":"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2","license":"MIT"},"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.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 SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) 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(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) 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        require(\n            (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(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\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(IERC20 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) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n","keccak256":"0x02348b2e4b9f3200c7e3907c5c2661643a6d8520e9f79939fbb9b4005a54894d","license":"MIT"},"@openzeppelin/contracts/utils/Address.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\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        assembly {\n            size := extcodesize(account)\n        }\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        (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(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) 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(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) 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(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) 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        (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(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal 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                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":"0x3336baae5cf23e94274d75336e2d412193be508504aee185e61dc7d58cd05c8a","license":"MIT"},"@openzeppelin/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\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 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 Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n","keccak256":"0x90565a39ae45c80f0468dc96c7b20d0afc3055f344c8203a0c9258239f350b9f","license":"MIT"},"@openzeppelin/contracts/utils/math/SafeMath.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\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) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\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        return a + b;\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 a - b;\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        return a * b;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator.\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting 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 a % b;\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     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {trySub}.\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(\n        uint256 a,\n        uint256 b,\n        string memory errorMessage\n    ) internal pure returns (uint256) {\n        unchecked {\n            require(b <= a, errorMessage);\n            return a - b;\n        }\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting 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(\n        uint256 a,\n        uint256 b,\n        string memory errorMessage\n    ) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a / b;\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting with custom message when dividing by zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryMod}.\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(\n        uint256 a,\n        uint256 b,\n        string memory errorMessage\n    ) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a % b;\n        }\n    }\n}\n","keccak256":"0x8666f020bd8fc9dc14f07e2ebc52b5f236ab4cdde7c77679b08cb2f94730043b","license":"MIT"},"contracts/ACFI/interfaces/common/IUniswapRouterETH.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.9.0;\n\ninterface IUniswapRouterETH {\n    function addLiquidity(\n        address tokenA,\n        address tokenB,\n        uint amountADesired,\n        uint amountBDesired,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountA, uint amountB, uint liquidity);\n\n    function addLiquidityETH(\n        address token,\n        uint amountTokenDesired,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);\n\n    function removeLiquidity(\n        address tokenA,\n        address tokenB,\n        uint liquidity,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountA, uint amountB);\n\n    function removeLiquidityETH(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountToken, uint amountETH);\n\n    function swapExactTokensForTokens(\n        uint amountIn, \n        uint amountOutMin, \n        address[] calldata path, \n        address to, \n        uint deadline\n    ) external returns (uint[] memory amounts);\n\n    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)\n        external\n        payable\n        returns (uint[] memory amounts);\n    \n    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)\n        external\n        returns (uint[] memory amounts);\n\n    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);\n}","keccak256":"0x294fdb0ecd8652b64f478e5c7ce2ed22ad637699248af719f306f50032752439","license":"MIT"},"contracts/ACFI/interfaces/common/IUniswapV2Pair.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IUniswapV2Pair {\n  function factory() external view returns (address);\n\n  function token0() external view returns (address);\n\n  function token1() external view returns (address);\n\n  function burn(address to) external returns (uint256 amount0, uint256 amount1);\n\n  function getReserves()\n    external\n    view\n    returns (\n      uint112 reserve0,\n      uint112 reserve1,\n      uint32 blockTimestampLast\n    );\n}\n","keccak256":"0x92f2ba60a649cca76a07c4e68cfec6e234511fb8af7b310c561d346875e551ad","license":"MIT"},"contracts/ACFI/interfaces/synthetix/IStakingRewards.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n// import \"../../../openzeppelin-solidity/contracts/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n// https://docs.synthetix.io/contracts/source/interfaces/istakingrewards\ninterface IStakingRewards {\n  // Views\n  function rewardsToken() external view returns (IERC20);\n\n  function stakingToken() external view returns (IERC20);\n\n  function lastTimeRewardApplicable() external view returns (uint256);\n\n  function rewardPerToken() external view returns (uint256);\n\n  function earned(address account) external view returns (uint256);\n\n  function getRewardForDuration() external view returns (uint256);\n\n  function totalSupply() external view returns (uint256);\n\n  function balanceOf(address account) external view returns (uint256);\n\n  // Mutative\n\n  function stake(uint256 amount) external;\n\n  function withdraw(uint256 amount) external;\n\n  function getReward() external;\n\n  function exit() external;\n}\n","keccak256":"0x55ce0e1a8b2271c88bf267874c026fe55fb3f18d383559ff008784d29b8184b2","license":"MIT"},"contracts/ACFI/strategies/common/BaseStrategyTripleRewardLP.sol":{"content":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.0;\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nimport \"../../interfaces/synthetix/IStakingRewards.sol\";\n\nimport \"./StratManager.sol\";\n\nabstract contract BaseStrategyTripleRewardLP is StratManager {\n  using SafeERC20 for IERC20;\n  using SafeMath for uint256;\n\n  // Tokens used\n  address public native;\n  address public output;\n  address public want;\n  address public lpToken0;\n  address public lpToken1;\n  address constant nullAddress = address(0);\n\n  // 2nd reward\n  address public output2;\n\n  // 3rd reward\n  address public output3;\n\n  // Third party contracts\n  address public chef;\n\n  uint256 public lastHarvest;\n\n  // Routes\n  address[] public outputToNativeRoute;\n  address[] public outputToLp0Route;\n  address[] public outputToLp1Route;\n  address[] public output2ToOutputRoute;\n  address[] public output3ToOutputRoute;\n\n  function chargeFees(address) internal virtual;\n\n  function deposit() public virtual;\n\n  function _safeSwap(\n    uint256 _amountIn,\n    address[] memory _path,\n    address _to\n  ) internal virtual;\n\n  function _addLiquidity(uint256 lp0Bal, uint256 lp1Bal) internal virtual;\n\n  //events\n  event StratHarvest(address indexed harvester);\n\n  function harvest() external virtual {\n    _harvest(nullAddress);\n  }\n\n  function harvestWithCallFeeRecipient(address callFeeRecipient)\n    external\n    virtual\n  {\n    _harvest(callFeeRecipient);\n  }\n\n  function managerHarvest() external onlyManager {\n    _harvest(nullAddress);\n  }\n\n  // compounds earnings and charges performance fee\n  function _harvest(address callFeeRecipient) internal whenNotPaused {\n    IStakingRewards(chef).getReward();\n\n    uint256 output2Bal = IERC20(output2).balanceOf(address(this));\n    uint256 output3Bal = IERC20(output3).balanceOf(address(this));\n\n    _safeSwap(output2Bal, output2ToOutputRoute, address(this));\n    _safeSwap(output3Bal, output3ToOutputRoute, address(this));\n\n    uint256 finalOutputBal = IERC20(output).balanceOf(address(this));\n\n    if (finalOutputBal > 0) {\n      chargeFees(callFeeRecipient);\n      addLiquidity();\n      deposit();\n      lastHarvest = block.timestamp;\n      emit StratHarvest(msg.sender);\n    }\n  }\n\n  // Adds liquidity to AMM and gets more LP tokens.\n  function addLiquidity() internal {\n    uint256 outputHalf = IERC20(output).balanceOf(address(this)).div(2);\n\n    if (lpToken0 != output) {\n      _safeSwap(outputHalf, outputToLp0Route, address(this));\n    }\n\n    if (lpToken1 != output) {\n      _safeSwap(outputHalf, outputToLp1Route, address(this));\n    }\n\n    uint256 lp0Bal = IERC20(lpToken0).balanceOf(address(this));\n    uint256 lp1Bal = IERC20(lpToken1).balanceOf(address(this));\n    if (lp0Bal > 0 && lp1Bal > 0) {\n      _addLiquidity(lp0Bal, lp1Bal);\n    }\n  }\n}\n","keccak256":"0xa539bde11aa6e31c888ea65cb4dd5897f01c61556a2161c269f9be446d00653f","license":"GPL-3.0"},"contracts/ACFI/strategies/common/FeeManager.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./StratManager.sol\";\n\nabstract contract FeeManager is StratManager {\n  uint256 public constant STRATEGIST_FEE = 112;\n  uint256 public constant MAX_FEE = 1000;\n  uint256 public constant MAX_CALL_FEE = 111;\n\n  uint256 public constant WITHDRAWAL_FEE_CAP = 50;\n  uint256 public constant WITHDRAWAL_MAX = 10000;\n\n  uint256 public withdrawalFee = 10;\n\n  uint256 public callFee = 111;\n  uint256 public autocompFee = MAX_FEE - STRATEGIST_FEE - callFee;\n\n  function setCallFee(uint256 _fee) public onlyManager {\n    require(_fee <= MAX_CALL_FEE, \"!cap\");\n\n    callFee = _fee;\n    autocompFee = MAX_FEE - STRATEGIST_FEE - callFee;\n  }\n\n  function setWithdrawalFee(uint256 _fee) public onlyManager {\n    require(_fee <= WITHDRAWAL_FEE_CAP, \"!cap\");\n\n    withdrawalFee = _fee;\n  }\n}\n","keccak256":"0x3f92ff9856bbeda5eb5fb1df3d4713238c843ad284febba27c03edc1b4b9b08a","license":"MIT"},"contracts/ACFI/strategies/common/StratManager.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.4.22 <0.9.0;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/security/Pausable.sol\";\n\ncontract StratManager is Ownable, Pausable {\n  /**\n   * @dev Autocomp Contracts:\n   * {keeper} - Address to manage a few lower risk features of the strat\n   * {strategist} - Address of the strategy author/deployer where strategist fee will go.\n   * {vault} - Address of the vault that controls the strategy's funds.\n   * {unirouter} - Address of exchange to execute swaps.\n   */\n  address public keeper;\n  address public strategist;\n  address public unirouter;\n  address public vault;\n  address public harvester;\n  address public autocompFeeRecipient;\n\n  struct StratMgr {\n    address keeper;\n    address strategist;\n    address unirouter;\n    address vault;\n    address harvester;\n    address autocompFeeRecipient;\n  }\n\n  /**\n   * @dev Initializes the base strategy.\n   * @param stratMgr.keeper address to use as alternative owner.\n   * @param stratMgr.strategist address where strategist fees go.\n   * @param stratMgr.unirouter router to use for swaps\n   * @param stratMgr.vault address of parent vault.\n   * @param stratMgr.autocompFeeRecipient address where to send autocomp's fees.\n   */\n  constructor(StratMgr memory stratMgr) public {\n    keeper = stratMgr.keeper;\n    strategist = stratMgr.strategist;\n    unirouter = stratMgr.unirouter;\n    vault = stratMgr.vault;\n    harvester = stratMgr.harvester;\n    autocompFeeRecipient = stratMgr.autocompFeeRecipient;\n  }\n\n  // checks that caller is either owner or keeper.\n  modifier onlyManager() {\n    require(msg.sender == owner() || msg.sender == keeper, \"!manager\");\n    _;\n  }\n\n  // checks that caller is harvestr.\n  modifier onlyHarvester() {\n    require(msg.sender == harvester, \"!harvester\");\n    _;\n  }\n\n  /**\n   * @dev Updates address of the strat keeper.\n   * @param _keeper new keeper address.\n   */\n  function setKeeper(address _keeper) external onlyManager {\n    keeper = _keeper;\n  }\n\n  /**\n   * @dev Updates address of the strat harvester.\n   * @param _harvester new harvester address.\n   */\n  function setHarvester(address _harvester) external onlyManager {\n    harvester = _harvester;\n  }\n\n  /**\n   * @dev Updates address where strategist fee earnings will go.\n   * @param _strategist new strategist address.\n   */\n  function setStrategist(address _strategist) external {\n    require(msg.sender == strategist, \"!strategist\");\n    strategist = _strategist;\n  }\n\n  /**\n   * @dev Updates router that will be used for swaps.\n   * @param _unirouter new unirouter address.\n   */\n  function setUnirouter(address _unirouter) external onlyOwner {\n    unirouter = _unirouter;\n  }\n\n  /**\n   * @dev Updates parent vault.\n   * @param _vault new vault address.\n   */\n  function setVault(address _vault) external onlyOwner {\n    vault = _vault;\n  }\n\n  /**\n   * @dev Updates autocomp fee recipient.\n   * @param _autocompFeeRecipient new autocomp fee recipient address.\n   */\n  function setAutocompFeeRecipient(address _autocompFeeRecipient)\n    external\n    onlyOwner\n  {\n    autocompFeeRecipient = _autocompFeeRecipient;\n  }\n\n  /**\n   * @dev Function to synchronize balances before new user deposit.\n   * Can be overridden in the strategy.\n   */\n  function beforeDeposit() external virtual {}\n}\n","keccak256":"0x6bef4ad7d1a26e340e7f03bb89d4d7bbaf08662409aec37c64f051adfc39d8d6","license":"MIT"},"contracts/ACFI/strategies/ubeswap/StrategyStakingTripleRewardLP.sol":{"content":"// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nimport \"../../interfaces/common/IUniswapRouterETH.sol\";\nimport \"../../interfaces/common/IUniswapV2Pair.sol\";\nimport \"../../interfaces/synthetix/IStakingRewards.sol\";\n\nimport \"../common/StratManager.sol\";\nimport \"../common/FeeManager.sol\";\nimport \"../common/BaseStrategyTripleRewardLP.sol\";\n\ncontract StrategyStakingTripleRewardLP is\n  StratManager,\n  BaseStrategyTripleRewardLP,\n  FeeManager\n{\n  using SafeERC20 for IERC20;\n  using SafeMath for uint256;\n\n  bool public harvestOnDeposit;\n\n  /**\n   * @dev Event that is fired each time someone harvests the strat.\n   */\n  event _SafeSwap(\n    uint256 amountOut,\n    uint256 amountInMax,\n    address[] path,\n    address to,\n    uint256 deadline\n  );\n\n  constructor(\n    address _want,\n    address _chef,\n    StratMgr memory stratMgr,\n    address[] memory _outputToNativeRoute,\n    address[] memory _outputToLp0Route,\n    address[] memory _outputToLp1Route,\n    address[] memory _output2ToOutputRoute,\n    address[] memory _output3ToOutputRoute\n  ) public StratManager(stratMgr) {\n    want = _want;\n    chef = _chef;\n    // console.log(\"stratMgr %s \", stratMgr.vault);\n    require(_outputToNativeRoute.length >= 2);\n    output = _outputToNativeRoute[0];\n    native = _outputToNativeRoute[_outputToNativeRoute.length - 1];\n    outputToNativeRoute = _outputToNativeRoute;\n    // setup lp routing\n    lpToken0 = IUniswapV2Pair(want).token0();\n    require(_outputToLp0Route[0] == output);\n    require(_outputToLp0Route[_outputToLp0Route.length - 1] == lpToken0);\n    outputToLp0Route = _outputToLp0Route;\n    lpToken1 = IUniswapV2Pair(want).token1();\n    require(_outputToLp1Route[0] == output);\n    require(_outputToLp1Route[_outputToLp1Route.length - 1] == lpToken1);\n    outputToLp1Route = _outputToLp1Route;\n    // setup 2nd output\n    require(_output2ToOutputRoute.length >= 2);\n    output2 = _output2ToOutputRoute[0];\n    require(_output2ToOutputRoute[_output2ToOutputRoute.length - 1] == output);\n    output2ToOutputRoute = _output2ToOutputRoute;\n    // setup 3rd output\n    require(_output3ToOutputRoute.length >= 2);\n    output3 = _output3ToOutputRoute[0];\n    require(_output3ToOutputRoute[_output3ToOutputRoute.length - 1] == output);\n    output3ToOutputRoute = _output3ToOutputRoute;\n\n    // outputs are not the same\n    require(output != output2 && output != output3);\n    _giveAllowances();\n  }\n\n  // puts the funds to work\n  function deposit() public override {\n    uint256 wantBal = IERC20(want).balanceOf(address(this));\n\n    if (wantBal > 0) {\n      IStakingRewards(chef).stake(wantBal);\n    }\n  }\n\n  function withdraw(uint256 _amount) external {\n    require(msg.sender == vault, \"!vault\");\n\n    uint256 wantBal = IERC20(want).balanceOf(address(this));\n\n    if (wantBal < _amount) {\n      IStakingRewards(chef).withdraw(_amount.sub(wantBal));\n\n      wantBal = IERC20(want).balanceOf(address(this));\n    }\n\n    if (wantBal > _amount) {\n      wantBal = _amount;\n    }\n\n    if (tx.origin == owner() || paused()) {\n      IERC20(want).safeTransfer(vault, wantBal);\n    } else {\n      uint256 withdrawalFeeAmount = wantBal.mul(withdrawalFee).div(\n        WITHDRAWAL_MAX\n      );\n      IERC20(want).safeTransfer(vault, wantBal.sub(withdrawalFeeAmount));\n    }\n  }\n\n  function beforeDeposit() external override {\n    if (harvestOnDeposit) {\n      require(msg.sender == vault, \"!vault\");\n      _harvest(nullAddress);\n    }\n  }\n\n  // performance fees\n  function chargeFees(address callFeeRecipient) internal override {\n    // take fee from output\n    uint256 toNative = IERC20(output).balanceOf(address(this)).mul(45).div(\n      1000\n    );\n\n    _safeSwap(toNative, outputToNativeRoute, address(this));\n\n    uint256 nativeBal = IERC20(native).balanceOf(address(this));\n\n    uint256 callFeeAmount = nativeBal.mul(callFee).div(MAX_FEE);\n    if (callFeeRecipient != nullAddress) {\n      IERC20(native).safeTransfer(callFeeRecipient, callFeeAmount);\n    } else {\n      IERC20(native).safeTransfer(tx.origin, callFeeAmount);\n    }\n\n    uint256 autocompFeeAmount = nativeBal.mul(autocompFee).div(MAX_FEE);\n    IERC20(native).safeTransfer(autocompFeeRecipient, autocompFeeAmount);\n\n    uint256 strategistFee = nativeBal.mul(STRATEGIST_FEE).div(MAX_FEE);\n    IERC20(native).safeTransfer(strategist, strategistFee);\n  }\n\n  // calculate the total underlaying 'want' held by the strat.\n  function balanceOf() public view returns (uint256) {\n    return balanceOfWant().add(balanceOfPool());\n  }\n\n  // it calculates how much 'want' this contract holds.\n  function balanceOfWant() public view returns (uint256) {\n    return IERC20(want).balanceOf(address(this));\n  }\n\n  // it calculates how much 'want' the strategy has working in the farm.\n  function balanceOfPool() public view returns (uint256) {\n    uint256 _amount = IStakingRewards(chef).balanceOf(address(this));\n\n    return _amount;\n  }\n\n  // called as part of strat migration. Sends all the available funds back to the vault.\n  function retireStrat() external {\n    require(msg.sender == vault, \"!vault\");\n\n    IStakingRewards(chef).withdraw(balanceOf());\n\n    uint256 wantBal = IERC20(want).balanceOf(address(this));\n    IERC20(want).transfer(vault, wantBal);\n  }\n\n  function setHarvestOnDeposit(bool _harvestOnDeposit) external onlyManager {\n    harvestOnDeposit = _harvestOnDeposit;\n\n    if (harvestOnDeposit) {\n      setWithdrawalFee(0);\n    } else {\n      setWithdrawalFee(10);\n    }\n  }\n\n  function _safeSwap(\n    uint256 _amountIn,\n    address[] memory _path,\n    address _to\n  ) internal override {\n    // swapExactTokensForTokens\n    emit _SafeSwap(_amountIn, 0, _path, _to, block.timestamp.add(600));\n\n    if (_amountIn > 0) {\n      IUniswapRouterETH(unirouter).swapExactTokensForTokens(\n        _amountIn,\n        0,\n        _path,\n        _to,\n        block.timestamp.add(600)\n      );\n    }\n  }\n\n  function _addLiquidity(uint256 lp0Bal, uint256 lp1Bal) internal override {\n    IUniswapRouterETH(unirouter).addLiquidity(\n      lpToken0,\n      lpToken1,\n      lp0Bal,\n      lp1Bal,\n      1,\n      1,\n      address(this),\n      block.timestamp\n    );\n  }\n\n  // pauses deposits and withdraws all funds from third party systems.\n  function panic() public onlyManager {\n    pause();\n    IStakingRewards(chef).withdraw(balanceOf());\n  }\n\n  function pause() public onlyManager {\n    _pause();\n\n    _removeAllowances();\n  }\n\n  function unpause() external onlyManager {\n    _unpause();\n\n    _giveAllowances();\n\n    deposit();\n  }\n\n  function _giveAllowances() internal {\n    IERC20(want).safeApprove(chef, type(uint256).max);\n    IERC20(output).safeApprove(unirouter, type(uint256).max);\n    IERC20(lpToken0).safeApprove(unirouter, 0);\n    IERC20(lpToken0).safeApprove(unirouter, type(uint256).max);\n    IERC20(lpToken1).safeApprove(unirouter, 0);\n    IERC20(lpToken1).safeApprove(unirouter, type(uint256).max);\n    IERC20(output2).safeApprove(unirouter, 0);\n    IERC20(output2).safeApprove(unirouter, type(uint256).max);\n    IERC20(output3).safeApprove(unirouter, 0);\n    IERC20(output3).safeApprove(unirouter, type(uint256).max);\n  }\n\n  function _removeAllowances() internal {\n    IERC20(want).safeApprove(chef, 0);\n    IERC20(output).safeApprove(unirouter, 0);\n    IERC20(output2).safeApprove(unirouter, 0);\n    IERC20(output3).safeApprove(unirouter, 0);\n    IERC20(lpToken0).safeApprove(unirouter, 0);\n    IERC20(lpToken1).safeApprove(unirouter, 0);\n  }\n}\n","keccak256":"0x10875b71defead56234abd7cb62b4cc81c31f52589ea247eb1e5c6a0a8e041c7","license":"GPL-3.0"}},"version":1}