diff --git a/archive/deploy/mig/CauldronV3MIG.ts b/archive/deploy/mig/CauldronV3MIG.ts new file mode 100644 index 00000000..0fe2adaa --- /dev/null +++ b/archive/deploy/mig/CauldronV3MIG.ts @@ -0,0 +1,46 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; +import { network } from "hardhat"; +import { ChainId, setDeploymentSupportedChains, wrappedDeploy } from "../utilities"; +import { Constants, xMerlin } from "../test/constants"; +import { CauldronV3 } from "../typechain/CauldronV3"; + +const ParametersPerChain = { + [ChainId.Mainnet]: { + deploymentName: "CauldronV3MasterContractMIGMainnet", + degenBox: Constants.mainnet.degenBox, + mim: Constants.mainnet.mig, + owner: xMerlin, + }, +}; + +const deployFunction: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { getNamedAccounts } = hre; + const { deployer } = await getNamedAccounts(); + const chainId = await hre.getChainId(); + const parameters = ParametersPerChain[parseInt(chainId)]; + + // Deploy CauldronV3 MasterContract + const CauldronV3MasterContract = await wrappedDeploy(parameters.deploymentName, { + from: deployer, + args: [parameters.degenBox, parameters.mim], + log: true, + contract: "CauldronV3", + deterministicDeployment: false, + }); + + await (await CauldronV3MasterContract.setFeeTo(parameters.owner)).wait(); + + if (network.name !== "hardhat") { + if ((await CauldronV3MasterContract.owner()) != parameters.owner) { + await (await CauldronV3MasterContract.transferOwnership(parameters.owner, true, false)).wait(); + } + } +}; + +export default deployFunction; + +setDeploymentSupportedChains(Object.keys(ParametersPerChain), deployFunction); + +deployFunction.tags = ["CauldronV3MIG"]; +deployFunction.dependencies = []; diff --git a/archive/deploy/mig/MIG.ts b/archive/deploy/mig/MIG.ts new file mode 100644 index 00000000..7d054f46 --- /dev/null +++ b/archive/deploy/mig/MIG.ts @@ -0,0 +1,43 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; +import { network } from "hardhat"; +import { ChainId, setDeploymentSupportedChains, wrappedDeploy } from "../utilities"; +import { Constants, xMerlin } from "../test/constants"; +import { MagicInternetGold } from "../typechain/MagicInternetGold"; + +const ParametersPerChain = { + [ChainId.Mainnet]: { + deploymentName: "MagicInternetGold", + owner: xMerlin, + }, +}; + +const deployFunction: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { getNamedAccounts } = hre; + const { deployer } = await getNamedAccounts(); + const chainId = await hre.getChainId(); + const parameters = ParametersPerChain[parseInt(chainId)]; + + // Deploy MIG + const magicInternetGold = await wrappedDeploy(parameters.deploymentName, { + from: deployer, + args: [], + log: true, + contract: "MagicInternetGold", + deterministicDeployment: false, + }); + + + if (network.name !== "hardhat") { + if ((await magicInternetGold.owner()) != parameters.owner) { + await (await magicInternetGold.transferOwnership(parameters.owner, true, false)).wait(); + } + } +}; + +export default deployFunction; + +setDeploymentSupportedChains(Object.keys(ParametersPerChain), deployFunction); + +deployFunction.tags = ["MIG"]; +deployFunction.dependencies = []; diff --git a/contracts/MagicInternetGold.sol b/contracts/MagicInternetGold.sol new file mode 100644 index 00000000..95159418 --- /dev/null +++ b/contracts/MagicInternetGold.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT + +// Magic Internet Money + +// ███╗ ███╗██╗ ██████╗ +// ████╗ ████║██║██╔════╝ +// ██╔████╔██║██║██║ ███╗ +// ██║╚██╔╝██║██║██║ ██║ +// ██║ ╚═╝ ██║██║╚██████╔╝ +// ╚═╝ ╚═╝╚═╝ ╚═════╝ + + +// BoringCrypto, 0xMerlin + +pragma solidity 0.6.12; +import "@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol"; +import "@boringcrypto/boring-solidity/contracts/ERC20.sol"; +import "@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol"; +import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol"; + +/// @title Magic Internet Gold +contract MagicInternetGold is ERC20, BoringOwnable { + using BoringMath for uint256; + // ERC20 'variables' + string public constant symbol = "MIG"; + string public constant name = "Magic Internet Gold"; + uint8 public constant decimals = 18; + uint256 public override totalSupply; + + struct Minting { + uint128 time; + uint128 amount; + } + + Minting public lastMint; + uint256 private constant MINTING_PERIOD = 24 hours; + uint256 private constant MINTING_INCREASE = 15000; + uint256 private constant MINTING_PRECISION = 1e5; + + // @notice mint MIG to an address + // @param to - the recipient + // @param amount - the amount minted + function mint(address to, uint256 amount) public onlyOwner { + require(to != address(0), "MIG: no mint to zero address"); + + // Limits the amount minted per period to a convergence function, with the period duration restarting on every mint + uint256 totalMintedAmount = uint256(lastMint.time < block.timestamp - MINTING_PERIOD ? 0 : lastMint.amount).add(amount); + require(totalSupply == 0 || totalSupply.mul(MINTING_INCREASE) / MINTING_PRECISION >= totalMintedAmount); + + lastMint.time = block.timestamp.to128(); + lastMint.amount = totalMintedAmount.to128(); + + totalSupply = totalSupply + amount; + balanceOf[to] += amount; + emit Transfer(address(0), to, amount); + } + + // @notice mint MIG to a recipient on BentoBox + // @param clone - the recipient clone contract + // @param amount - the amount minted + // @param bentoBox - the address of the BentoBox / DegenBox selected + function mintToBentoBox(address clone, uint256 amount, IBentoBoxV1 bentoBox) public onlyOwner { + mint(address(bentoBox), amount); + bentoBox.deposit(IERC20(address(this)), address(bentoBox), clone, amount, 0); + } + + // @notice burn MIG from caller + // @param amount - the amount burnt + function burn(uint256 amount) public { + require(amount <= balanceOf[msg.sender], "MIM: not enough"); + + balanceOf[msg.sender] -= amount; + totalSupply -= amount; + emit Transfer(msg.sender, address(0), amount); + } +} diff --git a/contracts/oracles/WbtcOracleMig.sol b/contracts/oracles/WbtcOracleMig.sol new file mode 100644 index 00000000..11eb3bc5 --- /dev/null +++ b/contracts/oracles/WbtcOracleMig.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.10; +import "../interfaces/IOracle.sol"; + +// Chainlink Aggregator + +interface IAggregator { + function latestAnswer() external view returns (int256 answer); +} + +interface IERC20 { + function totalSupply() external view returns (uint256); + + function balanceOf(address account) external view returns (uint256); +} + +contract WbtcOracleMig is IOracle { + IAggregator public constant BTCUSD = IAggregator(0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c); + IAggregator public constant GOLD = IAggregator(0x214eD9Da11D2fbe465a6fc601a91E62EbEc1a0D6); + // Calculates the lastest exchange rate + // Uses both divide and multiply only for tokens not supported directly by Chainlink, for example MKR/USD + function _get() internal view returns (uint256) { + uint256 btcPrice = uint256(BTCUSD.latestAnswer()); + uint256 goldPrice = uint256(GOLD.latestAnswer()); + return goldPrice * 1e8 / btcPrice; + } + + // Get the latest exchange rate + /// @inheritdoc IOracle + function get(bytes calldata) public view override returns (bool, uint256) { + return (true, _get()); + } + + // Check the last exchange rate without any state changes + /// @inheritdoc IOracle + function peek(bytes calldata) public view override returns (bool, uint256) { + return (true, _get()); + } + + // Check the current spot exchange rate without any state changes + /// @inheritdoc IOracle + function peekSpot(bytes calldata data) external view override returns (uint256 rate) { + (, rate) = peek(data); + } + + /// @inheritdoc IOracle + function name(bytes calldata) public pure override returns (string memory) { + return "Chainlink GOLD BTC"; + } + + /// @inheritdoc IOracle + function symbol(bytes calldata) public pure override returns (string memory) { + return "LINK/GOLD/BTC"; + } +} diff --git a/deploy/WBTCMIG.ts b/deploy/WBTCMIG.ts new file mode 100644 index 00000000..122ac335 --- /dev/null +++ b/deploy/WBTCMIG.ts @@ -0,0 +1,134 @@ +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; +import { deployments, ethers, getNamedAccounts } from "hardhat"; +import { expect } from "chai"; +import { DegenBox, IOracle, ProxyOracle } from "../typechain"; +import { ChainId, setDeploymentSupportedChains, wrappedDeploy } from "../utilities"; +import { Constants, xMerlin } from "../test/constants"; + +const INTEREST_CONVERSION = 1e18 / (365.25 * 3600 * 24) / 100; +const OPENING_CONVERSION = 1e5 / 100; + +const oracleData = "0x0000000000000000000000000000000000000000"; + +export const ParametersPerChain = { + + [ChainId.Mainnet]: { + enabled: true, + cauldronV3MC: Constants.mainnet.cauldronV3mig, + degenBox: Constants.mainnet.degenBox, + mim: Constants.mainnet.mig, + owner: xMerlin, + + collateralization: 85 * 1e3, // 75% LTV + opening: 0.05 * OPENING_CONVERSION, // 0% initial + interest: parseInt(String(0 * INTEREST_CONVERSION)), // 0% Interest + liquidation: 7 * 1e3 + 1e5, // 10% liquidation fee + + cauldrons: [ + { + deploymentNamePrefix: "WBTCMig", + collateral: Constants.mainnet.wbtc, + }, + ], + }, +}; + +const deployFunction: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployer } = await getNamedAccounts(); + const chainId = parseInt(await hre.getChainId()); + const parameters = ParametersPerChain[chainId]; + + if (!parameters.enabled) { + console.log(`Deployment disabled for chain id ${chainId}`); + return; + } + + const getDeployment = async (name: string) => { + try { + return (await deployments.get(name)).address + } catch { + return undefined + } + } + + const DegenBox = await ethers.getContractAt("DegenBox", parameters.degenBox); + const cauldrons = parameters.cauldrons; + + for (let i = 0; i < cauldrons.length; i++) { + const cauldron = cauldrons[i]; + + const ProxyOracle = await wrappedDeploy(`${cauldron.deploymentNamePrefix}ProxyOracle`, { + from: deployer, + args: [], + log: true, + contract: "ProxyOracle", + deterministicDeployment: false, + }); + + const Oracle = await wrappedDeploy(`${cauldron.deploymentNamePrefix}OracleV1`, { + from: deployer, + args: [], + log: true, + contract: "WbtcOracleMig", + deterministicDeployment: false, + }); + + if ((await ProxyOracle.oracleImplementation()) !== Oracle.address) { + await (await ProxyOracle.changeOracleImplementation(Oracle.address)).wait(); + } + if ((await ProxyOracle.owner()) !== xMerlin) { + await (await ProxyOracle.transferOwnership(xMerlin, true, false)).wait(); + } + + let initData = ethers.utils.defaultAbiCoder.encode( + ["address", "address", "bytes", "uint64", "uint256", "uint256", "uint256"], + [ + cauldron.collateral, + ProxyOracle.address, + oracleData, + parameters.interest, + parameters.liquidation, + parameters.collateralization, + parameters.opening, + ] + ); + + const cauldronAddress = await getDeployment(`${cauldron.deploymentNamePrefix}Cauldron`) + + if(cauldronAddress === undefined) { + const tx = await (await DegenBox.deploy(parameters.cauldronV3MC, initData, true)).wait(); + + const deployEvent = tx?.events?.[0]; + expect(deployEvent?.eventSignature).to.be.eq("LogDeploy(address,bytes,address)"); + + deployments.save(`${cauldron.deploymentNamePrefix}Cauldron`, { + abi: [], + address: deployEvent?.args?.cloneAddress, + }); + } + + /* // Liquidation Swapper + await wrappedDeploy(`${cauldron.deploymentNamePrefix}Swapper`, { + from: deployer, + log: true, + contract: "YVCrvStETHSwapper2", + deterministicDeployment: false, + }); + + // Leverage Swapper + await wrappedDeploy(`${cauldron.deploymentNamePrefix}LevSwapper`, { + from: deployer, + log: true, + contract: "YVCrvStETHLevSwapper2", + deterministicDeployment: false, + }); */ + } +}; + +export default deployFunction; + +setDeploymentSupportedChains(Object.keys(ParametersPerChain), deployFunction); + +deployFunction.tags = ["WBTCMig"]; +deployFunction.dependencies = []; diff --git a/deployments/mainnet/CauldronV3MasterContractMIGMainnet.json b/deployments/mainnet/CauldronV3MasterContractMIGMainnet.json new file mode 100644 index 00000000..af4fbe06 --- /dev/null +++ b/deployments/mainnet/CauldronV3MasterContractMIGMainnet.json @@ -0,0 +1,903 @@ +{ + "address": "0xe965db54fe154765460C5289a2B383d34FD6010B", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IBentoBoxV1", + "name": "bentoBox_", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "magicInternetMoney_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint128", + "name": "accruedAmount", + "type": "uint128" + } + ], + "name": "LogAccrue", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "share", + "type": "uint256" + } + ], + "name": "LogAddCollateral", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "part", + "type": "uint256" + } + ], + "name": "LogBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint128", + "name": "newLimit", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "perAddressPart", + "type": "uint128" + } + ], + "name": "LogChangeBorrowLimit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "rate", + "type": "uint256" + } + ], + "name": "LogExchangeRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newFeeTo", + "type": "address" + } + ], + "name": "LogFeeTo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "oldInterestRate", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newInterestRate", + "type": "uint64" + } + ], + "name": "LogInterestChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateralShare", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowPart", + "type": "uint256" + } + ], + "name": "LogLiquidation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "share", + "type": "uint256" + } + ], + "name": "LogRemoveCollateral", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "part", + "type": "uint256" + } + ], + "name": "LogRepay", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "feeTo", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feesEarnedFraction", + "type": "uint256" + } + ], + "name": "LogWithdrawFees", + "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" + }, + { + "inputs": [], + "name": "BORROW_OPENING_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COLLATERIZATION_RATE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIQUIDATION_MULTIPLIER", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accrueInfo", + "outputs": [ + { + "internalType": "uint64", + "name": "lastAccrued", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "feesEarned", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "INTEREST_PER_SECOND", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "skim", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "share", + "type": "uint256" + } + ], + "name": "addCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxV1", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "part", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "share", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "borrowLimit", + "outputs": [ + { + "internalType": "uint128", + "name": "total", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "borrowPartPerAddress", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "newBorrowLimit", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "perAddressPart", + "type": "uint128" + } + ], + "name": "changeBorrowLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "newInterestRate", + "type": "uint64" + } + ], + "name": "changeInterestRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "collateral", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8[]", + "name": "actions", + "type": "uint8[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "datas", + "type": "bytes[]" + } + ], + "name": "cook", + "outputs": [ + { + "internalType": "uint256", + "name": "value1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value2", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "init", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "users", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "maxBorrowParts", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "contract ISwapper", + "name": "swapper", + "type": "address" + } + ], + "name": "liquidate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "magicInternetMoney", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterContract", + "outputs": [ + { + "internalType": "contract CauldronV3", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract IOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracleData", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "reduceSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "share", + "type": "uint256" + } + ], + "name": "removeCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "skim", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "part", + "type": "uint256" + } + ], + "name": "repay", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newFeeTo", + "type": "address" + } + ], + "name": "setFeeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrow", + "outputs": [ + { + "internalType": "uint128", + "name": "elastic", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "base", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalCollateralShare", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + }, + { + "internalType": "bool", + "name": "direct", + "type": "bool" + }, + { + "internalType": "bool", + "name": "renounce", + "type": "bool" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateExchangeRate", + "outputs": [ + { + "internalType": "bool", + "name": "updated", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userBorrowPart", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userCollateralShare", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xf65b718a6a67695c9ca7b0ce7c86af45aed20d44c70215ba7e4ea576cd334935", + "receipt": { + "to": null, + "from": "0xb4EfdA6DAf5ef75D08869A0f9C0213278fb43b6C", + "contractAddress": "0xe965db54fe154765460C5289a2B383d34FD6010B", + "transactionIndex": 133, + "gasUsed": "5028058", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000400000000000000000000000000000000000000000000000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000000000000000000080000000000000000020000008000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x132d047780ef7a13aa016884253ae1086fef9049eacd3df24d43bc35eaacc6c0", + "transactionHash": "0xf65b718a6a67695c9ca7b0ce7c86af45aed20d44c70215ba7e4ea576cd334935", + "logs": [ + { + "transactionIndex": 133, + "blockNumber": 14818497, + "transactionHash": "0xf65b718a6a67695c9ca7b0ce7c86af45aed20d44c70215ba7e4ea576cd334935", + "address": "0xe965db54fe154765460C5289a2B383d34FD6010B", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000b4efda6daf5ef75d08869a0f9c0213278fb43b6c" + ], + "data": "0x", + "logIndex": 174, + "blockHash": "0x132d047780ef7a13aa016884253ae1086fef9049eacd3df24d43bc35eaacc6c0" + } + ], + "blockNumber": 14818497, + "cumulativeGasUsed": "16551869", + "status": 1, + "byzantium": true + }, + "args": [ + "0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce", + "0x5624b48Ec2848bD642230b46405E1F65938c5FD0" + ], + "numDeployments": 1, + "solcInputHash": "9f4bd60296ecc46266e9c6fc79b5f896", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IBentoBoxV1\",\"name\":\"bentoBox_\",\"type\":\"address\"},{\"internalType\":\"contract IERC20\",\"name\":\"magicInternetMoney_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"accruedAmount\",\"type\":\"uint128\"}],\"name\":\"LogAccrue\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"share\",\"type\":\"uint256\"}],\"name\":\"LogAddCollateral\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"part\",\"type\":\"uint256\"}],\"name\":\"LogBorrow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"newLimit\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"perAddressPart\",\"type\":\"uint128\"}],\"name\":\"LogChangeBorrowLimit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"}],\"name\":\"LogExchangeRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newFeeTo\",\"type\":\"address\"}],\"name\":\"LogFeeTo\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"oldInterestRate\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newInterestRate\",\"type\":\"uint64\"}],\"name\":\"LogInterestChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"collateralShare\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"borrowPart\",\"type\":\"uint256\"}],\"name\":\"LogLiquidation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"share\",\"type\":\"uint256\"}],\"name\":\"LogRemoveCollateral\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"part\",\"type\":\"uint256\"}],\"name\":\"LogRepay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeTo\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feesEarnedFraction\",\"type\":\"uint256\"}],\"name\":\"LogWithdrawFees\",\"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\"},{\"inputs\":[],\"name\":\"BORROW_OPENING_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COLLATERIZATION_RATE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LIQUIDATION_MULTIPLIER\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accrue\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accrueInfo\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"lastAccrued\",\"type\":\"uint64\"},{\"internalType\":\"uint128\",\"name\":\"feesEarned\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"INTEREST_PER_SECOND\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"skim\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"share\",\"type\":\"uint256\"}],\"name\":\"addCollateral\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"borrow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"part\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"share\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowLimit\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"total\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"borrowPartPerAddress\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint128\",\"name\":\"newBorrowLimit\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"perAddressPart\",\"type\":\"uint128\"}],\"name\":\"changeBorrowLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"newInterestRate\",\"type\":\"uint64\"}],\"name\":\"changeInterestRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"collateral\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8[]\",\"name\":\"actions\",\"type\":\"uint8[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes[]\",\"name\":\"datas\",\"type\":\"bytes[]\"}],\"name\":\"cook\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value2\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exchangeRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"init\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"users\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"maxBorrowParts\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"contract ISwapper\",\"name\":\"swapper\",\"type\":\"address\"}],\"name\":\"liquidate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"magicInternetMoney\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterContract\",\"outputs\":[{\"internalType\":\"contract CauldronV3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract IOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"reduceSupply\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"share\",\"type\":\"uint256\"}],\"name\":\"removeCollateral\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"skim\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"part\",\"type\":\"uint256\"}],\"name\":\"repay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newFeeTo\",\"type\":\"address\"}],\"name\":\"setFeeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalBorrow\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"elastic\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"base\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalCollateralShare\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"direct\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"renounce\",\"type\":\"bool\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateExchangeRate\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"updated\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userBorrowPart\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userCollateralShare\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This contract allows contract calls to any contract (except BentoBox) from arbitrary callers thus, don't trust calls from this contract in any circumstances.\",\"kind\":\"dev\",\"methods\":{\"addCollateral(address,bool,uint256)\":{\"params\":{\"share\":\"The amount of shares to add for `to`.\",\"skim\":\"True if the amount should be skimmed from the deposit balance of msg.sender.x False if tokens from msg.sender in `bentoBox` should be transferred.\",\"to\":\"The receiver of the tokens.\"}},\"borrow(address,uint256)\":{\"returns\":{\"part\":\"Total part of the debt held by borrowers.\",\"share\":\"Total amount in shares borrowed.\"}},\"changeBorrowLimit(uint128,uint128)\":{\"params\":{\"newBorrowLimit\":\"new borrow limit\",\"perAddressPart\":\"new borrow limit per address\"}},\"changeInterestRate(uint64)\":{\"params\":{\"newInterestRate\":\"new interest rate\"}},\"cook(uint8[],uint256[],bytes[])\":{\"params\":{\"actions\":\"An array with a sequence of actions to execute (see ACTION_ declarations).\",\"datas\":\"A one-to-one mapped array to `actions`. Contains abi encoded data of function arguments.\",\"values\":\"A one-to-one mapped array to `actions`. ETH amounts to send along with the actions. Only applicable to `ACTION_CALL`, `ACTION_BENTO_DEPOSIT`.\"},\"returns\":{\"value1\":\"May contain the first positioned return value of the last executed action (if applicable).\",\"value2\":\"May contain the second positioned return value of the last executed action which returns 2 values (if applicable).\"}},\"init(bytes)\":{\"details\":\"`data` is abi encoded in the format: (IERC20 collateral, IERC20 asset, IOracle oracle, bytes oracleData)\"},\"liquidate(address[],uint256[],address,address)\":{\"params\":{\"maxBorrowParts\":\"A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.\",\"to\":\"Address of the receiver in open liquidations if `swapper` is zero.\",\"users\":\"An array of user addresses.\"}},\"reduceSupply(uint256)\":{\"params\":{\"amount\":\"amount to reduce supply by\"}},\"removeCollateral(address,uint256)\":{\"params\":{\"share\":\"Amount of shares to remove.\",\"to\":\"The receiver of the shares.\"}},\"repay(address,bool,uint256)\":{\"params\":{\"part\":\"The amount to repay. See `userBorrowPart`.\",\"skim\":\"True if the amount should be skimmed from the deposit balance of msg.sender. False if tokens from msg.sender in `bentoBox` should be transferred.\",\"to\":\"Address of the user this payment should go.\"},\"returns\":{\"amount\":\"The total amount repayed.\"}},\"setFeeTo(address)\":{\"params\":{\"newFeeTo\":\"The address of the receiver.\"}},\"transferOwnership(address,bool,bool)\":{\"params\":{\"direct\":\"True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\",\"newOwner\":\"Address of the new owner.\",\"renounce\":\"Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\"}},\"updateExchangeRate()\":{\"returns\":{\"rate\":\"The new exchange rate.\",\"updated\":\"True if `exchangeRate` was updated.\"}}},\"title\":\"Cauldron\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"accrue()\":{\"notice\":\"Accrues the interest on the borrowed tokens and handles the accumulation of fees.\"},\"addCollateral(address,bool,uint256)\":{\"notice\":\"Adds `collateral` from msg.sender to the account `to`.\"},\"borrow(address,uint256)\":{\"notice\":\"Sender borrows `amount` and transfers it to `to`.\"},\"changeBorrowLimit(uint128,uint128)\":{\"notice\":\"allows to change the borrow limit\"},\"changeInterestRate(uint64)\":{\"notice\":\"allows to change the interest rate\"},\"claimOwnership()\":{\"notice\":\"Needs to be called by `pendingOwner` to claim ownership.\"},\"constructor\":\"The constructor is only used for the initial master contract. Subsequent clones are initialised via `init`.\",\"cook(uint8[],uint256[],bytes[])\":{\"notice\":\"Executes a set of actions and allows composability (contract calls) to other contracts.\"},\"exchangeRate()\":{\"notice\":\"Exchange and interest rate tracking. This is 'cached' here because calls to Oracles can be very expensive.\"},\"init(bytes)\":{\"notice\":\"Serves as the constructor for clones, as clones can't have a regular constructor\"},\"liquidate(address[],uint256[],address,address)\":{\"notice\":\"Handles the liquidation of users' balances, once the users' amount of collateral is too low.\"},\"reduceSupply(uint256)\":{\"notice\":\"reduces the supply of MIM\"},\"removeCollateral(address,uint256)\":{\"notice\":\"Removes `share` amount of collateral and transfers it to `to`.\"},\"repay(address,bool,uint256)\":{\"notice\":\"Repays a loan.\"},\"setFeeTo(address)\":{\"notice\":\"Sets the beneficiary of interest accrued. MasterContract Only Admin function.\"},\"transferOwnership(address,bool,bool)\":{\"notice\":\"Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner. Can only be invoked by the current `owner`.\"},\"updateExchangeRate()\":{\"notice\":\"Gets the exchange rate. I.e how much collateral to buy 1e18 asset. This function is supposed to be invoked if needed because Oracle queries can be expensive.\"},\"withdrawFees()\":{\"notice\":\"Withdraws the fees accumulated.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/CauldronV3.sol\":\"CauldronV3\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\":{\"keccak256\":\"0xbde1619421fef865bf5f5f806e319900fb862e27f0aef6e0878e93f04f477601\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://76fb6488d9329f078b67ab61296a0cc0672f1669f2e3b776b3418b89dccc7f26\",\"dweb:/ipfs/QmeNCQZRWZQktYeePHEfRmiuAg3JfpCTgKkJruddSRh3eD\"]},\"@boringcrypto/boring-solidity/contracts/Domain.sol\":{\"keccak256\":\"0xe5215010c5a07b4b2fb1a2347b2106377678fea3d6f9ed656677c0570de2f6aa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a6d7d2b184772d1524e61160790a8c7968c7b9fa6879545764f8a243ae52db84\",\"dweb:/ipfs/QmQTHA2gtm1zfK9GfrrZk5X2A7725RNSLNZFPn8CAMSf4v\"]},\"@boringcrypto/boring-solidity/contracts/ERC20.sol\":{\"keccak256\":\"0x215d98f2006287eb309c79fcfebd5a25cf26e60ccf28923d203de07b6f671658\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e6e19b72bd3e27113efec8111083dec06697d2d18b46c04fc7c7a0e9d6d6172e\",\"dweb:/ipfs/QmNoUEdjTryBBFhHqpf7JFWsMyFt72BQHV7DmsWNvgg4kn\"]},\"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\":{\"keccak256\":\"0xf0da35541d6ae9e3c12fdd7c8d5d9584c56f9ac50d062efb8ca353ebd6ffd47d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8670101b72310d2c5e9b3e216e15ccb46de879acb9d3e2260952f331dad86301\",\"dweb:/ipfs/QmPzbTvPqhjo2bqxyoDasCBPtGUK41BrWvf5BJ5UmiUgAd\"]},\"@boringcrypto/boring-solidity/contracts/interfaces/IMasterContract.sol\":{\"keccak256\":\"0xc8d7519d2bd26fc6d5125f8fc3fe2a6aada76f71f26b4712e0a4160f1cbdb2ba\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://eaaafc02c9346967f1808b285262c2269444ebb0e1d1c69e68219e7a7d383bbe\",\"dweb:/ipfs/QmTaKuXnyD2LDGAQYu6JMfhQn3Lfjkmy8CjjwdoJfY8cUN\"]},\"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\":{\"keccak256\":\"0x08491b0b0af82e0d3c54a1274e745d95bd65c7638d240a83479121c6808bfc0e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1ff10b2639d9d4ca7b4d7ab62c37c510a026b45aef035b73c33bf255144e4f81\",\"dweb:/ipfs/QmdpaE4CRNyzaYkj8CHfJ17E2N1q9tcv8ynV5xT4o4WMBg\"]},\"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\":{\"keccak256\":\"0x6bc52950e23c70a90a5b039697b77ba76360b62da6a06a61d3a1714b9c6c26b9\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://507b01278ba8ce200337e21122c8912c39b7a583d821fde847f47e36fd26c598\",\"dweb:/ipfs/Qmcm7G94MBdSPm7fS743fV86yMX2kMeE3a9QXjTpTAj6zW\"]},\"@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol\":{\"keccak256\":\"0xab228bfa8a3019a4f7effa8aeeb05de141d328703d8a2f7b87ca811d0ca33196\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1bd6ad690273605a13e3b0d6d3a36effb1731e37b80412173c2a05937c1f3feb\",\"dweb:/ipfs/Qmc3sQZy24idf3T7JwSJDNCMjDbGVuJX9KDxSYhrg6N1rW\"]},\"@sushiswap/bentobox-sdk/contracts/IBatchFlashBorrower.sol\":{\"keccak256\":\"0x825a46e61443df6e1289b513da4386d0413d0b5311553f3e7e7e5c90412ddd5d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://45b7f0de6681d4fb9df535fca0390a8cc142ec2981ffed02f3b83c6c501a553e\",\"dweb:/ipfs/QmWZhHU9oH2Hv1CtiMD9tmyx2w4nV4D1CmVaTKqCgZBGBC\"]},\"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\":{\"keccak256\":\"0x9c025e34e0ef0c1fc9372ada9afa61925341ee93de9b9a79e77de55d715b6fb6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fe5799a3729532b5778f28cd964c9e8a995a426655952c54eda463b4b64f4e10\",\"dweb:/ipfs/QmaGmvYv2EL5BphgSBigmoExZ49zg4TzzV37gZmSsHkZcq\"]},\"@sushiswap/bentobox-sdk/contracts/IFlashBorrower.sol\":{\"keccak256\":\"0x6e389a5acb7b3e7f337b7e28477e998228f05fc4c8ff877eab32d3e15037ccc2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://268688eb93738ee85a293b9e5d0aca5d59719e9002390bf7c82b9020f9b78e5a\",\"dweb:/ipfs/QmYvDnmzTV6WWDE2RFyMPKfVG6qAt1vQwTYsgcayYLsM7S\"]},\"@sushiswap/bentobox-sdk/contracts/IStrategy.sol\":{\"keccak256\":\"0x91c02244e1508cf8e4d6c45110c57142301c237e809dcad67b8022f83555ba13\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dbdc0679a3a2b12acf0ea4143229e604b1a594310c9c82c1cb719f54dec2770c\",\"dweb:/ipfs/QmadvAQG75cbdccjLz9CZvATidiRXJjTKbrDQB6Z5u1G1L\"]},\"contracts/CauldronV3.sol\":{\"keccak256\":\"0xa97c5b4ef435577d7b521ccce153ddae1ee3afd104f149d400bf315ca1570894\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://0fc1c360c539de2ec5f954a491226e807a65d645cc340281184d8a791745a8a5\",\"dweb:/ipfs/QmWnRUtpHmuRmB9RrmLNMEdXzpqrJHDG4e7rbnhMyhJrv9\"]},\"contracts/MagicInternetMoney.sol\":{\"keccak256\":\"0xa5b8321d8583abe3d8639ba67b7315fed5e94179f5aafbf8f0cfb4e832ea38a1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8127e30fe0e81bd06c9a3e86a9df97473d29979e58f9cd8fdfc590d205fdc804\",\"dweb:/ipfs/QmXXgEYYaV72ag67EfqH5g6ewMXD5rYAL1Wso18ZrWa9qA\"]},\"contracts/interfaces/IOracle.sol\":{\"keccak256\":\"0x4b3446c52308ff064dc7caa7cddd05aed7d999f1aa269a5a1d26792753a99b58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bbebffa70eee039941096dfbea74b23c41d7e870a561f50230bcb95f6735e2de\",\"dweb:/ipfs/QmaSftQLfaWptw3r8qmd5Q6xHcvCVywTudq3DrhocaqgVX\"]},\"contracts/interfaces/ISwapper.sol\":{\"keccak256\":\"0x4eb956332e5247ae9268342699b7b78d1ec4c5d64d6ccd781aa9094562d3705f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0dd56a278f6a4c50930ab80505ccc279a1ad5095aa679a84a4e1e01d3dde2cac\",\"dweb:/ipfs/QmXb8m49LfefSh4Csyr8cFPRaB6q5S5RE17hAKcpiYuwp5\"]}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162005c1b38038062005c1b833981016040819052620000349162000099565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36001600160601b0319606092831b811660805290821b1660c05230901b60a052620000f0565b60008060408385031215620000ac578182fd5b8251620000b981620000d7565b6020840151909250620000cc81620000d7565b809150509250929050565b6001600160a01b0381168114620000ed57600080fd5b50565b60805160601c60a05160601c60c05160601c615a1e620001fd60003980610c8f5280610d78528061195c5280611d7852806126c8528061286452806129505280612a3a5280612aab528061332652806133e352806137e452806138cc5250806108e45280610b615280611c3a5280611d9a5280612b2b5280612c77525080610c4d5280610d4b52806114f252806116c752806117ac52806119205280611b485280611d3c5280611f895280612120528061269b528061278852806129235280612a0d52806132f752806133a7528061340f52806134a652806137a2528061389f5280613a625280613c755280613d2b5280613e145280613fa652806142b052806143da5250615a1e6000f3fe6080604052600436106102345760003560e01c80637dc0d1d011610138578063b27c0e74116100b0578063e30c39781161007f578063f46901ed11610064578063f46901ed146105ae578063f7dad434146105ce578063f8ba4cff146105ee57610234565b8063e30c397814610584578063e551d11d1461059957610234565b8063b27c0e7414610521578063c7ee2a7b14610545578063cd446e221461055a578063d8dfeb451461056f57610234565b8063876467f811610107578063912860c5116100ec578063912860c5146104d75780639b352ae1146104f7578063aba024f41461050c57610234565b8063876467f8146104a25780638da5cb5b146104c257610234565b80637dc0d1d01461042a578063806234441461043f5780638285ef401461045f578063860ffea11461048257610234565b8063476343ee116101cb5780634e71e0c81161019a5780636b2ace871161017f5780636b2ace87146103de5780636ec097fb146103f357806374645ff31461040857610234565b80634e71e0c8146103b6578063656f3d64146103cb57610234565b8063476343ee1461034057806348e4163e146103555780634b8a3529146103755780634ddf47d4146103a357610234565b80631c9e379b116102075780631c9e379b146102d65780631cd4c966146102f65780633ba0b9a914610316578063473e3ce71461032b57610234565b8063017e7e581461023957806302ce728f14610264578063078dfbe71461028757806315294c40146102a9575b600080fd5b34801561024557600080fd5b5061024e610603565b60405161025b919061509b565b60405180910390f35b34801561027057600080fd5b5061027961061f565b60405161025b929190615102565b34801561029357600080fd5b506102a76102a23660046149fc565b61071f565b005b3480156102b557600080fd5b506102c96102c4366004614a46565b6108b3565b60405161025b91906157e6565b3480156102e257600080fd5b506102c96102f1366004614899565b6108d0565b34801561030257600080fd5b506102a7610311366004614fcc565b6108e2565b34801561032257600080fd5b506102c9610b49565b34801561033757600080fd5b506102c9610b4f565b34801561034c57600080fd5b506102a7610b55565b34801561036157600080fd5b506102c9610370366004614899565b610e55565b34801561038157600080fd5b50610395610390366004614a86565b610e67565b60405161025b9291906157ef565b6102a76103b1366004614c3a565b610ed6565b3480156103c257600080fd5b506102a7611126565b6103956103d9366004614b43565b61120c565b3480156103ea57600080fd5b5061024e611b46565b3480156103ff57600080fd5b506102c9611b6a565b34801561041457600080fd5b5061041d611b70565b60405161025b9190615112565b34801561043657600080fd5b5061024e611c1c565b34801561044b57600080fd5b506102a761045a366004614eb5565b611c38565b34801561046b57600080fd5b50610474611eaa565b60405161025b9291906157c3565b34801561048e57600080fd5b506102a761049d366004614a46565b611eda565b3480156104ae57600080fd5b506102a76104bd366004614a86565b611ffc565b3480156104ce57600080fd5b5061024e61205b565b3480156104e357600080fd5b506102a76104f2366004614ab1565b612077565b34801561050357600080fd5b5061024e612aa9565b34801561051857600080fd5b506102c9612acd565b34801561052d57600080fd5b50610536612ad3565b60405161025b93929190615813565b34801561055157600080fd5b506102c9612b23565b34801561056657600080fd5b5061024e612b29565b34801561057b57600080fd5b5061024e612b4d565b34801561059057600080fd5b5061024e612b69565b3480156105a557600080fd5b50610474612b85565b3480156105ba57600080fd5b506102a76105c9366004614899565b612bb5565b3480156105da57600080fd5b506102a76105e9366004614f64565b612c75565b3480156105fa57600080fd5b506102a7612e19565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b600480546040517fd6d7d525000000000000000000000000000000000000000000000000000000008152600092839273ffffffffffffffffffffffffffffffffffffffff169163d6d7d525916106789160059101615163565b6040805180830381600087803b15801561069157600080fd5b505af11580156106a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c99190614bd9565b9092509050811561071657600b8190556040517f9f9192b5edb17356c524e08d9e025c8e2f6307e6ea52fb7968faa3081f51c3c8906107099083906157e6565b60405180910390a161071b565b50600b545b9091565b60005473ffffffffffffffffffffffffffffffffffffffff163314610779576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615584565b60405180910390fd5b811561086d5773ffffffffffffffffffffffffffffffffffffffff83161515806107a05750805b6107d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615471565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808716939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff85167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556001805490911690556108ae565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85161790555b505050565b60006108bd612e19565b6108c88484846131bf565b949350505050565b60096020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561094857600080fd5b505afa15801561095c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098091906148b5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615403565b600c5467ffffffffffffffff7801000000000000000000000000000000000000000000000000909104811690600490600383021604810167ffffffffffffffff168267ffffffffffffffff161080610a4a57506312e687c067ffffffffffffffff831611155b610a80576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906155ee565b42600d546203f4800110610ac0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107709061554d565b42600d55600c805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8516021790556040517f76bc92b92b7755bcb03b25070431a80435c4d3fbf91c6c81c0c0cc350f6b5c6a90610b3d9083908590615849565b60405180910390a15050565b600b5481565b60075481565b610b5d612e19565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b158015610bc557600080fd5b505afa158015610bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfd91906148b5565b600c546040517fda5139ca0000000000000000000000000000000000000000000000000000000081529192506801000000000000000090046fffffffffffffffffffffffffffffffff16906000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063da5139ca90610cbb907f00000000000000000000000000000000000000000000000000000000000000009086908690600401615365565b60206040518083038186803b158015610cd357600080fd5b505afa158015610ce7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0b9190614f91565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90610da6907f000000000000000000000000000000000000000000000000000000000000000090309088908790600401615232565b600060405180830381600087803b158015610dc057600080fd5b505af1158015610dd4573d6000803e3d6000fd5b5050600c80547fffffffffffffffff00000000000000000000000000000000ffffffffffffffff169055505060405173ffffffffffffffffffffffffffffffffffffffff8416907fbe641c3ffc44b2d6c184f023fa4ed7bda4b6ffa71e03b3c98ae0c776da1f17e790610e489085906157e6565b60405180910390a2505050565b600a6020526000908152604090205481565b600080610e72612e19565b610e7c848461351d565b90925090506000610e8b61061f565b915050610e983382613991565b610ece576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906153cc565b509250929050565b60035473ffffffffffffffffffffffffffffffffffffffff1615610f26576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107709061565c565b610f3281830183614df0565b6010819055600e829055600f839055600c805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff87160217905584516003906000906004908290610fa69060059060208c01906146e3565b50815461010091820a73ffffffffffffffffffffffffffffffffffffffff818102199092169b8216029a909a17909155825491900a8089021990911698881602979097179096555050604080518082019091526fffffffffffffffffffffffffffffffff80825260209091015250507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6006556003541615159050611077576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906156ca565b600480546040517fd6d7d52500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169163d6d7d525916110cd9160059101615163565b6040805180830381600087803b1580156110e657600080fd5b505af11580156110fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111e9190614bd9565b600b55505050565b60015473ffffffffffffffffffffffffffffffffffffffff16338114611178576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906155b9565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055600180549091169055565b60008061121761475d565b60005b88811015611ae35760008a8a8381811061123057fe5b90506020020160208101906112459190614ff4565b9050826020015115801561125c5750600a8160ff16105b1561127157611269612e19565b600160208401525b60ff8116600a14156112cb57600080600089898681811061128e57fe5b90506020028101906112a09190615864565b8101906112ad9190614efc565b9250925092506112c3828261049d868c8c613b63565b505050611ada565b60ff81166002141561132b5760008060008989868181106112e857fe5b90506020028101906112fa9190615864565b8101906113079190614efc565b925092509250611322828261131d868c8c613b63565b6131bf565b50505050611ada565b60ff8116600414156113885760008088888581811061134657fe5b90506020028101906113589190615864565b8101906113659190614ecd565b9150915061137d81611378848a8a613b63565b613ba9565b505060018352611ada565b60ff8116600514156113eb576000808888858181106113a357fe5b90506020028101906113b59190615864565b8101906113c29190614ecd565b915091506113da816113d5848a8a613b63565b61351d565b600187529097509550611ada915050565b60ff8116600b14156114a457600080600089898681811061140857fe5b905060200281019061141a9190615864565b8101906114279190614c06565b92509250925060008061143861061f565b915091508415806114465750815b801561145157508381115b8015611464575082158061146457508281115b61149a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107709061576f565b5050505050611ada565b60ff811660181415611590576000806000806000808c8c898181106114c557fe5b90506020028101906114d79190615864565b8101906114e491906148d1565b9550955095509550955095507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663c0a47c938787878787876040518763ffffffff1660e01b8152600401611553969594939291906150bc565b600060405180830381600087803b15801561156d57600080fd5b505af1158015611581573d6000803e3d6000fd5b50505050505050505050611ada565b60ff8116601414156116185761160e8787848181106115ab57fe5b90506020028101906115bd9190615864565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92508c915086905081811061160057fe5b905060200201358787613cea565b9095509350611ada565b60ff8116601514156116835761160e87878481811061163357fe5b90506020028101906116459190615864565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250899250889150613ded9050565b60ff8116601614156117685760008060008989868181106116a057fe5b90506020028101906116b29190615864565b8101906116bf9190614ca7565b9250925092507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc84338561170f868e8e613b63565b6040518563ffffffff1660e01b815260040161172e9493929190615232565b600060405180830381600087803b15801561174857600080fd5b505af115801561175c573d6000803e3d6000fd5b50505050505050611ada565b60ff81166017141561180957600060608089898681811061178557fe5b90506020028101906117979190615864565b8101906117a49190614d1d565b9250925092507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630fca8843843385856040518563ffffffff1660e01b815260040161172e94939291906152aa565b60ff8116601e14156118e3576060600061188b8b8b8681811061182857fe5b905060200201358a8a8781811061183b57fe5b905060200281019061184d9190615864565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c92508b9150613ee89050565b915091508060ff16600114156118b657818060200190518101906118af9190614f91565b96506118dc565b8060ff16600214156118dc57818060200190518101906118d69190614fa9565b90975095505b5050611ada565b60ff811660061415611a475760008787848181106118fd57fe5b905060200281019061190f9190615864565b81019061191c9190614eb5565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663da5139ca7f00000000000000000000000000000000000000000000000000000000000000006119cf611989858b8b613b63565b604080518082019091526008546fffffffffffffffffffffffffffffffff8082168352700100000000000000000000000000000000909104166020820152906001614106565b60016040518463ffffffff1660e01b81526004016119ef93929190615365565b60206040518083038186803b158015611a0757600080fd5b505afa158015611a1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3f9190614f91565b955050611ada565b60ff811660071415611ada576000878784818110611a6157fe5b9050602002810190611a739190615864565b810190611a809190614eb5565b9050611ad6611a90828888613b63565b604080518082019091526008546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041660208201529060006141ca565b9550505b5060010161121a565b50805115611b3a576000611af561061f565b915050611b023382613991565b611b38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906153cc565b505b50965096945050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600f5481565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f81018490048402820184019092528181529291830182828015611c145780601f10611be957610100808354040283529160200191611c14565b820191906000526020600020905b815481529060010190602001808311611bf757829003601f168201915b505050505081565b60045473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9e57600080fd5b505afa158015611cb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd691906148b5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615403565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166397da6d307f0000000000000000000000000000000000000000000000000000000000000000307f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611dfe57600080fd5b505afa158015611e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3691906148b5565b8560006040518663ffffffff1660e01b8152600401611e59959493929190615269565b6040805180830381600087803b158015611e7257600080fd5b505af1158015611e86573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190614fa9565b6008546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260096020526040902054611f0a9082614267565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260096020526040902055600754611f3d8183614267565b600755600354611f659073ffffffffffffffffffffffffffffffffffffffff168383866142a4565b8373ffffffffffffffffffffffffffffffffffffffff1683611f875733611fa9565b7f00000000000000000000000000000000000000000000000000000000000000005b73ffffffffffffffffffffffffffffffffffffffff167f9ed03113de523cebfe5e49d5f8e12894b1c0d42ce805990461726444c90eab8784604051611fee91906157e6565b60405180910390a350505050565b612004612e19565b61200e8282613ba9565b600061201861061f565b9150506120253382613991565b6108ae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906153cc565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b600061208161061f565b91505061208c612e19565b600080600061209961475d565b50604080518082019091526008546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041660208201526120e061475d565b6003546040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692634ffe34db9261215992919091169060040161509b565b604080518083038186803b15801561217057600080fd5b505afa158015612184573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a89190614f22565b905060005b8b81101561247c5760008d8d838181106121c357fe5b90506020020160208101906121d89190614899565b90506121e48189613991565b6124735773ffffffffffffffffffffffffffffffffffffffff81166000908152600a6020526040812054808e8e8681811061221b57fe5b905060200201351161223f578d8d8581811061223357fe5b90506020020135612241565b805b915061224d818361444e565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600a60205260408120919091559050612283868383614106565b905060006122c9670de0b6b3a7640000620186a0026122b78d6122b1600f548761448b90919063ffffffff16565b9061448b565b816122be57fe5b8891900460006141ca565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600960205260409020549091506122fc908261444e565b73ffffffffffffffffffffffffffffffffffffffff80861660008181526009602052604090819020939093559151908f1691907f8ad4d3ff00da092c7ad9a573ea4f5f6a3dffc6712dc06d3f78f49b862297c4029061235c9085906157e6565b60405180910390a38373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc8e512d8f188ca059984b5853d2bf653da902696b8512785b182b2c813789a6e84866040516123c39291906157ef565b60405180910390a38c73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f66b108dc29b952efc76dccea9b82dce6b59fab4d9af73d8dcc9789afcad5daf6848688604051612443939291906157fd565b60405180910390a46124558a82614267565b99506124618983614267565b985061246d8884614267565b97505050505b506001016121ad565b50836124b4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906154df565b6124da6124c0856144dc565b83516fffffffffffffffffffffffffffffffff169061452c565b6fffffffffffffffffffffffffffffffff1682526125176124fa846144dc565b60208401516fffffffffffffffffffffffffffffffff169061452c565b6fffffffffffffffffffffffffffffffff908116602084018190528351600880547fffffffffffffffffffffffffffffffff000000000000000000000000000000001691841691909117909216700100000000000000000000000000000000909102179055600754612589908661444e565b600781905550600060646125c3600a6122b188620186a06125b5600f548c61448b90919063ffffffff16565b816125bc57fe5b049061444e565b816125ca57fe5b0490506125d78582614267565b945061260c6125e5826144dc565b600c546801000000000000000090046fffffffffffffffffffffffffffffffff169061457e565b600c80546fffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffffffffffff00000000000000000000000000000000ffffffffffffffff909216919091179055506040517fda5139ca00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063da5139ca906126f5907f0000000000000000000000000000000000000000000000000000000000000000908990600190600401615365565b60206040518083038186803b15801561270d57600080fd5b505afa158015612721573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127459190614f91565b6003546040517ff18d03cc00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169263f18d03cc926127c492169030908e908c90600401615232565b600060405180830381600087803b1580156127de57600080fd5b505af11580156127f2573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff8816156128e6576003546040517fe343fe1200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a81169263e343fe129261289292909116907f000000000000000000000000000000000000000000000000000000000000000090339087908d90600401615269565b6040805180830381600087803b1580156128ab57600080fd5b505af11580156128bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e39190614fa9565b50505b6040517fda5139ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063da5139ca9061297d907f0000000000000000000000000000000000000000000000000000000000000000908990600190600401615365565b60206040518083038186803b15801561299557600080fd5b505afa1580156129a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129cd9190614f91565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90612a68907f000000000000000000000000000000000000000000000000000000000000000090339030908790600401615232565b600060405180830381600087803b158015612a8257600080fd5b505af1158015612a96573d6000803e3d6000fd5b5050505050505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60105481565b600c5467ffffffffffffffff808216916fffffffffffffffffffffffffffffffff680100000000000000008204169178010000000000000000000000000000000000000000000000009091041683565b600e5481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60035473ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b6006546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b60005473ffffffffffffffffffffffffffffffffffffffff163314612c06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615584565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fcf1d3f17e521c635e0d20b8acba94ba170afc041d0546d46dafa09d3c9c19eb390600090a250565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612cdb57600080fd5b505afa158015612cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d1391906148b5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612d77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615403565b6040805180820182526fffffffffffffffffffffffffffffffff8481168083528482166020909301839052600680547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016909117909116700100000000000000000000000000000000909202919091179055517ff1fce436bc22563026222b3b2bdc088cb69d25192974264114df12ab812628f690610b3d90849084906157c3565b612e21614774565b5060408051606081018252600c5467ffffffffffffffff8082168084526fffffffffffffffffffffffffffffffff6801000000000000000084041660208501527801000000000000000000000000000000000000000000000000909204169282019290925290420380612e955750506131bd565b67ffffffffffffffff42168252612eaa61475d565b50604080518082019091526008546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041660208201819052612fbf5750508051600c8054602084015160409094015167ffffffffffffffff90811678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff90961668010000000000000000027fffffffffffffffff00000000000000000000000000000000ffffffffffffffff929095167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909316929092171692909217929092161790556131bd565b6000613015670de0b6b3a7640000613008856122b1886040015167ffffffffffffffff1687600001516fffffffffffffffffffffffffffffffff1661448b90919063ffffffff16565b8161300f57fe5b046144dc565b8251909150613036906fffffffffffffffffffffffffffffffff168261457e565b6fffffffffffffffffffffffffffffffff9081168352602085015161305c91168261457e565b6fffffffffffffffffffffffffffffffff9081166020808701829052845160088054928701518516700100000000000000000000000000000000029185167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090931692909217909316929092179091558451600c805460408089015167ffffffffffffffff90811678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff680100000000000000009097027fffffffffffffffff00000000000000000000000000000000ffffffffffffffff929096167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009094169390931716939093179390931692909217909155517fee527de5e142bcc7fe0eddc4b9a04816d73f6307dd74f9204585910d60a8c083906131b09083906157a6565b60405180910390a1505050505b565b604080518082019091526008546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000090910416602082015260009061320c908360016145d0565b8151600880546020948501516fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000029381167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216919091171691909117905573ffffffffffffffffffffffffffffffffffffffff86166000908152600a9092526040909120549091506132a5908361444e565b73ffffffffffffffffffffffffffffffffffffffff8086166000908152600a60205260408082209390935591517fda5139ca0000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000009091169063da5139ca90613353907f0000000000000000000000000000000000000000000000000000000000000000908690600190600401615365565b60206040518083038186803b15801561336b57600080fd5b505afa15801561337f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a39190614f91565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc7f00000000000000000000000000000000000000000000000000000000000000008661340d573361342f565b7f00000000000000000000000000000000000000000000000000000000000000005b30856040518563ffffffff1660e01b81526004016134509493929190615232565b600060405180830381600087803b15801561346a57600080fd5b505af115801561347e573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff16846134a457336134c6565b7f00000000000000000000000000000000000000000000000000000000000000005b73ffffffffffffffffffffffffffffffffffffffff167fc8e512d8f188ca059984b5853d2bf653da902696b8512785b182b2c813789a6e848660405161350d9291906157ef565b60405180910390a3509392505050565b6000806000620186a061353b6010548661448b90919063ffffffff16565b8161354257fe5b0490506135986135528583614267565b604080518082019091526008546fffffffffffffffffffffffffffffffff8082168352700100000000000000000000000000000000909104166020820152906001614669565b8151600880546020909401516fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000029281167fffffffffffffffffffffffffffffffff000000000000000000000000000000009095169490941790931617909155925061360761475d565b50604080518082019091526006546fffffffffffffffffffffffffffffffff80821680845270010000000000000000000000000000000090920481166020840152600854161115613684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615701565b600c546136af906801000000000000000090046fffffffffffffffffffffffffffffffff168361457e565b600c80546fffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffffffffffff00000000000000000000000000000000ffffffffffffffff909216919091179055336000908152600a60205260408120546137179086614267565b905081602001516fffffffffffffffffffffffffffffffff16811115613769576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615701565b336000908152600a6020526040808220839055517fda5139ca0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169163da5139ca9161380f917f0000000000000000000000000000000000000000000000000000000000000000918b9190600401615365565b60206040518083038186803b15801561382757600080fd5b505afa15801561383b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061385f9190614f91565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815290945073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc906138fa907f00000000000000000000000000000000000000000000000000000000000000009030908c908a90600401615232565b600060405180830381600087803b15801561391457600080fd5b505af1158015613928573d6000803e3d6000fd5b50505073ffffffffffffffffffffffffffffffffffffffff88169050337fb92cb6bca8e3270b9170930f03b17571e55791acdb1a0e9f339eec88bdb35e246139708987614267565b8860405161397f9291906157ef565b60405180910390a35050509250929050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a6020526040812054806139c6576001915050613b5d565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260096020526040902054806139fc57600092505050613b5d565b613a0461475d565b50604080518082019091526008546fffffffffffffffffffffffffffffffff808216808452700100000000000000000000000000000000909204166020830181905290613a589087906122b190879061448b565b81613a5f57fe5b047f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166356623118600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613ae5600e546122b1620186a0670de0b6b3a764000081613adc57fe5b8a91900461448b565b60006040518463ffffffff1660e01b8152600401613b0593929190615365565b60206040518083038186803b158015613b1d57600080fd5b505afa158015613b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b559190614f91565b101593505050505b92915050565b600080841215613ba1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8414613b9a5781613b9c565b825b6108c8565b509192915050565b33600090815260096020526040902054613bc3908261444e565b33600090815260096020526040902055600754613be0908261444e565b60075560405173ffffffffffffffffffffffffffffffffffffffff83169033907f8ad4d3ff00da092c7ad9a573ea4f5f6a3dffc6712dc06d3f78f49b862297c40290613c2d9085906157e6565b60405180910390a36003546040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169263f18d03cc92613cb4929190911690309087908790600401615232565b600060405180830381600087803b158015613cce57600080fd5b505af1158015613ce2573d6000803e3d6000fd5b505050505050565b60008060008060008089806020019051810190613d079190614cd6565b9350935093509350613d1a828989613b63565b9150613d27818989613b63565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166302b9446c8a86338787876040518763ffffffff1660e01b8152600401613d8b959493929190615269565b60408051808303818588803b158015613da357600080fd5b505af1158015613db7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613ddc9190614fa9565b955095505050505094509492505050565b60008060008060008088806020019051810190613e0a9190614cd6565b93509350935093507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166397da6d30853386613e5c878e8e613b63565b613e67878f8f613b63565b6040518663ffffffff1660e01b8152600401613e87959493929190615269565b6040805180830381600087803b158015613ea057600080fd5b505af1158015613eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ed89190614fa9565b9550955050505050935093915050565b60606000806060600080600089806020019051810190613f08919061493e565b94509450945094509450828015613f1d575081155b15613f4b578389604051602001613f35929190615052565b6040516020818303038152906040529350613fa4565b82158015613f565750815b15613f6e578388604051602001613f35929190615052565b828015613f785750815b15613fa457838989604051602001613f9293929190615074565b60405160208183030381529060405293505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614158015614016575073ffffffffffffffffffffffffffffffffffffffff85163014155b61404c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615625565b600060608673ffffffffffffffffffffffffffffffffffffffff168d876040516140769190615036565b60006040518083038185875af1925050503d80600081146140b3576040519150601f19603f3d011682016040523d82523d6000602084013e6140b8565b606091505b5091509150816140f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107709061543a565b9c919b50909950505050505050505050565b600083602001516fffffffffffffffffffffffffffffffff166000141561412e5750816141c3565b602084015184516fffffffffffffffffffffffffffffffff918216916141569186911661448b565b8161415d57fe5b0490508180156141b357508284600001516fffffffffffffffffffffffffffffffff166141a986602001516fffffffffffffffffffffffffffffffff168461448b90919063ffffffff16565b816141b057fe5b04105b156141c3576108c8816001614267565b9392505050565b82516000906fffffffffffffffffffffffffffffffff166141ec5750816141c3565b835160208501516fffffffffffffffffffffffffffffffff918216916142149186911661448b565b8161421b57fe5b0490508180156141b357508284602001516fffffffffffffffffffffffffffffffff166141a986600001516fffffffffffffffffffffffffffffffff168461448b90919063ffffffff16565b81810181811015613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615516565b801561439d5761435f827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f7888aec87306040518363ffffffff1660e01b815260040161430992919061520b565b60206040518083038186803b15801561432157600080fd5b505afa158015614335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143599190614f91565b9061444e565b831115614398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615693565b614448565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90614415908790339030908990600401615232565b600060405180830381600087803b15801561442f57600080fd5b505af1158015614443573d6000803e3d6000fd5b505050505b50505050565b80820382811115613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615395565b60008115806144a6575050808202828282816144a357fe5b04145b613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615738565b60006fffffffffffffffffffffffffffffffff821115614528576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906154a8565b5090565b8082036fffffffffffffffffffffffffffffffff8084169082161115613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615395565b8181016fffffffffffffffffffffffffffffffff8083169082161015613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615516565b6145d861475d565b60006145e5858585614106565b905061460d6145f3826144dc565b86516fffffffffffffffffffffffffffffffff169061452c565b6fffffffffffffffffffffffffffffffff16855261464a61462d856144dc565b60208701516fffffffffffffffffffffffffffffffff169061452c565b6fffffffffffffffffffffffffffffffff166020860152939492505050565b61467161475d565b600061467e8585856141ca565b90506146a661468c856144dc565b86516fffffffffffffffffffffffffffffffff169061457e565b6fffffffffffffffffffffffffffffffff16855261464a6146c6826144dc565b60208701516fffffffffffffffffffffffffffffffff169061457e565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061472457805160ff1916838001178555614751565b82800160010185558215614751579182015b82811115614751578251825591602001919060010190614736565b50614528929150614794565b604080518082019091526000808252602082015290565b604080516060810182526000808252602082018190529181019190915290565b5b808211156145285760008155600101614795565b8035613b5d81615988565b60008083601f8401126147c5578182fd5b50813567ffffffffffffffff8111156147dc578182fd5b60208301915083602080830285010111156147f657600080fd5b9250929050565b600082601f83011261480d578081fd5b813561482061481b826158ee565b6158c7565b81815291506020808301908481018184028601820187101561484157600080fd5b60005b8481101561486057813584529282019290820190600101614844565b505050505092915050565b8051613b5d816159ad565b803567ffffffffffffffff81168114613b5d57600080fd5b8051613b5d816159d9565b6000602082840312156148aa578081fd5b81356141c381615988565b6000602082840312156148c6578081fd5b81516141c381615988565b60008060008060008060c087890312156148e9578182fd5b86356148f481615988565b9550602087013561490481615988565b94506040870135614914816159ad565b93506060870135614924816159d9565b9598949750929560808101359460a0909101359350915050565b600080600080600060a08688031215614955578283fd5b855161496081615988565b602087015190955067ffffffffffffffff81111561497c578384fd5b8601601f8101881361498c578384fd5b805161499a61481b8261590e565b8181528960208385010111156149ae578586fd5b6149bf82602083016020860161595c565b8096505050506149d2876040880161486b565b92506149e1876060880161486b565b91506149f0876080880161488e565b90509295509295909350565b600080600060608486031215614a10578081fd5b8335614a1b81615988565b92506020840135614a2b816159ad565b91506040840135614a3b816159ad565b809150509250925092565b600080600060608486031215614a5a578081fd5b8335614a6581615988565b92506020840135614a75816159ad565b929592945050506040919091013590565b60008060408385031215614a98578182fd5b8235614aa381615988565b946020939093013593505050565b60008060008060008060808789031215614ac9578384fd5b863567ffffffffffffffff80821115614ae0578586fd5b614aec8a838b016147b4565b90985096506020890135915080821115614b04578586fd5b50614b1189828a016147b4565b9095509350506040870135614b2581615988565b91506060870135614b3581615988565b809150509295509295509295565b60008060008060008060608789031215614b5b578384fd5b863567ffffffffffffffff80821115614b72578586fd5b614b7e8a838b016147b4565b90985096506020890135915080821115614b96578586fd5b614ba28a838b016147b4565b90965094506040890135915080821115614bba578384fd5b50614bc789828a016147b4565b979a9699509497509295939492505050565b60008060408385031215614beb578182fd5b8251614bf6816159ad565b6020939093015192949293505050565b600080600060608486031215614c1a578081fd5b8335614c25816159ad565b95602085013595506040909401359392505050565b60008060208385031215614c4c578182fd5b823567ffffffffffffffff80821115614c63578384fd5b818501915085601f830112614c76578384fd5b813581811115614c84578485fd5b866020828501011115614c95578485fd5b60209290920196919550909350505050565b600080600060608486031215614cbb578081fd5b8335614cc681615988565b92506020840135614a7581615988565b60008060008060808587031215614ceb578182fd5b8451614cf681615988565b6020860151909450614d0781615988565b6040860151606090960151949790965092505050565b600080600060608486031215614d31578081fd5b8335614d3c81615988565b925060208481013567ffffffffffffffff80821115614d59578384fd5b818701915087601f830112614d6c578384fd5b8135614d7a61481b826158ee565b81815284810190848601868402860187018c1015614d96578788fd5b8795505b83861015614dc057614dac8c826147a9565b835260019590950194918601918601614d9a565b50965050506040870135925080831115614dd8578384fd5b5050614de6868287016147fd565b9150509250925092565b600080600080600080600060e0888a031215614e0a578485fd5b8735614e1581615988565b96506020880135614e2581615988565b9550604088013567ffffffffffffffff811115614e40578586fd5b8801601f81018a13614e50578586fd5b8035614e5e61481b8261590e565b8181528b6020838501011115614e72578788fd5b816020840160208301379081016020019690965250614e948960608a01614876565b9699959850939660808101359560a0820135955060c0909101359350915050565b600060208284031215614ec6578081fd5b5035919050565b60008060408385031215614edf578182fd5b823591506020830135614ef181615988565b809150509250929050565b600080600060608486031215614f10578081fd5b833592506020840135614a2b81615988565b600060408284031215614f33578081fd5b614f3d60406158c7565b8251614f48816159bb565b81526020830151614f58816159bb565b60208201529392505050565b60008060408385031215614f76578182fd5b8235614f81816159bb565b91506020830135614ef1816159bb565b600060208284031215614fa2578081fd5b5051919050565b60008060408385031215614fbb578182fd5b505080516020909101519092909150565b600060208284031215614fdd578081fd5b813567ffffffffffffffff811681146141c3578182fd5b600060208284031215615005578081fd5b81356141c3816159d9565b73ffffffffffffffffffffffffffffffffffffffff16815260200190565b815260200190565b6000825161504881846020870161595c565b9190910192915050565b6000835161506481846020880161595c565b9190910191825250602001919050565b6000845161508681846020890161595c565b91909101928352506020820152604001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff9687168152949095166020850152911515604084015260ff166060830152608082015260a081019190915260c00190565b9115158252602082015260400190565b600060208252825180602084015261513181604085016020870161595c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602080830181845282855460018082166000811461518a57600181146151c6576151fe565b607f600284041685527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00831660408901526060880193506151fe565b600283048086526151d68a615950565b885b828110156151f45781548b8201604001529084019088016151d8565b8a01604001955050505b5091979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015292166040820152606081019190915260800190565b73ffffffffffffffffffffffffffffffffffffffff958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b60006080820173ffffffffffffffffffffffffffffffffffffffff80881684526020818816818601526080604086015282915086516152e981856157e6565b92508188019350845b8181101561531357615305848651615010565b9483019493506001016152f2565b50508482036060860152819250855161532c81846157e6565b93508187019250845b818110156153565761534885855161502e565b945092820192600101615335565b50929998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff93909316835260208301919091521515604082015260600190565b60208082526015908201527f426f72696e674d6174683a20556e646572666c6f770000000000000000000000604082015260600190565b60208082526018908201527f4361756c64726f6e3a207573657220696e736f6c76656e740000000000000000604082015260600190565b60208082526017908201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b60208082526015908201527f4361756c64726f6e3a2063616c6c206661696c65640000000000000000000000604082015260600190565b60208082526015908201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604082015260600190565b6020808252601c908201527f426f72696e674d6174683a2075696e74313238204f766572666c6f7700000000604082015260600190565b60208082526019908201527f4361756c64726f6e3a20616c6c2061726520736f6c76656e7400000000000000604082015260600190565b60208082526018908201527f426f72696e674d6174683a20416464204f766572666c6f770000000000000000604082015260600190565b60208082526018908201527f557064617465206f6e6c79206576657279203320646179730000000000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e6572604082015260600190565b6020808252601c908201527f496e746572657374207261746520696e637265617365203e2037352500000000604082015260600190565b60208082526014908201527f4361756c64726f6e3a2063616e27742063616c6c000000000000000000000000604082015260600190565b6020808252601d908201527f4361756c64726f6e3a20616c726561647920696e697469616c697a6564000000604082015260600190565b60208082526017908201527f4361756c64726f6e3a20536b696d20746f6f206d756368000000000000000000604082015260600190565b60208082526012908201527f4361756c64726f6e3a2062616420706169720000000000000000000000000000604082015260600190565b60208082526014908201527f426f72726f77204c696d69742072656163686564000000000000000000000000604082015260600190565b60208082526018908201527f426f72696e674d6174683a204d756c204f766572666c6f770000000000000000604082015260600190565b60208082526015908201527f4361756c64726f6e3a2072617465206e6f74206f6b0000000000000000000000604082015260600190565b6fffffffffffffffffffffffffffffffff91909116815260200190565b6fffffffffffffffffffffffffffffffff92831681529116602082015260400190565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b67ffffffffffffffff93841681526fffffffffffffffffffffffffffffffff929092166020830152909116604082015260600190565b67ffffffffffffffff92831681529116602082015260400190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615898578283fd5b83018035915067ffffffffffffffff8211156158b2578283fd5b6020019150368190038213156147f657600080fd5b60405181810167ffffffffffffffff811182821017156158e657600080fd5b604052919050565b600067ffffffffffffffff821115615904578081fd5b5060209081020190565b600067ffffffffffffffff821115615924578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60009081526020902090565b60005b8381101561597757818101518382015260200161595f565b838111156144485750506000910152565b73ffffffffffffffffffffffffffffffffffffffff811681146159aa57600080fd5b50565b80151581146159aa57600080fd5b6fffffffffffffffffffffffffffffffff811681146159aa57600080fd5b60ff811681146159aa57600080fdfea2646970667358221220078881611528a34bc39f9fa8079eb355ad4b339a474b4891d87f23da01500c2864736f6c634300060c0033", + "deployedBytecode": "0x6080604052600436106102345760003560e01c80637dc0d1d011610138578063b27c0e74116100b0578063e30c39781161007f578063f46901ed11610064578063f46901ed146105ae578063f7dad434146105ce578063f8ba4cff146105ee57610234565b8063e30c397814610584578063e551d11d1461059957610234565b8063b27c0e7414610521578063c7ee2a7b14610545578063cd446e221461055a578063d8dfeb451461056f57610234565b8063876467f811610107578063912860c5116100ec578063912860c5146104d75780639b352ae1146104f7578063aba024f41461050c57610234565b8063876467f8146104a25780638da5cb5b146104c257610234565b80637dc0d1d01461042a578063806234441461043f5780638285ef401461045f578063860ffea11461048257610234565b8063476343ee116101cb5780634e71e0c81161019a5780636b2ace871161017f5780636b2ace87146103de5780636ec097fb146103f357806374645ff31461040857610234565b80634e71e0c8146103b6578063656f3d64146103cb57610234565b8063476343ee1461034057806348e4163e146103555780634b8a3529146103755780634ddf47d4146103a357610234565b80631c9e379b116102075780631c9e379b146102d65780631cd4c966146102f65780633ba0b9a914610316578063473e3ce71461032b57610234565b8063017e7e581461023957806302ce728f14610264578063078dfbe71461028757806315294c40146102a9575b600080fd5b34801561024557600080fd5b5061024e610603565b60405161025b919061509b565b60405180910390f35b34801561027057600080fd5b5061027961061f565b60405161025b929190615102565b34801561029357600080fd5b506102a76102a23660046149fc565b61071f565b005b3480156102b557600080fd5b506102c96102c4366004614a46565b6108b3565b60405161025b91906157e6565b3480156102e257600080fd5b506102c96102f1366004614899565b6108d0565b34801561030257600080fd5b506102a7610311366004614fcc565b6108e2565b34801561032257600080fd5b506102c9610b49565b34801561033757600080fd5b506102c9610b4f565b34801561034c57600080fd5b506102a7610b55565b34801561036157600080fd5b506102c9610370366004614899565b610e55565b34801561038157600080fd5b50610395610390366004614a86565b610e67565b60405161025b9291906157ef565b6102a76103b1366004614c3a565b610ed6565b3480156103c257600080fd5b506102a7611126565b6103956103d9366004614b43565b61120c565b3480156103ea57600080fd5b5061024e611b46565b3480156103ff57600080fd5b506102c9611b6a565b34801561041457600080fd5b5061041d611b70565b60405161025b9190615112565b34801561043657600080fd5b5061024e611c1c565b34801561044b57600080fd5b506102a761045a366004614eb5565b611c38565b34801561046b57600080fd5b50610474611eaa565b60405161025b9291906157c3565b34801561048e57600080fd5b506102a761049d366004614a46565b611eda565b3480156104ae57600080fd5b506102a76104bd366004614a86565b611ffc565b3480156104ce57600080fd5b5061024e61205b565b3480156104e357600080fd5b506102a76104f2366004614ab1565b612077565b34801561050357600080fd5b5061024e612aa9565b34801561051857600080fd5b506102c9612acd565b34801561052d57600080fd5b50610536612ad3565b60405161025b93929190615813565b34801561055157600080fd5b506102c9612b23565b34801561056657600080fd5b5061024e612b29565b34801561057b57600080fd5b5061024e612b4d565b34801561059057600080fd5b5061024e612b69565b3480156105a557600080fd5b50610474612b85565b3480156105ba57600080fd5b506102a76105c9366004614899565b612bb5565b3480156105da57600080fd5b506102a76105e9366004614f64565b612c75565b3480156105fa57600080fd5b506102a7612e19565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b600480546040517fd6d7d525000000000000000000000000000000000000000000000000000000008152600092839273ffffffffffffffffffffffffffffffffffffffff169163d6d7d525916106789160059101615163565b6040805180830381600087803b15801561069157600080fd5b505af11580156106a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c99190614bd9565b9092509050811561071657600b8190556040517f9f9192b5edb17356c524e08d9e025c8e2f6307e6ea52fb7968faa3081f51c3c8906107099083906157e6565b60405180910390a161071b565b50600b545b9091565b60005473ffffffffffffffffffffffffffffffffffffffff163314610779576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615584565b60405180910390fd5b811561086d5773ffffffffffffffffffffffffffffffffffffffff83161515806107a05750805b6107d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615471565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808716939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff85167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556001805490911690556108ae565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85161790555b505050565b60006108bd612e19565b6108c88484846131bf565b949350505050565b60096020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561094857600080fd5b505afa15801561095c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098091906148b5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615403565b600c5467ffffffffffffffff7801000000000000000000000000000000000000000000000000909104811690600490600383021604810167ffffffffffffffff168267ffffffffffffffff161080610a4a57506312e687c067ffffffffffffffff831611155b610a80576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906155ee565b42600d546203f4800110610ac0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107709061554d565b42600d55600c805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8516021790556040517f76bc92b92b7755bcb03b25070431a80435c4d3fbf91c6c81c0c0cc350f6b5c6a90610b3d9083908590615849565b60405180910390a15050565b600b5481565b60075481565b610b5d612e19565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b158015610bc557600080fd5b505afa158015610bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfd91906148b5565b600c546040517fda5139ca0000000000000000000000000000000000000000000000000000000081529192506801000000000000000090046fffffffffffffffffffffffffffffffff16906000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063da5139ca90610cbb907f00000000000000000000000000000000000000000000000000000000000000009086908690600401615365565b60206040518083038186803b158015610cd357600080fd5b505afa158015610ce7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0b9190614f91565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90610da6907f000000000000000000000000000000000000000000000000000000000000000090309088908790600401615232565b600060405180830381600087803b158015610dc057600080fd5b505af1158015610dd4573d6000803e3d6000fd5b5050600c80547fffffffffffffffff00000000000000000000000000000000ffffffffffffffff169055505060405173ffffffffffffffffffffffffffffffffffffffff8416907fbe641c3ffc44b2d6c184f023fa4ed7bda4b6ffa71e03b3c98ae0c776da1f17e790610e489085906157e6565b60405180910390a2505050565b600a6020526000908152604090205481565b600080610e72612e19565b610e7c848461351d565b90925090506000610e8b61061f565b915050610e983382613991565b610ece576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906153cc565b509250929050565b60035473ffffffffffffffffffffffffffffffffffffffff1615610f26576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107709061565c565b610f3281830183614df0565b6010819055600e829055600f839055600c805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff87160217905584516003906000906004908290610fa69060059060208c01906146e3565b50815461010091820a73ffffffffffffffffffffffffffffffffffffffff818102199092169b8216029a909a17909155825491900a8089021990911698881602979097179096555050604080518082019091526fffffffffffffffffffffffffffffffff80825260209091015250507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6006556003541615159050611077576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906156ca565b600480546040517fd6d7d52500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169163d6d7d525916110cd9160059101615163565b6040805180830381600087803b1580156110e657600080fd5b505af11580156110fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111e9190614bd9565b600b55505050565b60015473ffffffffffffffffffffffffffffffffffffffff16338114611178576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906155b9565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055600180549091169055565b60008061121761475d565b60005b88811015611ae35760008a8a8381811061123057fe5b90506020020160208101906112459190614ff4565b9050826020015115801561125c5750600a8160ff16105b1561127157611269612e19565b600160208401525b60ff8116600a14156112cb57600080600089898681811061128e57fe5b90506020028101906112a09190615864565b8101906112ad9190614efc565b9250925092506112c3828261049d868c8c613b63565b505050611ada565b60ff81166002141561132b5760008060008989868181106112e857fe5b90506020028101906112fa9190615864565b8101906113079190614efc565b925092509250611322828261131d868c8c613b63565b6131bf565b50505050611ada565b60ff8116600414156113885760008088888581811061134657fe5b90506020028101906113589190615864565b8101906113659190614ecd565b9150915061137d81611378848a8a613b63565b613ba9565b505060018352611ada565b60ff8116600514156113eb576000808888858181106113a357fe5b90506020028101906113b59190615864565b8101906113c29190614ecd565b915091506113da816113d5848a8a613b63565b61351d565b600187529097509550611ada915050565b60ff8116600b14156114a457600080600089898681811061140857fe5b905060200281019061141a9190615864565b8101906114279190614c06565b92509250925060008061143861061f565b915091508415806114465750815b801561145157508381115b8015611464575082158061146457508281115b61149a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107709061576f565b5050505050611ada565b60ff811660181415611590576000806000806000808c8c898181106114c557fe5b90506020028101906114d79190615864565b8101906114e491906148d1565b9550955095509550955095507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663c0a47c938787878787876040518763ffffffff1660e01b8152600401611553969594939291906150bc565b600060405180830381600087803b15801561156d57600080fd5b505af1158015611581573d6000803e3d6000fd5b50505050505050505050611ada565b60ff8116601414156116185761160e8787848181106115ab57fe5b90506020028101906115bd9190615864565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d92508c915086905081811061160057fe5b905060200201358787613cea565b9095509350611ada565b60ff8116601514156116835761160e87878481811061163357fe5b90506020028101906116459190615864565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250899250889150613ded9050565b60ff8116601614156117685760008060008989868181106116a057fe5b90506020028101906116b29190615864565b8101906116bf9190614ca7565b9250925092507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc84338561170f868e8e613b63565b6040518563ffffffff1660e01b815260040161172e9493929190615232565b600060405180830381600087803b15801561174857600080fd5b505af115801561175c573d6000803e3d6000fd5b50505050505050611ada565b60ff81166017141561180957600060608089898681811061178557fe5b90506020028101906117979190615864565b8101906117a49190614d1d565b9250925092507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630fca8843843385856040518563ffffffff1660e01b815260040161172e94939291906152aa565b60ff8116601e14156118e3576060600061188b8b8b8681811061182857fe5b905060200201358a8a8781811061183b57fe5b905060200281019061184d9190615864565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c92508b9150613ee89050565b915091508060ff16600114156118b657818060200190518101906118af9190614f91565b96506118dc565b8060ff16600214156118dc57818060200190518101906118d69190614fa9565b90975095505b5050611ada565b60ff811660061415611a475760008787848181106118fd57fe5b905060200281019061190f9190615864565b81019061191c9190614eb5565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663da5139ca7f00000000000000000000000000000000000000000000000000000000000000006119cf611989858b8b613b63565b604080518082019091526008546fffffffffffffffffffffffffffffffff8082168352700100000000000000000000000000000000909104166020820152906001614106565b60016040518463ffffffff1660e01b81526004016119ef93929190615365565b60206040518083038186803b158015611a0757600080fd5b505afa158015611a1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3f9190614f91565b955050611ada565b60ff811660071415611ada576000878784818110611a6157fe5b9050602002810190611a739190615864565b810190611a809190614eb5565b9050611ad6611a90828888613b63565b604080518082019091526008546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041660208201529060006141ca565b9550505b5060010161121a565b50805115611b3a576000611af561061f565b915050611b023382613991565b611b38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906153cc565b505b50965096945050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600f5481565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f81018490048402820184019092528181529291830182828015611c145780601f10611be957610100808354040283529160200191611c14565b820191906000526020600020905b815481529060010190602001808311611bf757829003601f168201915b505050505081565b60045473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9e57600080fd5b505afa158015611cb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd691906148b5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615403565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166397da6d307f0000000000000000000000000000000000000000000000000000000000000000307f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611dfe57600080fd5b505afa158015611e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3691906148b5565b8560006040518663ffffffff1660e01b8152600401611e59959493929190615269565b6040805180830381600087803b158015611e7257600080fd5b505af1158015611e86573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190614fa9565b6008546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260096020526040902054611f0a9082614267565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260096020526040902055600754611f3d8183614267565b600755600354611f659073ffffffffffffffffffffffffffffffffffffffff168383866142a4565b8373ffffffffffffffffffffffffffffffffffffffff1683611f875733611fa9565b7f00000000000000000000000000000000000000000000000000000000000000005b73ffffffffffffffffffffffffffffffffffffffff167f9ed03113de523cebfe5e49d5f8e12894b1c0d42ce805990461726444c90eab8784604051611fee91906157e6565b60405180910390a350505050565b612004612e19565b61200e8282613ba9565b600061201861061f565b9150506120253382613991565b6108ae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906153cc565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b600061208161061f565b91505061208c612e19565b600080600061209961475d565b50604080518082019091526008546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041660208201526120e061475d565b6003546040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692634ffe34db9261215992919091169060040161509b565b604080518083038186803b15801561217057600080fd5b505afa158015612184573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a89190614f22565b905060005b8b81101561247c5760008d8d838181106121c357fe5b90506020020160208101906121d89190614899565b90506121e48189613991565b6124735773ffffffffffffffffffffffffffffffffffffffff81166000908152600a6020526040812054808e8e8681811061221b57fe5b905060200201351161223f578d8d8581811061223357fe5b90506020020135612241565b805b915061224d818361444e565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600a60205260408120919091559050612283868383614106565b905060006122c9670de0b6b3a7640000620186a0026122b78d6122b1600f548761448b90919063ffffffff16565b9061448b565b816122be57fe5b8891900460006141ca565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600960205260409020549091506122fc908261444e565b73ffffffffffffffffffffffffffffffffffffffff80861660008181526009602052604090819020939093559151908f1691907f8ad4d3ff00da092c7ad9a573ea4f5f6a3dffc6712dc06d3f78f49b862297c4029061235c9085906157e6565b60405180910390a38373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fc8e512d8f188ca059984b5853d2bf653da902696b8512785b182b2c813789a6e84866040516123c39291906157ef565b60405180910390a38c73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f66b108dc29b952efc76dccea9b82dce6b59fab4d9af73d8dcc9789afcad5daf6848688604051612443939291906157fd565b60405180910390a46124558a82614267565b99506124618983614267565b985061246d8884614267565b97505050505b506001016121ad565b50836124b4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906154df565b6124da6124c0856144dc565b83516fffffffffffffffffffffffffffffffff169061452c565b6fffffffffffffffffffffffffffffffff1682526125176124fa846144dc565b60208401516fffffffffffffffffffffffffffffffff169061452c565b6fffffffffffffffffffffffffffffffff908116602084018190528351600880547fffffffffffffffffffffffffffffffff000000000000000000000000000000001691841691909117909216700100000000000000000000000000000000909102179055600754612589908661444e565b600781905550600060646125c3600a6122b188620186a06125b5600f548c61448b90919063ffffffff16565b816125bc57fe5b049061444e565b816125ca57fe5b0490506125d78582614267565b945061260c6125e5826144dc565b600c546801000000000000000090046fffffffffffffffffffffffffffffffff169061457e565b600c80546fffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffffffffffff00000000000000000000000000000000ffffffffffffffff909216919091179055506040517fda5139ca00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063da5139ca906126f5907f0000000000000000000000000000000000000000000000000000000000000000908990600190600401615365565b60206040518083038186803b15801561270d57600080fd5b505afa158015612721573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127459190614f91565b6003546040517ff18d03cc00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169263f18d03cc926127c492169030908e908c90600401615232565b600060405180830381600087803b1580156127de57600080fd5b505af11580156127f2573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff8816156128e6576003546040517fe343fe1200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a81169263e343fe129261289292909116907f000000000000000000000000000000000000000000000000000000000000000090339087908d90600401615269565b6040805180830381600087803b1580156128ab57600080fd5b505af11580156128bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e39190614fa9565b50505b6040517fda5139ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063da5139ca9061297d907f0000000000000000000000000000000000000000000000000000000000000000908990600190600401615365565b60206040518083038186803b15801561299557600080fd5b505afa1580156129a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129cd9190614f91565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90612a68907f000000000000000000000000000000000000000000000000000000000000000090339030908790600401615232565b600060405180830381600087803b158015612a8257600080fd5b505af1158015612a96573d6000803e3d6000fd5b5050505050505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60105481565b600c5467ffffffffffffffff808216916fffffffffffffffffffffffffffffffff680100000000000000008204169178010000000000000000000000000000000000000000000000009091041683565b600e5481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60035473ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b6006546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b60005473ffffffffffffffffffffffffffffffffffffffff163314612c06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615584565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fcf1d3f17e521c635e0d20b8acba94ba170afc041d0546d46dafa09d3c9c19eb390600090a250565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015612cdb57600080fd5b505afa158015612cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d1391906148b5565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612d77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615403565b6040805180820182526fffffffffffffffffffffffffffffffff8481168083528482166020909301839052600680547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016909117909116700100000000000000000000000000000000909202919091179055517ff1fce436bc22563026222b3b2bdc088cb69d25192974264114df12ab812628f690610b3d90849084906157c3565b612e21614774565b5060408051606081018252600c5467ffffffffffffffff8082168084526fffffffffffffffffffffffffffffffff6801000000000000000084041660208501527801000000000000000000000000000000000000000000000000909204169282019290925290420380612e955750506131bd565b67ffffffffffffffff42168252612eaa61475d565b50604080518082019091526008546fffffffffffffffffffffffffffffffff80821683527001000000000000000000000000000000009091041660208201819052612fbf5750508051600c8054602084015160409094015167ffffffffffffffff90811678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff6fffffffffffffffffffffffffffffffff90961668010000000000000000027fffffffffffffffff00000000000000000000000000000000ffffffffffffffff929095167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909316929092171692909217929092161790556131bd565b6000613015670de0b6b3a7640000613008856122b1886040015167ffffffffffffffff1687600001516fffffffffffffffffffffffffffffffff1661448b90919063ffffffff16565b8161300f57fe5b046144dc565b8251909150613036906fffffffffffffffffffffffffffffffff168261457e565b6fffffffffffffffffffffffffffffffff9081168352602085015161305c91168261457e565b6fffffffffffffffffffffffffffffffff9081166020808701829052845160088054928701518516700100000000000000000000000000000000029185167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090931692909217909316929092179091558451600c805460408089015167ffffffffffffffff90811678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff680100000000000000009097027fffffffffffffffff00000000000000000000000000000000ffffffffffffffff929096167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009094169390931716939093179390931692909217909155517fee527de5e142bcc7fe0eddc4b9a04816d73f6307dd74f9204585910d60a8c083906131b09083906157a6565b60405180910390a1505050505b565b604080518082019091526008546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000090910416602082015260009061320c908360016145d0565b8151600880546020948501516fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000029381167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216919091171691909117905573ffffffffffffffffffffffffffffffffffffffff86166000908152600a9092526040909120549091506132a5908361444e565b73ffffffffffffffffffffffffffffffffffffffff8086166000908152600a60205260408082209390935591517fda5139ca0000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000009091169063da5139ca90613353907f0000000000000000000000000000000000000000000000000000000000000000908690600190600401615365565b60206040518083038186803b15801561336b57600080fd5b505afa15801561337f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133a39190614f91565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc7f00000000000000000000000000000000000000000000000000000000000000008661340d573361342f565b7f00000000000000000000000000000000000000000000000000000000000000005b30856040518563ffffffff1660e01b81526004016134509493929190615232565b600060405180830381600087803b15801561346a57600080fd5b505af115801561347e573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff16846134a457336134c6565b7f00000000000000000000000000000000000000000000000000000000000000005b73ffffffffffffffffffffffffffffffffffffffff167fc8e512d8f188ca059984b5853d2bf653da902696b8512785b182b2c813789a6e848660405161350d9291906157ef565b60405180910390a3509392505050565b6000806000620186a061353b6010548661448b90919063ffffffff16565b8161354257fe5b0490506135986135528583614267565b604080518082019091526008546fffffffffffffffffffffffffffffffff8082168352700100000000000000000000000000000000909104166020820152906001614669565b8151600880546020909401516fffffffffffffffffffffffffffffffff908116700100000000000000000000000000000000029281167fffffffffffffffffffffffffffffffff000000000000000000000000000000009095169490941790931617909155925061360761475d565b50604080518082019091526006546fffffffffffffffffffffffffffffffff80821680845270010000000000000000000000000000000090920481166020840152600854161115613684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615701565b600c546136af906801000000000000000090046fffffffffffffffffffffffffffffffff168361457e565b600c80546fffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffffffffffff00000000000000000000000000000000ffffffffffffffff909216919091179055336000908152600a60205260408120546137179086614267565b905081602001516fffffffffffffffffffffffffffffffff16811115613769576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615701565b336000908152600a6020526040808220839055517fda5139ca0000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169163da5139ca9161380f917f0000000000000000000000000000000000000000000000000000000000000000918b9190600401615365565b60206040518083038186803b15801561382757600080fd5b505afa15801561383b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061385f9190614f91565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815290945073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc906138fa907f00000000000000000000000000000000000000000000000000000000000000009030908c908a90600401615232565b600060405180830381600087803b15801561391457600080fd5b505af1158015613928573d6000803e3d6000fd5b50505073ffffffffffffffffffffffffffffffffffffffff88169050337fb92cb6bca8e3270b9170930f03b17571e55791acdb1a0e9f339eec88bdb35e246139708987614267565b8860405161397f9291906157ef565b60405180910390a35050509250929050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a6020526040812054806139c6576001915050613b5d565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260096020526040902054806139fc57600092505050613b5d565b613a0461475d565b50604080518082019091526008546fffffffffffffffffffffffffffffffff808216808452700100000000000000000000000000000000909204166020830181905290613a589087906122b190879061448b565b81613a5f57fe5b047f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166356623118600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613ae5600e546122b1620186a0670de0b6b3a764000081613adc57fe5b8a91900461448b565b60006040518463ffffffff1660e01b8152600401613b0593929190615365565b60206040518083038186803b158015613b1d57600080fd5b505afa158015613b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b559190614f91565b101593505050505b92915050565b600080841215613ba1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8414613b9a5781613b9c565b825b6108c8565b509192915050565b33600090815260096020526040902054613bc3908261444e565b33600090815260096020526040902055600754613be0908261444e565b60075560405173ffffffffffffffffffffffffffffffffffffffff83169033907f8ad4d3ff00da092c7ad9a573ea4f5f6a3dffc6712dc06d3f78f49b862297c40290613c2d9085906157e6565b60405180910390a36003546040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169263f18d03cc92613cb4929190911690309087908790600401615232565b600060405180830381600087803b158015613cce57600080fd5b505af1158015613ce2573d6000803e3d6000fd5b505050505050565b60008060008060008089806020019051810190613d079190614cd6565b9350935093509350613d1a828989613b63565b9150613d27818989613b63565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166302b9446c8a86338787876040518763ffffffff1660e01b8152600401613d8b959493929190615269565b60408051808303818588803b158015613da357600080fd5b505af1158015613db7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613ddc9190614fa9565b955095505050505094509492505050565b60008060008060008088806020019051810190613e0a9190614cd6565b93509350935093507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166397da6d30853386613e5c878e8e613b63565b613e67878f8f613b63565b6040518663ffffffff1660e01b8152600401613e87959493929190615269565b6040805180830381600087803b158015613ea057600080fd5b505af1158015613eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ed89190614fa9565b9550955050505050935093915050565b60606000806060600080600089806020019051810190613f08919061493e565b94509450945094509450828015613f1d575081155b15613f4b578389604051602001613f35929190615052565b6040516020818303038152906040529350613fa4565b82158015613f565750815b15613f6e578388604051602001613f35929190615052565b828015613f785750815b15613fa457838989604051602001613f9293929190615074565b60405160208183030381529060405293505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614158015614016575073ffffffffffffffffffffffffffffffffffffffff85163014155b61404c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615625565b600060608673ffffffffffffffffffffffffffffffffffffffff168d876040516140769190615036565b60006040518083038185875af1925050503d80600081146140b3576040519150601f19603f3d011682016040523d82523d6000602084013e6140b8565b606091505b5091509150816140f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107709061543a565b9c919b50909950505050505050505050565b600083602001516fffffffffffffffffffffffffffffffff166000141561412e5750816141c3565b602084015184516fffffffffffffffffffffffffffffffff918216916141569186911661448b565b8161415d57fe5b0490508180156141b357508284600001516fffffffffffffffffffffffffffffffff166141a986602001516fffffffffffffffffffffffffffffffff168461448b90919063ffffffff16565b816141b057fe5b04105b156141c3576108c8816001614267565b9392505050565b82516000906fffffffffffffffffffffffffffffffff166141ec5750816141c3565b835160208501516fffffffffffffffffffffffffffffffff918216916142149186911661448b565b8161421b57fe5b0490508180156141b357508284602001516fffffffffffffffffffffffffffffffff166141a986600001516fffffffffffffffffffffffffffffffff168461448b90919063ffffffff16565b81810181811015613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615516565b801561439d5761435f827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f7888aec87306040518363ffffffff1660e01b815260040161430992919061520b565b60206040518083038186803b15801561432157600080fd5b505afa158015614335573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143599190614f91565b9061444e565b831115614398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615693565b614448565b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90614415908790339030908990600401615232565b600060405180830381600087803b15801561442f57600080fd5b505af1158015614443573d6000803e3d6000fd5b505050505b50505050565b80820382811115613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615395565b60008115806144a6575050808202828282816144a357fe5b04145b613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615738565b60006fffffffffffffffffffffffffffffffff821115614528576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610770906154a8565b5090565b8082036fffffffffffffffffffffffffffffffff8084169082161115613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615395565b8181016fffffffffffffffffffffffffffffffff8083169082161015613b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077090615516565b6145d861475d565b60006145e5858585614106565b905061460d6145f3826144dc565b86516fffffffffffffffffffffffffffffffff169061452c565b6fffffffffffffffffffffffffffffffff16855261464a61462d856144dc565b60208701516fffffffffffffffffffffffffffffffff169061452c565b6fffffffffffffffffffffffffffffffff166020860152939492505050565b61467161475d565b600061467e8585856141ca565b90506146a661468c856144dc565b86516fffffffffffffffffffffffffffffffff169061457e565b6fffffffffffffffffffffffffffffffff16855261464a6146c6826144dc565b60208701516fffffffffffffffffffffffffffffffff169061457e565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061472457805160ff1916838001178555614751565b82800160010185558215614751579182015b82811115614751578251825591602001919060010190614736565b50614528929150614794565b604080518082019091526000808252602082015290565b604080516060810182526000808252602082018190529181019190915290565b5b808211156145285760008155600101614795565b8035613b5d81615988565b60008083601f8401126147c5578182fd5b50813567ffffffffffffffff8111156147dc578182fd5b60208301915083602080830285010111156147f657600080fd5b9250929050565b600082601f83011261480d578081fd5b813561482061481b826158ee565b6158c7565b81815291506020808301908481018184028601820187101561484157600080fd5b60005b8481101561486057813584529282019290820190600101614844565b505050505092915050565b8051613b5d816159ad565b803567ffffffffffffffff81168114613b5d57600080fd5b8051613b5d816159d9565b6000602082840312156148aa578081fd5b81356141c381615988565b6000602082840312156148c6578081fd5b81516141c381615988565b60008060008060008060c087890312156148e9578182fd5b86356148f481615988565b9550602087013561490481615988565b94506040870135614914816159ad565b93506060870135614924816159d9565b9598949750929560808101359460a0909101359350915050565b600080600080600060a08688031215614955578283fd5b855161496081615988565b602087015190955067ffffffffffffffff81111561497c578384fd5b8601601f8101881361498c578384fd5b805161499a61481b8261590e565b8181528960208385010111156149ae578586fd5b6149bf82602083016020860161595c565b8096505050506149d2876040880161486b565b92506149e1876060880161486b565b91506149f0876080880161488e565b90509295509295909350565b600080600060608486031215614a10578081fd5b8335614a1b81615988565b92506020840135614a2b816159ad565b91506040840135614a3b816159ad565b809150509250925092565b600080600060608486031215614a5a578081fd5b8335614a6581615988565b92506020840135614a75816159ad565b929592945050506040919091013590565b60008060408385031215614a98578182fd5b8235614aa381615988565b946020939093013593505050565b60008060008060008060808789031215614ac9578384fd5b863567ffffffffffffffff80821115614ae0578586fd5b614aec8a838b016147b4565b90985096506020890135915080821115614b04578586fd5b50614b1189828a016147b4565b9095509350506040870135614b2581615988565b91506060870135614b3581615988565b809150509295509295509295565b60008060008060008060608789031215614b5b578384fd5b863567ffffffffffffffff80821115614b72578586fd5b614b7e8a838b016147b4565b90985096506020890135915080821115614b96578586fd5b614ba28a838b016147b4565b90965094506040890135915080821115614bba578384fd5b50614bc789828a016147b4565b979a9699509497509295939492505050565b60008060408385031215614beb578182fd5b8251614bf6816159ad565b6020939093015192949293505050565b600080600060608486031215614c1a578081fd5b8335614c25816159ad565b95602085013595506040909401359392505050565b60008060208385031215614c4c578182fd5b823567ffffffffffffffff80821115614c63578384fd5b818501915085601f830112614c76578384fd5b813581811115614c84578485fd5b866020828501011115614c95578485fd5b60209290920196919550909350505050565b600080600060608486031215614cbb578081fd5b8335614cc681615988565b92506020840135614a7581615988565b60008060008060808587031215614ceb578182fd5b8451614cf681615988565b6020860151909450614d0781615988565b6040860151606090960151949790965092505050565b600080600060608486031215614d31578081fd5b8335614d3c81615988565b925060208481013567ffffffffffffffff80821115614d59578384fd5b818701915087601f830112614d6c578384fd5b8135614d7a61481b826158ee565b81815284810190848601868402860187018c1015614d96578788fd5b8795505b83861015614dc057614dac8c826147a9565b835260019590950194918601918601614d9a565b50965050506040870135925080831115614dd8578384fd5b5050614de6868287016147fd565b9150509250925092565b600080600080600080600060e0888a031215614e0a578485fd5b8735614e1581615988565b96506020880135614e2581615988565b9550604088013567ffffffffffffffff811115614e40578586fd5b8801601f81018a13614e50578586fd5b8035614e5e61481b8261590e565b8181528b6020838501011115614e72578788fd5b816020840160208301379081016020019690965250614e948960608a01614876565b9699959850939660808101359560a0820135955060c0909101359350915050565b600060208284031215614ec6578081fd5b5035919050565b60008060408385031215614edf578182fd5b823591506020830135614ef181615988565b809150509250929050565b600080600060608486031215614f10578081fd5b833592506020840135614a2b81615988565b600060408284031215614f33578081fd5b614f3d60406158c7565b8251614f48816159bb565b81526020830151614f58816159bb565b60208201529392505050565b60008060408385031215614f76578182fd5b8235614f81816159bb565b91506020830135614ef1816159bb565b600060208284031215614fa2578081fd5b5051919050565b60008060408385031215614fbb578182fd5b505080516020909101519092909150565b600060208284031215614fdd578081fd5b813567ffffffffffffffff811681146141c3578182fd5b600060208284031215615005578081fd5b81356141c3816159d9565b73ffffffffffffffffffffffffffffffffffffffff16815260200190565b815260200190565b6000825161504881846020870161595c565b9190910192915050565b6000835161506481846020880161595c565b9190910191825250602001919050565b6000845161508681846020890161595c565b91909101928352506020820152604001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff9687168152949095166020850152911515604084015260ff166060830152608082015260a081019190915260c00190565b9115158252602082015260400190565b600060208252825180602084015261513181604085016020870161595c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602080830181845282855460018082166000811461518a57600181146151c6576151fe565b607f600284041685527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00831660408901526060880193506151fe565b600283048086526151d68a615950565b885b828110156151f45781548b8201604001529084019088016151d8565b8a01604001955050505b5091979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015292166040820152606081019190915260800190565b73ffffffffffffffffffffffffffffffffffffffff958616815293851660208501529190931660408301526060820192909252608081019190915260a00190565b60006080820173ffffffffffffffffffffffffffffffffffffffff80881684526020818816818601526080604086015282915086516152e981856157e6565b92508188019350845b8181101561531357615305848651615010565b9483019493506001016152f2565b50508482036060860152819250855161532c81846157e6565b93508187019250845b818110156153565761534885855161502e565b945092820192600101615335565b50929998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff93909316835260208301919091521515604082015260600190565b60208082526015908201527f426f72696e674d6174683a20556e646572666c6f770000000000000000000000604082015260600190565b60208082526018908201527f4361756c64726f6e3a207573657220696e736f6c76656e740000000000000000604082015260600190565b60208082526017908201527f43616c6c6572206973206e6f7420746865206f776e6572000000000000000000604082015260600190565b60208082526015908201527f4361756c64726f6e3a2063616c6c206661696c65640000000000000000000000604082015260600190565b60208082526015908201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604082015260600190565b6020808252601c908201527f426f72696e674d6174683a2075696e74313238204f766572666c6f7700000000604082015260600190565b60208082526019908201527f4361756c64726f6e3a20616c6c2061726520736f6c76656e7400000000000000604082015260600190565b60208082526018908201527f426f72696e674d6174683a20416464204f766572666c6f770000000000000000604082015260600190565b60208082526018908201527f557064617465206f6e6c79206576657279203320646179730000000000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e6572604082015260600190565b6020808252601c908201527f496e746572657374207261746520696e637265617365203e2037352500000000604082015260600190565b60208082526014908201527f4361756c64726f6e3a2063616e27742063616c6c000000000000000000000000604082015260600190565b6020808252601d908201527f4361756c64726f6e3a20616c726561647920696e697469616c697a6564000000604082015260600190565b60208082526017908201527f4361756c64726f6e3a20536b696d20746f6f206d756368000000000000000000604082015260600190565b60208082526012908201527f4361756c64726f6e3a2062616420706169720000000000000000000000000000604082015260600190565b60208082526014908201527f426f72726f77204c696d69742072656163686564000000000000000000000000604082015260600190565b60208082526018908201527f426f72696e674d6174683a204d756c204f766572666c6f770000000000000000604082015260600190565b60208082526015908201527f4361756c64726f6e3a2072617465206e6f74206f6b0000000000000000000000604082015260600190565b6fffffffffffffffffffffffffffffffff91909116815260200190565b6fffffffffffffffffffffffffffffffff92831681529116602082015260400190565b90815260200190565b918252602082015260400190565b9283526020830191909152604082015260600190565b67ffffffffffffffff93841681526fffffffffffffffffffffffffffffffff929092166020830152909116604082015260600190565b67ffffffffffffffff92831681529116602082015260400190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615898578283fd5b83018035915067ffffffffffffffff8211156158b2578283fd5b6020019150368190038213156147f657600080fd5b60405181810167ffffffffffffffff811182821017156158e657600080fd5b604052919050565b600067ffffffffffffffff821115615904578081fd5b5060209081020190565b600067ffffffffffffffff821115615924578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60009081526020902090565b60005b8381101561597757818101518382015260200161595f565b838111156144485750506000910152565b73ffffffffffffffffffffffffffffffffffffffff811681146159aa57600080fd5b50565b80151581146159aa57600080fd5b6fffffffffffffffffffffffffffffffff811681146159aa57600080fd5b60ff811681146159aa57600080fdfea2646970667358221220078881611528a34bc39f9fa8079eb355ad4b339a474b4891d87f23da01500c2864736f6c634300060c0033" +} \ No newline at end of file diff --git a/deployments/mainnet/MagicInternetGold.json b/deployments/mainnet/MagicInternetGold.json new file mode 100644 index 00000000..d8ba5ed4 --- /dev/null +++ b/deployments/mainnet/MagicInternetGold.json @@ -0,0 +1,683 @@ +{ + "address": "0x5624b48Ec2848bD642230b46405E1F65938c5FD0", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "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": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastMint", + "outputs": [ + { + "internalType": "uint128", + "name": "time", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "clone", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "contract IBentoBoxV1", + "name": "bentoBox", + "type": "address" + } + ], + "name": "mintToBentoBox", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + }, + { + "internalType": "bool", + "name": "direct", + "type": "bool" + }, + { + "internalType": "bool", + "name": "renounce", + "type": "bool" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xf8030045d930196457bfe372170cd80d0e3c86d98628f85b39009d51421f5a30", + "receipt": { + "to": null, + "from": "0xb4EfdA6DAf5ef75D08869A0f9C0213278fb43b6C", + "contractAddress": "0x5624b48Ec2848bD642230b46405E1F65938c5FD0", + "transactionIndex": 192, + "gasUsed": "1217926", + "logsBloom": "0x00000000000002000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000100000000008000000000000000000000020000000000000000000000000000000000000000000000000000000020000008000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1dae620a6263d84edebfd9125b8833024c48bbfa4f8d9be0eb34185ef9b45aa9", + "transactionHash": "0xf8030045d930196457bfe372170cd80d0e3c86d98628f85b39009d51421f5a30", + "logs": [ + { + "transactionIndex": 192, + "blockNumber": 14818453, + "transactionHash": "0xf8030045d930196457bfe372170cd80d0e3c86d98628f85b39009d51421f5a30", + "address": "0x5624b48Ec2848bD642230b46405E1F65938c5FD0", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000b4efda6daf5ef75d08869a0f9c0213278fb43b6c" + ], + "data": "0x", + "logIndex": 311, + "blockHash": "0x1dae620a6263d84edebfd9125b8833024c48bbfa4f8d9be0eb34185ef9b45aa9" + } + ], + "blockNumber": 14818453, + "cumulativeGasUsed": "14699550", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "a8287f9582549e1e61e2a34e7021b1e9", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"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\":true,\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastMint\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"time\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"clone\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"contract IBentoBoxV1\",\"name\":\"bentoBox\",\"type\":\"address\"}],\"name\":\"mintToBentoBox\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"direct\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"renounce\",\"type\":\"bool\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"params\":{\"amount\":\"The maximum collective amount that `spender` can draw.\",\"spender\":\"Address of the party that can draw from msg.sender's account.\"},\"returns\":{\"_0\":\"(bool) Returns True if approved.\"}},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"params\":{\"deadline\":\"This permit must be redeemed before this deadline (UTC timestamp in seconds).\",\"owner_\":\"Address of the owner.\",\"spender\":\"The address of the spender that gets approved to draw from `owner_`.\",\"value\":\"The maximum collective amount that `spender` can draw.\"}},\"transfer(address,uint256)\":{\"params\":{\"amount\":\"of the tokens to move.\",\"to\":\"The address to move the tokens.\"},\"returns\":{\"_0\":\"(bool) Returns True if succeeded.\"}},\"transferFrom(address,address,uint256)\":{\"params\":{\"amount\":\"The token amount to move.\",\"from\":\"Address to draw tokens from.\",\"to\":\"The address to move the tokens.\"},\"returns\":{\"_0\":\"(bool) Returns True if succeeded.\"}},\"transferOwnership(address,bool,bool)\":{\"params\":{\"direct\":\"True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\",\"newOwner\":\"Address of the new owner.\",\"renounce\":\"Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\"}}},\"title\":\"Magic Internet Gold\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"allowance(address,address)\":{\"notice\":\"owner > spender > allowance mapping.\"},\"approve(address,uint256)\":{\"notice\":\"Approves `amount` from sender to be spend by `spender`.\"},\"balanceOf(address)\":{\"notice\":\"owner > balance mapping.\"},\"claimOwnership()\":{\"notice\":\"Needs to be called by `pendingOwner` to claim ownership.\"},\"nonces(address)\":{\"notice\":\"owner > nonce mapping. Used in `permit`.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"notice\":\"Approves `value` from `owner_` to be spend by `spender`.\"},\"transfer(address,uint256)\":{\"notice\":\"Transfers `amount` tokens from `msg.sender` to `to`.\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"Transfers `amount` tokens from `from` to `to`. Caller needs approval for `from`.\"},\"transferOwnership(address,bool,bool)\":{\"notice\":\"Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner. Can only be invoked by the current `owner`.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/MagicInternetGold.sol\":\"MagicInternetGold\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":690},\"remappings\":[]},\"sources\":{\"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\\n// Edited by BoringCrypto\\n\\ncontract BoringOwnableData {\\n address public owner;\\n address public pendingOwner;\\n}\\n\\ncontract BoringOwnable is BoringOwnableData {\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /// @notice `owner` defaults to msg.sender on construction.\\n constructor() public {\\n owner = msg.sender;\\n emit OwnershipTransferred(address(0), msg.sender);\\n }\\n\\n /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.\\n /// Can only be invoked by the current `owner`.\\n /// @param newOwner Address of the new owner.\\n /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\\n /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\\n function transferOwnership(\\n address newOwner,\\n bool direct,\\n bool renounce\\n ) public onlyOwner {\\n if (direct) {\\n // Checks\\n require(newOwner != address(0) || renounce, \\\"Ownable: zero address\\\");\\n\\n // Effects\\n emit OwnershipTransferred(owner, newOwner);\\n owner = newOwner;\\n pendingOwner = address(0);\\n } else {\\n // Effects\\n pendingOwner = newOwner;\\n }\\n }\\n\\n /// @notice Needs to be called by `pendingOwner` to claim ownership.\\n function claimOwnership() public {\\n address _pendingOwner = pendingOwner;\\n\\n // Checks\\n require(msg.sender == _pendingOwner, \\\"Ownable: caller != pending owner\\\");\\n\\n // Effects\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = address(0);\\n }\\n\\n /// @notice Only allows the `owner` to execute the function.\\n modifier onlyOwner() {\\n require(msg.sender == owner, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n}\\n\",\"keccak256\":\"0xbde1619421fef865bf5f5f806e319900fb862e27f0aef6e0878e93f04f477601\",\"license\":\"MIT\"},\"@boringcrypto/boring-solidity/contracts/Domain.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// Based on code and smartness by Ross Campbell and Keno\\n// Uses immutable to store the domain separator to reduce gas usage\\n// If the chain id changes due to a fork, the forked chain will calculate on the fly.\\npragma solidity 0.6.12;\\n\\n// solhint-disable no-inline-assembly\\n\\ncontract Domain {\\n bytes32 private constant DOMAIN_SEPARATOR_SIGNATURE_HASH = keccak256(\\\"EIP712Domain(uint256 chainId,address verifyingContract)\\\");\\n // See https://eips.ethereum.org/EIPS/eip-191\\n string private constant EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA = \\\"\\\\x19\\\\x01\\\";\\n\\n // solhint-disable var-name-mixedcase\\n bytes32 private immutable _DOMAIN_SEPARATOR;\\n uint256 private immutable DOMAIN_SEPARATOR_CHAIN_ID; \\n\\n /// @dev Calculate the DOMAIN_SEPARATOR\\n function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) {\\n return keccak256(\\n abi.encode(\\n DOMAIN_SEPARATOR_SIGNATURE_HASH,\\n chainId,\\n address(this)\\n )\\n );\\n }\\n\\n constructor() public {\\n uint256 chainId; assembly {chainId := chainid()}\\n _DOMAIN_SEPARATOR = _calculateDomainSeparator(DOMAIN_SEPARATOR_CHAIN_ID = chainId);\\n }\\n\\n /// @dev Return the DOMAIN_SEPARATOR\\n // It's named internal to allow making it public from the contract that uses it by creating a simple view function\\n // with the desired public name, such as DOMAIN_SEPARATOR or domainSeparator.\\n // solhint-disable-next-line func-name-mixedcase\\n function _domainSeparator() internal view returns (bytes32) {\\n uint256 chainId; assembly {chainId := chainid()}\\n return chainId == DOMAIN_SEPARATOR_CHAIN_ID ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(chainId);\\n }\\n\\n function _getDigest(bytes32 dataHash) internal view returns (bytes32 digest) {\\n digest =\\n keccak256(\\n abi.encodePacked(\\n EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA,\\n _domainSeparator(),\\n dataHash\\n )\\n );\\n }\\n}\",\"keccak256\":\"0xe5215010c5a07b4b2fb1a2347b2106377678fea3d6f9ed656677c0570de2f6aa\",\"license\":\"MIT\"},\"@boringcrypto/boring-solidity/contracts/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\nimport \\\"./interfaces/IERC20.sol\\\";\\nimport \\\"./Domain.sol\\\";\\n\\n// solhint-disable no-inline-assembly\\n// solhint-disable not-rely-on-time\\n\\n// Data part taken out for building of contracts that receive delegate calls\\ncontract ERC20Data {\\n /// @notice owner > balance mapping.\\n mapping(address => uint256) public balanceOf;\\n /// @notice owner > spender > allowance mapping.\\n mapping(address => mapping(address => uint256)) public allowance;\\n /// @notice owner > nonce mapping. Used in `permit`.\\n mapping(address => uint256) public nonces;\\n}\\n\\nabstract contract ERC20 is IERC20, Domain {\\n /// @notice owner > balance mapping.\\n mapping(address => uint256) public override balanceOf;\\n /// @notice owner > spender > allowance mapping.\\n mapping(address => mapping(address => uint256)) public override allowance;\\n /// @notice owner > nonce mapping. Used in `permit`.\\n mapping(address => uint256) public nonces;\\n\\n event Transfer(address indexed _from, address indexed _to, uint256 _value);\\n event Approval(address indexed _owner, address indexed _spender, uint256 _value);\\n\\n /// @notice Transfers `amount` tokens from `msg.sender` to `to`.\\n /// @param to The address to move the tokens.\\n /// @param amount of the tokens to move.\\n /// @return (bool) Returns True if succeeded.\\n function transfer(address to, uint256 amount) public returns (bool) {\\n // If `amount` is 0, or `msg.sender` is `to` nothing happens\\n if (amount != 0 || msg.sender == to) {\\n uint256 srcBalance = balanceOf[msg.sender];\\n require(srcBalance >= amount, \\\"ERC20: balance too low\\\");\\n if (msg.sender != to) {\\n require(to != address(0), \\\"ERC20: no zero address\\\"); // Moved down so low balance calls safe some gas\\n\\n balanceOf[msg.sender] = srcBalance - amount; // Underflow is checked\\n balanceOf[to] += amount;\\n }\\n }\\n emit Transfer(msg.sender, to, amount);\\n return true;\\n }\\n\\n /// @notice Transfers `amount` tokens from `from` to `to`. Caller needs approval for `from`.\\n /// @param from Address to draw tokens from.\\n /// @param to The address to move the tokens.\\n /// @param amount The token amount to move.\\n /// @return (bool) Returns True if succeeded.\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public returns (bool) {\\n // If `amount` is 0, or `from` is `to` nothing happens\\n if (amount != 0) {\\n uint256 srcBalance = balanceOf[from];\\n require(srcBalance >= amount, \\\"ERC20: balance too low\\\");\\n\\n if (from != to) {\\n uint256 spenderAllowance = allowance[from][msg.sender];\\n // If allowance is infinite, don't decrease it to save on gas (breaks with EIP-20).\\n if (spenderAllowance != type(uint256).max) {\\n require(spenderAllowance >= amount, \\\"ERC20: allowance too low\\\");\\n allowance[from][msg.sender] = spenderAllowance - amount; // Underflow is checked\\n }\\n require(to != address(0), \\\"ERC20: no zero address\\\"); // Moved down so other failed calls safe some gas\\n\\n balanceOf[from] = srcBalance - amount; // Underflow is checked\\n balanceOf[to] += amount;\\n }\\n }\\n emit Transfer(from, to, amount);\\n return true;\\n }\\n\\n /// @notice Approves `amount` from sender to be spend by `spender`.\\n /// @param spender Address of the party that can draw from msg.sender's account.\\n /// @param amount The maximum collective amount that `spender` can draw.\\n /// @return (bool) Returns True if approved.\\n function approve(address spender, uint256 amount) public override returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32) {\\n return _domainSeparator();\\n }\\n\\n // keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n bytes32 private constant PERMIT_SIGNATURE_HASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n\\n /// @notice Approves `value` from `owner_` to be spend by `spender`.\\n /// @param owner_ Address of the owner.\\n /// @param spender The address of the spender that gets approved to draw from `owner_`.\\n /// @param value The maximum collective amount that `spender` can draw.\\n /// @param deadline This permit must be redeemed before this deadline (UTC timestamp in seconds).\\n function permit(\\n address owner_,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external override {\\n require(owner_ != address(0), \\\"ERC20: Owner cannot be 0\\\");\\n require(block.timestamp < deadline, \\\"ERC20: Expired\\\");\\n require(\\n ecrecover(_getDigest(keccak256(abi.encode(PERMIT_SIGNATURE_HASH, owner_, spender, value, nonces[owner_]++, deadline))), v, r, s) ==\\n owner_,\\n \\\"ERC20: Invalid Signature\\\"\\n );\\n allowance[owner_][spender] = value;\\n emit Approval(owner_, spender, value);\\n }\\n}\\n\\ncontract ERC20WithSupply is IERC20, ERC20 {\\n uint256 public override totalSupply;\\n\\n function _mint(address user, uint256 amount) private {\\n uint256 newTotalSupply = totalSupply + amount;\\n require(newTotalSupply >= totalSupply, \\\"Mint overflow\\\");\\n totalSupply = newTotalSupply;\\n balanceOf[user] += amount;\\n }\\n\\n function _burn(address user, uint256 amount) private {\\n require(balanceOf[user] >= amount, \\\"Burn too much\\\");\\n totalSupply -= amount;\\n balanceOf[user] -= amount;\\n }\\n}\\n\",\"keccak256\":\"0x215d98f2006287eb309c79fcfebd5a25cf26e60ccf28923d203de07b6f671658\",\"license\":\"MIT\"},\"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n\\n function balanceOf(address account) external view returns (uint256);\\n\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /// @notice EIP 2612\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0xf0da35541d6ae9e3c12fdd7c8d5d9584c56f9ac50d062efb8ca353ebd6ffd47d\",\"license\":\"MIT\"},\"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\n/// @notice A library for performing overflow-/underflow-safe math,\\n/// updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math).\\nlibrary BoringMath {\\n function add(uint256 a, uint256 b) internal pure returns (uint256 c) {\\n require((c = a + b) >= b, \\\"BoringMath: Add Overflow\\\");\\n }\\n\\n function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {\\n require((c = a - b) <= a, \\\"BoringMath: Underflow\\\");\\n }\\n\\n function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {\\n require(b == 0 || (c = a * b) / b == a, \\\"BoringMath: Mul Overflow\\\");\\n }\\n\\n function to128(uint256 a) internal pure returns (uint128 c) {\\n require(a <= uint128(-1), \\\"BoringMath: uint128 Overflow\\\");\\n c = uint128(a);\\n }\\n\\n function to64(uint256 a) internal pure returns (uint64 c) {\\n require(a <= uint64(-1), \\\"BoringMath: uint64 Overflow\\\");\\n c = uint64(a);\\n }\\n\\n function to32(uint256 a) internal pure returns (uint32 c) {\\n require(a <= uint32(-1), \\\"BoringMath: uint32 Overflow\\\");\\n c = uint32(a);\\n }\\n}\\n\\n/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint128.\\nlibrary BoringMath128 {\\n function add(uint128 a, uint128 b) internal pure returns (uint128 c) {\\n require((c = a + b) >= b, \\\"BoringMath: Add Overflow\\\");\\n }\\n\\n function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {\\n require((c = a - b) <= a, \\\"BoringMath: Underflow\\\");\\n }\\n}\\n\\n/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint64.\\nlibrary BoringMath64 {\\n function add(uint64 a, uint64 b) internal pure returns (uint64 c) {\\n require((c = a + b) >= b, \\\"BoringMath: Add Overflow\\\");\\n }\\n\\n function sub(uint64 a, uint64 b) internal pure returns (uint64 c) {\\n require((c = a - b) <= a, \\\"BoringMath: Underflow\\\");\\n }\\n}\\n\\n/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint32.\\nlibrary BoringMath32 {\\n function add(uint32 a, uint32 b) internal pure returns (uint32 c) {\\n require((c = a + b) >= b, \\\"BoringMath: Add Overflow\\\");\\n }\\n\\n function sub(uint32 a, uint32 b) internal pure returns (uint32 c) {\\n require((c = a - b) <= a, \\\"BoringMath: Underflow\\\");\\n }\\n}\\n\",\"keccak256\":\"0x6bc52950e23c70a90a5b039697b77ba76360b62da6a06a61d3a1714b9c6c26b9\",\"license\":\"MIT\"},\"@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\nimport \\\"./BoringMath.sol\\\";\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\n/// @notice A rebasing library using overflow-/underflow-safe math.\\nlibrary RebaseLibrary {\\n using BoringMath for uint256;\\n using BoringMath128 for uint128;\\n\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(\\n Rebase memory total,\\n uint256 elastic,\\n bool roundUp\\n ) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = elastic.mul(total.base) / total.elastic;\\n if (roundUp && base.mul(total.elastic) / total.base < elastic) {\\n base = base.add(1);\\n }\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(\\n Rebase memory total,\\n uint256 base,\\n bool roundUp\\n ) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = base.mul(total.elastic) / total.base;\\n if (roundUp && elastic.mul(total.base) / total.elastic < base) {\\n elastic = elastic.add(1);\\n }\\n }\\n }\\n\\n /// @notice Add `elastic` to `total` and doubles `total.base`.\\n /// @return (Rebase) The new total.\\n /// @return base in relationship to `elastic`.\\n function add(\\n Rebase memory total,\\n uint256 elastic,\\n bool roundUp\\n ) internal pure returns (Rebase memory, uint256 base) {\\n base = toBase(total, elastic, roundUp);\\n total.elastic = total.elastic.add(elastic.to128());\\n total.base = total.base.add(base.to128());\\n return (total, base);\\n }\\n\\n /// @notice Sub `base` from `total` and update `total.elastic`.\\n /// @return (Rebase) The new total.\\n /// @return elastic in relationship to `base`.\\n function sub(\\n Rebase memory total,\\n uint256 base,\\n bool roundUp\\n ) internal pure returns (Rebase memory, uint256 elastic) {\\n elastic = toElastic(total, base, roundUp);\\n total.elastic = total.elastic.sub(elastic.to128());\\n total.base = total.base.sub(base.to128());\\n return (total, elastic);\\n }\\n\\n /// @notice Add `elastic` and `base` to `total`.\\n function add(\\n Rebase memory total,\\n uint256 elastic,\\n uint256 base\\n ) internal pure returns (Rebase memory) {\\n total.elastic = total.elastic.add(elastic.to128());\\n total.base = total.base.add(base.to128());\\n return total;\\n }\\n\\n /// @notice Subtract `elastic` and `base` to `total`.\\n function sub(\\n Rebase memory total,\\n uint256 elastic,\\n uint256 base\\n ) internal pure returns (Rebase memory) {\\n total.elastic = total.elastic.sub(elastic.to128());\\n total.base = total.base.sub(base.to128());\\n return total;\\n }\\n\\n /// @notice Add `elastic` to `total` and update storage.\\n /// @return newElastic Returns updated `elastic`.\\n function addElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {\\n newElastic = total.elastic = total.elastic.add(elastic.to128());\\n }\\n\\n /// @notice Subtract `elastic` from `total` and update storage.\\n /// @return newElastic Returns updated `elastic`.\\n function subElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {\\n newElastic = total.elastic = total.elastic.sub(elastic.to128());\\n }\\n}\\n\",\"keccak256\":\"0xab228bfa8a3019a4f7effa8aeeb05de141d328703d8a2f7b87ca811d0ca33196\",\"license\":\"MIT\"},\"@sushiswap/bentobox-sdk/contracts/IBatchFlashBorrower.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\nimport '@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol';\\n\\ninterface IBatchFlashBorrower {\\n function onBatchFlashLoan(\\n address sender,\\n IERC20[] calldata tokens,\\n uint256[] calldata amounts,\\n uint256[] calldata fees,\\n bytes calldata data\\n ) external;\\n}\",\"keccak256\":\"0x825a46e61443df6e1289b513da4386d0413d0b5311553f3e7e7e5c90412ddd5d\",\"license\":\"MIT\"},\"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\npragma experimental ABIEncoderV2;\\n\\nimport '@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol';\\nimport '@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol';\\nimport './IBatchFlashBorrower.sol';\\nimport './IFlashBorrower.sol';\\nimport './IStrategy.sol';\\n\\ninterface IBentoBoxV1 {\\n event LogDeploy(address indexed masterContract, bytes data, address indexed cloneAddress);\\n event LogDeposit(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);\\n event LogFlashLoan(address indexed borrower, address indexed token, uint256 amount, uint256 feeAmount, address indexed receiver);\\n event LogRegisterProtocol(address indexed protocol);\\n event LogSetMasterContractApproval(address indexed masterContract, address indexed user, bool approved);\\n event LogStrategyDivest(address indexed token, uint256 amount);\\n event LogStrategyInvest(address indexed token, uint256 amount);\\n event LogStrategyLoss(address indexed token, uint256 amount);\\n event LogStrategyProfit(address indexed token, uint256 amount);\\n event LogStrategyQueued(address indexed token, address indexed strategy);\\n event LogStrategySet(address indexed token, address indexed strategy);\\n event LogStrategyTargetPercentage(address indexed token, uint256 targetPercentage);\\n event LogTransfer(address indexed token, address indexed from, address indexed to, uint256 share);\\n event LogWhiteListMasterContract(address indexed masterContract, bool approved);\\n event LogWithdraw(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n function balanceOf(IERC20, address) external view returns (uint256);\\n function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results);\\n function batchFlashLoan(IBatchFlashBorrower borrower, address[] calldata receivers, IERC20[] calldata tokens, uint256[] calldata amounts, bytes calldata data) external;\\n function claimOwnership() external;\\n function deploy(address masterContract, bytes calldata data, bool useCreate2) external payable;\\n function deposit(IERC20 token_, address from, address to, uint256 amount, uint256 share) external payable returns (uint256 amountOut, uint256 shareOut);\\n function flashLoan(IFlashBorrower borrower, address receiver, IERC20 token, uint256 amount, bytes calldata data) external;\\n function harvest(IERC20 token, bool balance, uint256 maxChangeAmount) external;\\n function masterContractApproved(address, address) external view returns (bool);\\n function masterContractOf(address) external view returns (address);\\n function nonces(address) external view returns (uint256);\\n function owner() external view returns (address);\\n function pendingOwner() external view returns (address);\\n function pendingStrategy(IERC20) external view returns (IStrategy);\\n function permitToken(IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\\n function registerProtocol() external;\\n function setMasterContractApproval(address user, address masterContract, bool approved, uint8 v, bytes32 r, bytes32 s) external;\\n function setStrategy(IERC20 token, IStrategy newStrategy) external;\\n function setStrategyTargetPercentage(IERC20 token, uint64 targetPercentage_) external;\\n function strategy(IERC20) external view returns (IStrategy);\\n function strategyData(IERC20) external view returns (uint64 strategyStartDate, uint64 targetPercentage, uint128 balance);\\n function toAmount(IERC20 token, uint256 share, bool roundUp) external view returns (uint256 amount);\\n function toShare(IERC20 token, uint256 amount, bool roundUp) external view returns (uint256 share);\\n function totals(IERC20) external view returns (Rebase memory totals_);\\n function transfer(IERC20 token, address from, address to, uint256 share) external;\\n function transferMultiple(IERC20 token, address from, address[] calldata tos, uint256[] calldata shares) external;\\n function transferOwnership(address newOwner, bool direct, bool renounce) external;\\n function whitelistMasterContract(address masterContract, bool approved) external;\\n function whitelistedMasterContracts(address) external view returns (bool);\\n function withdraw(IERC20 token_, address from, address to, uint256 amount, uint256 share) external returns (uint256 amountOut, uint256 shareOut);\\n}\",\"keccak256\":\"0x9c025e34e0ef0c1fc9372ada9afa61925341ee93de9b9a79e77de55d715b6fb6\",\"license\":\"MIT\"},\"@sushiswap/bentobox-sdk/contracts/IFlashBorrower.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\nimport '@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol';\\n\\ninterface IFlashBorrower {\\n function onFlashLoan(\\n address sender,\\n IERC20 token,\\n uint256 amount,\\n uint256 fee,\\n bytes calldata data\\n ) external;\\n}\",\"keccak256\":\"0x6e389a5acb7b3e7f337b7e28477e998228f05fc4c8ff877eab32d3e15037ccc2\",\"license\":\"MIT\"},\"@sushiswap/bentobox-sdk/contracts/IStrategy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\ninterface IStrategy {\\n // Send the assets to the Strategy and call skim to invest them\\n function skim(uint256 amount) external;\\n\\n // Harvest any profits made converted to the asset and pass them to the caller\\n function harvest(uint256 balance, address sender) external returns (int256 amountAdded);\\n\\n // Withdraw assets. The returned amount can differ from the requested amount due to rounding.\\n // The actualAmount should be very close to the amount. The difference should NOT be used to report a loss. That's what harvest is for.\\n function withdraw(uint256 amount) external returns (uint256 actualAmount);\\n\\n // Withdraw all assets in the safest way possible. This shouldn't fail.\\n function exit(uint256 balance) external returns (int256 amountAdded);\\n}\",\"keccak256\":\"0x91c02244e1508cf8e4d6c45110c57142301c237e809dcad67b8022f83555ba13\",\"license\":\"MIT\"},\"contracts/MagicInternetGold.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n// Magic Internet Money\\n\\n// \\u2588\\u2588\\u2588\\u2557 \\u2588\\u2588\\u2588\\u2557\\u2588\\u2588\\u2557 \\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2557 \\n// \\u2588\\u2588\\u2588\\u2588\\u2557 \\u2588\\u2588\\u2588\\u2588\\u2551\\u2588\\u2588\\u2551\\u2588\\u2588\\u2554\\u2550\\u2550\\u2550\\u2550\\u255d \\n// \\u2588\\u2588\\u2554\\u2588\\u2588\\u2588\\u2588\\u2554\\u2588\\u2588\\u2551\\u2588\\u2588\\u2551\\u2588\\u2588\\u2551 \\u2588\\u2588\\u2588\\u2557\\n// \\u2588\\u2588\\u2551\\u255a\\u2588\\u2588\\u2554\\u255d\\u2588\\u2588\\u2551\\u2588\\u2588\\u2551\\u2588\\u2588\\u2551 \\u2588\\u2588\\u2551\\n// \\u2588\\u2588\\u2551 \\u255a\\u2550\\u255d \\u2588\\u2588\\u2551\\u2588\\u2588\\u2551\\u255a\\u2588\\u2588\\u2588\\u2588\\u2588\\u2588\\u2554\\u255d\\n// \\u255a\\u2550\\u255d \\u255a\\u2550\\u255d\\u255a\\u2550\\u255d \\u255a\\u2550\\u2550\\u2550\\u2550\\u2550\\u255d \\n \\n\\n// BoringCrypto, 0xMerlin\\n\\npragma solidity 0.6.12;\\nimport \\\"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\\\";\\nimport \\\"@boringcrypto/boring-solidity/contracts/ERC20.sol\\\";\\nimport \\\"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\\\";\\nimport \\\"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\\\";\\n\\n/// @title Magic Internet Gold\\ncontract MagicInternetGold is ERC20, BoringOwnable {\\n using BoringMath for uint256;\\n // ERC20 'variables'\\n string public constant symbol = \\\"MIG\\\";\\n string public constant name = \\\"Magic Internet Gold\\\";\\n uint8 public constant decimals = 18;\\n uint256 public override totalSupply;\\n\\n struct Minting {\\n uint128 time;\\n uint128 amount;\\n }\\n\\n Minting public lastMint;\\n uint256 private constant MINTING_PERIOD = 24 hours;\\n uint256 private constant MINTING_INCREASE = 15000;\\n uint256 private constant MINTING_PRECISION = 1e5;\\n\\n // @notice mint MIG to an address\\n // @param to - the recipient\\n // @param amount - the amount minted\\n function mint(address to, uint256 amount) public onlyOwner {\\n require(to != address(0), \\\"MIG: no mint to zero address\\\");\\n\\n // Limits the amount minted per period to a convergence function, with the period duration restarting on every mint\\n uint256 totalMintedAmount = uint256(lastMint.time < block.timestamp - MINTING_PERIOD ? 0 : lastMint.amount).add(amount);\\n require(totalSupply == 0 || totalSupply.mul(MINTING_INCREASE) / MINTING_PRECISION >= totalMintedAmount);\\n\\n lastMint.time = block.timestamp.to128();\\n lastMint.amount = totalMintedAmount.to128();\\n\\n totalSupply = totalSupply + amount;\\n balanceOf[to] += amount;\\n emit Transfer(address(0), to, amount);\\n }\\n\\n // @notice mint MIG to a recipient on BentoBox\\n // @param clone - the recipient clone contract\\n // @param amount - the amount minted\\n // @param bentoBox - the address of the BentoBox / DegenBox selected\\n function mintToBentoBox(address clone, uint256 amount, IBentoBoxV1 bentoBox) public onlyOwner {\\n mint(address(bentoBox), amount);\\n bentoBox.deposit(IERC20(address(this)), address(bentoBox), clone, amount, 0);\\n }\\n\\n // @notice burn MIG from caller\\n // @param amount - the amount burnt\\n function burn(uint256 amount) public {\\n require(amount <= balanceOf[msg.sender], \\\"MIM: not enough\\\");\\n\\n balanceOf[msg.sender] -= amount;\\n totalSupply -= amount;\\n emit Transfer(msg.sender, address(0), amount);\\n }\\n}\\n\",\"keccak256\":\"0x154ca9e628f50b7b1fa373185f977998714f00eefc03162f7b66d086fe48b3a6\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c060405234801561001057600080fd5b504660a081905261002081610069565b60805250600380546001600160a01b031916339081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36100c2565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020808301919091528183019390935230606080830191909152825180830390910181526080909101909152805191012090565b60805160a05161149c6100e5600039806111f0525080611225525061149c6000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c8063586fc5b5116100cd57806395d89b4111610081578063d505accf11610066578063d505accf1461043e578063dd62ed3e1461048f578063e30c3978146104bd5761016c565b806395d89b411461040a578063a9059cbb146104125761016c565b806370a08231116100b257806370a082311461039a5780637ecebe00146103c05780638da5cb5b146103e65761016c565b8063586fc5b51461032d57806369e40265146103645761016c565b8063313ce5671161012457806340c10f191161010957806340c10f19146102dc57806342966c68146103085780634e71e0c8146103255761016c565b8063313ce567146102b65780633644e515146102d45761016c565b8063095ea7b311610155578063095ea7b31461022657806318160ddd1461026657806323b872dd146102805761016c565b806306fdde0314610171578063078dfbe7146101ee575b600080fd5b6101796104c5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101b357818101518382015260200161019b565b50505050905090810190601f1680156101e05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102246004803603606081101561020457600080fd5b506001600160a01b038135169060208101351515906040013515156104fe565b005b6102526004803603604081101561023c57600080fd5b506001600160a01b038135169060200135610669565b604080519115158252519081900360200190f35b61026e6106d0565b60408051918252519081900360200190f35b6102526004803603606081101561029657600080fd5b506001600160a01b038135811691602081013590911690604001356106d6565b6102be6108ef565b6040805160ff9092168252519081900360200190f35b61026e6108f4565b610224600480360360408110156102f257600080fd5b506001600160a01b038135169060200135610903565b6102246004803603602081101561031e57600080fd5b5035610afe565b610224610bba565b610335610c8a565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102246004803603606081101561037a57600080fd5b506001600160a01b03813581169160208101359160409091013516610ca4565b61026e600480360360208110156103b057600080fd5b50356001600160a01b0316610da4565b61026e600480360360208110156103d657600080fd5b50356001600160a01b0316610db6565b6103ee610dc8565b604080516001600160a01b039092168252519081900360200190f35b610179610dd7565b6102526004803603604081101561042857600080fd5b506001600160a01b038135169060200135610df6565b610224600480360360e081101561045457600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610f58565b61026e600480360360408110156104a557600080fd5b506001600160a01b03813581169160200135166111bf565b6103ee6111dc565b6040518060400160405280601381526020017f4d6167696320496e7465726e657420476f6c640000000000000000000000000081525081565b6003546001600160a01b0316331461055d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b811561063b576001600160a01b0383161515806105775750805b6105c8576040805162461bcd60e51b815260206004820152601560248201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604482015290519081900360640190fd5b6003546040516001600160a01b038086169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b03851673ffffffffffffffffffffffffffffffffffffffff1991821617909155600480549091169055610664565b6004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385161790555b505050565b3360008181526001602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b60055481565b6000811561089a576001600160a01b0384166000908152602081905260409020548281101561074c576040805162461bcd60e51b815260206004820152601660248201527f45524332303a2062616c616e636520746f6f206c6f7700000000000000000000604482015290519081900360640190fd5b836001600160a01b0316856001600160a01b031614610898576001600160a01b0385166000908152600160209081526040808320338452909152902054600019811461081057838110156107e7576040805162461bcd60e51b815260206004820152601860248201527f45524332303a20616c6c6f77616e636520746f6f206c6f770000000000000000604482015290519081900360640190fd5b6001600160a01b0386166000908152600160209081526040808320338452909152902084820390555b6001600160a01b03851661086b576040805162461bcd60e51b815260206004820152601660248201527f45524332303a206e6f207a65726f206164647265737300000000000000000000604482015290519081900360640190fd5b506001600160a01b0380861660009081526020819052604080822086850390559186168152208054840190555b505b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a35060019392505050565b601281565b60006108fe6111eb565b905090565b6003546001600160a01b03163314610962576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0382166109bd576040805162461bcd60e51b815260206004820152601c60248201527f4d49473a206e6f206d696e7420746f207a65726f206164647265737300000000604482015290519081900360640190fd5b600654600090610a0a9083906201517f1942016001600160801b03909116106109f857600654600160801b90046001600160801b03166109fb565b60005b6001600160801b03169061124b565b905060055460001480610a3f575080620186a0610a34613a986005546112a390919063ffffffff16565b81610a3b57fe5b0410155b610a4857600080fd5b610a514261130f565b600680546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055610a838161130f565b600680546001600160801b03928316600160801b02921691909117905560058054830190556001600160a01b038316600081815260208181526040808320805487019055805186815290517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3505050565b33600090815260208190526040902054811115610b62576040805162461bcd60e51b815260206004820152600f60248201527f4d494d3a206e6f7420656e6f7567680000000000000000000000000000000000604482015290519081900360640190fd5b3360008181526020818152604080832080548690039055600580548690039055805185815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350565b6004546001600160a01b0316338114610c1a576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e6572604482015290519081900360640190fd5b6003546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0390921673ffffffffffffffffffffffffffffffffffffffff19928316179055600480549091169055565b6006546001600160801b0380821691600160801b90041682565b6003546001600160a01b03163314610d03576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610d0d8183610903565b6040805162ae511b60e21b81523060048201526001600160a01b0380841660248301819052908616604483015260648201859052600060848301819052835191936302b9446c9360a4808201949293918390030190829087803b158015610d7357600080fd5b505af1158015610d87573d6000803e3d6000fd5b505050506040513d6040811015610d9d57600080fd5b5050505050565b60006020819052908152604090205481565b60026020526000908152604090205481565b6003546001600160a01b031681565b604051806040016040528060038152602001624d494760e81b81525081565b600081151580610e0e5750336001600160a01b038416145b15610f0f573360009081526020819052604090205482811015610e78576040805162461bcd60e51b815260206004820152601660248201527f45524332303a2062616c616e636520746f6f206c6f7700000000000000000000604482015290519081900360640190fd5b336001600160a01b03851614610f0d576001600160a01b038416610ee3576040805162461bcd60e51b815260206004820152601660248201527f45524332303a206e6f207a65726f206164647265737300000000000000000000604482015290519081900360640190fd5b3360009081526020819052604080822085840390556001600160a01b038616825290208054840190555b505b6040805183815290516001600160a01b0385169133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600192915050565b6001600160a01b038716610fb3576040805162461bcd60e51b815260206004820152601860248201527f45524332303a204f776e65722063616e6e6f7420626520300000000000000000604482015290519081900360640190fd5b834210611007576040805162461bcd60e51b815260206004820152600e60248201527f45524332303a2045787069726564000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038088166000818152600260209081526040918290208054600181810190925583517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981850152808501869052958c166060870152608086018b905260a086015260c08086018a90528351808703909101815260e0909501909252835193019290922090919061109d90611371565b85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156110f4573d6000803e3d6000fd5b505050602060405103516001600160a01b031614611159576040805162461bcd60e51b815260206004820152601860248201527f45524332303a20496e76616c6964205369676e61747572650000000000000000604482015290519081900360640190fd5b6001600160a01b038088166000818152600160209081526040808320948b1680845294825291829020899055815189815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a350505050505050565b600160209081526000928352604080842090915290825290205481565b6004546001600160a01b031681565b6000467f000000000000000000000000000000000000000000000000000000000000000081146112235761121e8161140d565b611245565b7f00000000000000000000000000000000000000000000000000000000000000005b91505090565b818101818110156106ca576040805162461bcd60e51b815260206004820152601860248201527f426f72696e674d6174683a20416464204f766572666c6f770000000000000000604482015290519081900360640190fd5b60008115806112be575050808202828282816112bb57fe5b04145b6106ca576040805162461bcd60e51b815260206004820152601860248201527f426f72696e674d6174683a204d756c204f766572666c6f770000000000000000604482015290519081900360640190fd5b60006001600160801b0382111561136d576040805162461bcd60e51b815260206004820152601c60248201527f426f72696e674d6174683a2075696e74313238204f766572666c6f7700000000604482015290519081900360640190fd5b5090565b600060405180604001604052806002815260200161190160f01b8152506113966111eb565b836040516020018084805190602001908083835b602083106113c95780518252601f1990920191602091820191016113aa565b51815160209384036101000a600019018019909216911617905292019485525083810192909252506040805180840383018152928101905281519101209392505050565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218602080830191909152818301939093523060608083019190915282518083039091018152608090910190915280519101209056fea2646970667358221220626f7582c87502e024292c3aeeee593ab9a0b2e15c4032188a7ae6c73cffe59b64736f6c634300060c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061016c5760003560e01c8063586fc5b5116100cd57806395d89b4111610081578063d505accf11610066578063d505accf1461043e578063dd62ed3e1461048f578063e30c3978146104bd5761016c565b806395d89b411461040a578063a9059cbb146104125761016c565b806370a08231116100b257806370a082311461039a5780637ecebe00146103c05780638da5cb5b146103e65761016c565b8063586fc5b51461032d57806369e40265146103645761016c565b8063313ce5671161012457806340c10f191161010957806340c10f19146102dc57806342966c68146103085780634e71e0c8146103255761016c565b8063313ce567146102b65780633644e515146102d45761016c565b8063095ea7b311610155578063095ea7b31461022657806318160ddd1461026657806323b872dd146102805761016c565b806306fdde0314610171578063078dfbe7146101ee575b600080fd5b6101796104c5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101b357818101518382015260200161019b565b50505050905090810190601f1680156101e05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102246004803603606081101561020457600080fd5b506001600160a01b038135169060208101351515906040013515156104fe565b005b6102526004803603604081101561023c57600080fd5b506001600160a01b038135169060200135610669565b604080519115158252519081900360200190f35b61026e6106d0565b60408051918252519081900360200190f35b6102526004803603606081101561029657600080fd5b506001600160a01b038135811691602081013590911690604001356106d6565b6102be6108ef565b6040805160ff9092168252519081900360200190f35b61026e6108f4565b610224600480360360408110156102f257600080fd5b506001600160a01b038135169060200135610903565b6102246004803603602081101561031e57600080fd5b5035610afe565b610224610bba565b610335610c8a565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102246004803603606081101561037a57600080fd5b506001600160a01b03813581169160208101359160409091013516610ca4565b61026e600480360360208110156103b057600080fd5b50356001600160a01b0316610da4565b61026e600480360360208110156103d657600080fd5b50356001600160a01b0316610db6565b6103ee610dc8565b604080516001600160a01b039092168252519081900360200190f35b610179610dd7565b6102526004803603604081101561042857600080fd5b506001600160a01b038135169060200135610df6565b610224600480360360e081101561045457600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610f58565b61026e600480360360408110156104a557600080fd5b506001600160a01b03813581169160200135166111bf565b6103ee6111dc565b6040518060400160405280601381526020017f4d6167696320496e7465726e657420476f6c640000000000000000000000000081525081565b6003546001600160a01b0316331461055d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b811561063b576001600160a01b0383161515806105775750805b6105c8576040805162461bcd60e51b815260206004820152601560248201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604482015290519081900360640190fd5b6003546040516001600160a01b038086169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b03851673ffffffffffffffffffffffffffffffffffffffff1991821617909155600480549091169055610664565b6004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385161790555b505050565b3360008181526001602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b60055481565b6000811561089a576001600160a01b0384166000908152602081905260409020548281101561074c576040805162461bcd60e51b815260206004820152601660248201527f45524332303a2062616c616e636520746f6f206c6f7700000000000000000000604482015290519081900360640190fd5b836001600160a01b0316856001600160a01b031614610898576001600160a01b0385166000908152600160209081526040808320338452909152902054600019811461081057838110156107e7576040805162461bcd60e51b815260206004820152601860248201527f45524332303a20616c6c6f77616e636520746f6f206c6f770000000000000000604482015290519081900360640190fd5b6001600160a01b0386166000908152600160209081526040808320338452909152902084820390555b6001600160a01b03851661086b576040805162461bcd60e51b815260206004820152601660248201527f45524332303a206e6f207a65726f206164647265737300000000000000000000604482015290519081900360640190fd5b506001600160a01b0380861660009081526020819052604080822086850390559186168152208054840190555b505b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a35060019392505050565b601281565b60006108fe6111eb565b905090565b6003546001600160a01b03163314610962576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0382166109bd576040805162461bcd60e51b815260206004820152601c60248201527f4d49473a206e6f206d696e7420746f207a65726f206164647265737300000000604482015290519081900360640190fd5b600654600090610a0a9083906201517f1942016001600160801b03909116106109f857600654600160801b90046001600160801b03166109fb565b60005b6001600160801b03169061124b565b905060055460001480610a3f575080620186a0610a34613a986005546112a390919063ffffffff16565b81610a3b57fe5b0410155b610a4857600080fd5b610a514261130f565b600680546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055610a838161130f565b600680546001600160801b03928316600160801b02921691909117905560058054830190556001600160a01b038316600081815260208181526040808320805487019055805186815290517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a3505050565b33600090815260208190526040902054811115610b62576040805162461bcd60e51b815260206004820152600f60248201527f4d494d3a206e6f7420656e6f7567680000000000000000000000000000000000604482015290519081900360640190fd5b3360008181526020818152604080832080548690039055600580548690039055805185815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350565b6004546001600160a01b0316338114610c1a576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e6572604482015290519081900360640190fd5b6003546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0390921673ffffffffffffffffffffffffffffffffffffffff19928316179055600480549091169055565b6006546001600160801b0380821691600160801b90041682565b6003546001600160a01b03163314610d03576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610d0d8183610903565b6040805162ae511b60e21b81523060048201526001600160a01b0380841660248301819052908616604483015260648201859052600060848301819052835191936302b9446c9360a4808201949293918390030190829087803b158015610d7357600080fd5b505af1158015610d87573d6000803e3d6000fd5b505050506040513d6040811015610d9d57600080fd5b5050505050565b60006020819052908152604090205481565b60026020526000908152604090205481565b6003546001600160a01b031681565b604051806040016040528060038152602001624d494760e81b81525081565b600081151580610e0e5750336001600160a01b038416145b15610f0f573360009081526020819052604090205482811015610e78576040805162461bcd60e51b815260206004820152601660248201527f45524332303a2062616c616e636520746f6f206c6f7700000000000000000000604482015290519081900360640190fd5b336001600160a01b03851614610f0d576001600160a01b038416610ee3576040805162461bcd60e51b815260206004820152601660248201527f45524332303a206e6f207a65726f206164647265737300000000000000000000604482015290519081900360640190fd5b3360009081526020819052604080822085840390556001600160a01b038616825290208054840190555b505b6040805183815290516001600160a01b0385169133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600192915050565b6001600160a01b038716610fb3576040805162461bcd60e51b815260206004820152601860248201527f45524332303a204f776e65722063616e6e6f7420626520300000000000000000604482015290519081900360640190fd5b834210611007576040805162461bcd60e51b815260206004820152600e60248201527f45524332303a2045787069726564000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b038088166000818152600260209081526040918290208054600181810190925583517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981850152808501869052958c166060870152608086018b905260a086015260c08086018a90528351808703909101815260e0909501909252835193019290922090919061109d90611371565b85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156110f4573d6000803e3d6000fd5b505050602060405103516001600160a01b031614611159576040805162461bcd60e51b815260206004820152601860248201527f45524332303a20496e76616c6964205369676e61747572650000000000000000604482015290519081900360640190fd5b6001600160a01b038088166000818152600160209081526040808320948b1680845294825291829020899055815189815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a350505050505050565b600160209081526000928352604080842090915290825290205481565b6004546001600160a01b031681565b6000467f000000000000000000000000000000000000000000000000000000000000000081146112235761121e8161140d565b611245565b7f00000000000000000000000000000000000000000000000000000000000000005b91505090565b818101818110156106ca576040805162461bcd60e51b815260206004820152601860248201527f426f72696e674d6174683a20416464204f766572666c6f770000000000000000604482015290519081900360640190fd5b60008115806112be575050808202828282816112bb57fe5b04145b6106ca576040805162461bcd60e51b815260206004820152601860248201527f426f72696e674d6174683a204d756c204f766572666c6f770000000000000000604482015290519081900360640190fd5b60006001600160801b0382111561136d576040805162461bcd60e51b815260206004820152601c60248201527f426f72696e674d6174683a2075696e74313238204f766572666c6f7700000000604482015290519081900360640190fd5b5090565b600060405180604001604052806002815260200161190160f01b8152506113966111eb565b836040516020018084805190602001908083835b602083106113c95780518252601f1990920191602091820191016113aa565b51815160209384036101000a600019018019909216911617905292019485525083810192909252506040805180840383018152928101905281519101209392505050565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218602080830191909152818301939093523060608083019190915282518083039091018152608090910190915280519101209056fea2646970667358221220626f7582c87502e024292c3aeeee593ab9a0b2e15c4032188a7ae6c73cffe59b64736f6c634300060c0033", + "devdoc": { + "kind": "dev", + "methods": { + "approve(address,uint256)": { + "params": { + "amount": "The maximum collective amount that `spender` can draw.", + "spender": "Address of the party that can draw from msg.sender's account." + }, + "returns": { + "_0": "(bool) Returns True if approved." + } + }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "params": { + "deadline": "This permit must be redeemed before this deadline (UTC timestamp in seconds).", + "owner_": "Address of the owner.", + "spender": "The address of the spender that gets approved to draw from `owner_`.", + "value": "The maximum collective amount that `spender` can draw." + } + }, + "transfer(address,uint256)": { + "params": { + "amount": "of the tokens to move.", + "to": "The address to move the tokens." + }, + "returns": { + "_0": "(bool) Returns True if succeeded." + } + }, + "transferFrom(address,address,uint256)": { + "params": { + "amount": "The token amount to move.", + "from": "Address to draw tokens from.", + "to": "The address to move the tokens." + }, + "returns": { + "_0": "(bool) Returns True if succeeded." + } + }, + "transferOwnership(address,bool,bool)": { + "params": { + "direct": "True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.", + "newOwner": "Address of the new owner.", + "renounce": "Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise." + } + } + }, + "title": "Magic Internet Gold", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "allowance(address,address)": { + "notice": "owner > spender > allowance mapping." + }, + "approve(address,uint256)": { + "notice": "Approves `amount` from sender to be spend by `spender`." + }, + "balanceOf(address)": { + "notice": "owner > balance mapping." + }, + "claimOwnership()": { + "notice": "Needs to be called by `pendingOwner` to claim ownership." + }, + "nonces(address)": { + "notice": "owner > nonce mapping. Used in `permit`." + }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "notice": "Approves `value` from `owner_` to be spend by `spender`." + }, + "transfer(address,uint256)": { + "notice": "Transfers `amount` tokens from `msg.sender` to `to`." + }, + "transferFrom(address,address,uint256)": { + "notice": "Transfers `amount` tokens from `from` to `to`. Caller needs approval for `from`." + }, + "transferOwnership(address,bool,bool)": { + "notice": "Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner. Can only be invoked by the current `owner`." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 368, + "contract": "contracts/MagicInternetGold.sol:MagicInternetGold", + "label": "balanceOf", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 376, + "contract": "contracts/MagicInternetGold.sol:MagicInternetGold", + "label": "allowance", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 381, + "contract": "contracts/MagicInternetGold.sol:MagicInternetGold", + "label": "nonces", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 118, + "contract": "contracts/MagicInternetGold.sol:MagicInternetGold", + "label": "owner", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 120, + "contract": "contracts/MagicInternetGold.sol:MagicInternetGold", + "label": "pendingOwner", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 4827, + "contract": "contracts/MagicInternetGold.sol:MagicInternetGold", + "label": "totalSupply", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 4834, + "contract": "contracts/MagicInternetGold.sol:MagicInternetGold", + "label": "lastMint", + "offset": 0, + "slot": "6", + "type": "t_struct(Minting)4832_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(Minting)4832_storage": { + "encoding": "inplace", + "label": "struct MagicInternetGold.Minting", + "members": [ + { + "astId": 4829, + "contract": "contracts/MagicInternetGold.sol:MagicInternetGold", + "label": "time", + "offset": 0, + "slot": "0", + "type": "t_uint128" + }, + { + "astId": 4831, + "contract": "contracts/MagicInternetGold.sol:MagicInternetGold", + "label": "amount", + "offset": 16, + "slot": "0", + "type": "t_uint128" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/mainnet/WBTCMigCauldron.json b/deployments/mainnet/WBTCMigCauldron.json new file mode 100644 index 00000000..34b04703 --- /dev/null +++ b/deployments/mainnet/WBTCMigCauldron.json @@ -0,0 +1,5 @@ +{ + "address": "0x6aA3A55c65aF5b4EfF4D8fb5069376fcD5D756A5", + "abi": [], + "numDeployments": 1 +} \ No newline at end of file diff --git a/deployments/mainnet/WBTCMigOracleV1.json b/deployments/mainnet/WBTCMigOracleV1.json new file mode 100644 index 00000000..c8350699 --- /dev/null +++ b/deployments/mainnet/WBTCMigOracleV1.json @@ -0,0 +1,231 @@ +{ + "address": "0xDD1052137472CcA4c2f55B93Cc9C0f06EC20b6b0", + "abi": [ + { + "inputs": [], + "name": "BTCUSD", + "outputs": [ + { + "internalType": "contract IAggregator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOLD", + "outputs": [ + { + "internalType": "contract IAggregator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "get", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "peek", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "peekSpot", + "outputs": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xd1975108ac0dd986dd2d33c3526b0f95b54437a156811ecfa49459b8fdf372d1", + "receipt": { + "to": null, + "from": "0xb4EfdA6DAf5ef75D08869A0f9C0213278fb43b6C", + "contractAddress": "0xDD1052137472CcA4c2f55B93Cc9C0f06EC20b6b0", + "transactionIndex": 34, + "gasUsed": "303339", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xabc36f1a0465145315adfb5f0c3dde0e6cd6b4abf19024c78d06daf15f68f7a0", + "transactionHash": "0xd1975108ac0dd986dd2d33c3526b0f95b54437a156811ecfa49459b8fdf372d1", + "logs": [], + "blockNumber": 14818528, + "cumulativeGasUsed": "2818636", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "f3c6669b166894ac5cec2d9fe7c3a109", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"BTCUSD\",\"outputs\":[{\"internalType\":\"contract IAggregator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GOLD\",\"outputs\":[{\"internalType\":\"contract IAggregator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"get\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"peek\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"peekSpot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"get(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"_0\":\"if no valid (recent) rate is available, return false else true.\",\"_1\":\"The rate of the requested asset / pair / pool.\"}},\"name(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"_0\":\"(string) A human readable name about this oracle.\"}},\"peek(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"_0\":\"if no valid (recent) rate is available, return false else true.\",\"_1\":\"The rate of the requested asset / pair / pool.\"}},\"peekSpot(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"rate\":\"The rate of the requested asset / pair / pool.\"}},\"symbol(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"_0\":\"(string) A human readable symbol name about this oracle.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"get(bytes)\":{\"notice\":\"Get the latest exchange rate.\"},\"name(bytes)\":{\"notice\":\"Returns a human readable name about this oracle.\"},\"peek(bytes)\":{\"notice\":\"Check the last exchange rate without any state changes.\"},\"peekSpot(bytes)\":{\"notice\":\"Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().\"},\"symbol(bytes)\":{\"notice\":\"Returns a human readable (short) name about this oracle.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/oracles/WbtcOracleMig.sol\":\"WbtcOracleMig\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":690},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.6.12;\\n\\ninterface IOracle {\\n /// @notice Get the latest exchange rate.\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return success if no valid (recent) rate is available, return false else true.\\n /// @return rate The rate of the requested asset / pair / pool.\\n function get(bytes calldata data) external returns (bool success, uint256 rate);\\n\\n /// @notice Check the last exchange rate without any state changes.\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return success if no valid (recent) rate is available, return false else true.\\n /// @return rate The rate of the requested asset / pair / pool.\\n function peek(bytes calldata data) external view returns (bool success, uint256 rate);\\n\\n /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return rate The rate of the requested asset / pair / pool.\\n function peekSpot(bytes calldata data) external view returns (uint256 rate);\\n\\n /// @notice Returns a human readable (short) name about this oracle.\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return (string) A human readable symbol name about this oracle.\\n function symbol(bytes calldata data) external view returns (string memory);\\n\\n /// @notice Returns a human readable name about this oracle.\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return (string) A human readable name about this oracle.\\n function name(bytes calldata data) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x4b3446c52308ff064dc7caa7cddd05aed7d999f1aa269a5a1d26792753a99b58\",\"license\":\"MIT\"},\"contracts/oracles/WbtcOracleMig.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.10;\\nimport \\\"../interfaces/IOracle.sol\\\";\\n\\n// Chainlink Aggregator\\n\\ninterface IAggregator {\\n function latestAnswer() external view returns (int256 answer);\\n}\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n\\n function balanceOf(address account) external view returns (uint256);\\n}\\n\\ncontract WbtcOracleMig is IOracle {\\n IAggregator public constant BTCUSD = IAggregator(0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c);\\n IAggregator public constant GOLD = IAggregator(0x214eD9Da11D2fbe465a6fc601a91E62EbEc1a0D6);\\n // Calculates the lastest exchange rate\\n // Uses both divide and multiply only for tokens not supported directly by Chainlink, for example MKR/USD\\n function _get() internal view returns (uint256) {\\n uint256 btcPrice = uint256(BTCUSD.latestAnswer());\\n uint256 goldPrice = uint256(GOLD.latestAnswer());\\n return goldPrice * 1e8 / btcPrice;\\n }\\n\\n // Get the latest exchange rate\\n /// @inheritdoc IOracle\\n function get(bytes calldata) public view override returns (bool, uint256) {\\n return (true, _get());\\n }\\n\\n // Check the last exchange rate without any state changes\\n /// @inheritdoc IOracle\\n function peek(bytes calldata) public view override returns (bool, uint256) {\\n return (true, _get());\\n }\\n\\n // Check the current spot exchange rate without any state changes\\n /// @inheritdoc IOracle\\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\\n (, rate) = peek(data);\\n }\\n\\n /// @inheritdoc IOracle\\n function name(bytes calldata) public pure override returns (string memory) {\\n return \\\"Chainlink GOLD BTC\\\";\\n }\\n\\n /// @inheritdoc IOracle\\n function symbol(bytes calldata) public pure override returns (string memory) {\\n return \\\"LINK/GOLD/BTC\\\";\\n }\\n}\\n\",\"keccak256\":\"0x4a252128ca3814a4c1ecf254245b18bf07133fcf31f78bc0da782d6dac14876c\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610488806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063d568866c1161005b578063d568866c1461013c578063d6d7d52514610183578063eeb8a8d314610183578063fc2650d8146101ad57600080fd5b80633e4bee3814610082578063c699c4d6146100c7578063d39bbef01461011b575b600080fd5b61009d73214ed9da11d2fbe465a6fc601a91e62ebec1a0d681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61010e6100d5366004610323565b505060408051808201909152600d81527f4c494e4b2f474f4c442f42544300000000000000000000000000000000000000602082015290565b6040516100be9190610395565b61012e610129366004610323565b6101c8565b6040519081526020016100be565b61010e61014a366004610323565b505060408051808201909152601281527f436861696e6c696e6b20474f4c44204254430000000000000000000000000000602082015290565b610196610191366004610323565b6101dc565b6040805192151583526020830191909152016100be565b61009d73f4030086522a5beea4988f8ca5b36dbc97bee88c81565b60006101d483836101dc565b949350505050565b60008060016101e96101f4565b915091509250929050565b60008073f4030086522a5beea4988f8ca5b36dbc97bee88c73ffffffffffffffffffffffffffffffffffffffff166350d25bcd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027a91906103ea565b9050600073214ed9da11d2fbe465a6fc601a91e62ebec1a0d673ffffffffffffffffffffffffffffffffffffffff166350d25bcd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030191906103ea565b905081610312826305f5e100610403565b61031c9190610430565b9250505090565b6000806020838503121561033657600080fd5b823567ffffffffffffffff8082111561034e57600080fd5b818501915085601f83011261036257600080fd5b81358181111561037157600080fd5b86602082850101111561038357600080fd5b60209290920196919550909350505050565b600060208083528351808285015260005b818110156103c2578581018301518582016040015282016103a6565b818111156103d4576000604083870101525b50601f01601f1916929092016040019392505050565b6000602082840312156103fc57600080fd5b5051919050565b600081600019048311821515161561042b57634e487b7160e01b600052601160045260246000fd5b500290565b60008261044d57634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220a237b19474f742898c47d57418a3398250303c9a885f8f597ee8c7310ec5533b64736f6c634300080a0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063d568866c1161005b578063d568866c1461013c578063d6d7d52514610183578063eeb8a8d314610183578063fc2650d8146101ad57600080fd5b80633e4bee3814610082578063c699c4d6146100c7578063d39bbef01461011b575b600080fd5b61009d73214ed9da11d2fbe465a6fc601a91e62ebec1a0d681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61010e6100d5366004610323565b505060408051808201909152600d81527f4c494e4b2f474f4c442f42544300000000000000000000000000000000000000602082015290565b6040516100be9190610395565b61012e610129366004610323565b6101c8565b6040519081526020016100be565b61010e61014a366004610323565b505060408051808201909152601281527f436861696e6c696e6b20474f4c44204254430000000000000000000000000000602082015290565b610196610191366004610323565b6101dc565b6040805192151583526020830191909152016100be565b61009d73f4030086522a5beea4988f8ca5b36dbc97bee88c81565b60006101d483836101dc565b949350505050565b60008060016101e96101f4565b915091509250929050565b60008073f4030086522a5beea4988f8ca5b36dbc97bee88c73ffffffffffffffffffffffffffffffffffffffff166350d25bcd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027a91906103ea565b9050600073214ed9da11d2fbe465a6fc601a91e62ebec1a0d673ffffffffffffffffffffffffffffffffffffffff166350d25bcd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030191906103ea565b905081610312826305f5e100610403565b61031c9190610430565b9250505090565b6000806020838503121561033657600080fd5b823567ffffffffffffffff8082111561034e57600080fd5b818501915085601f83011261036257600080fd5b81358181111561037157600080fd5b86602082850101111561038357600080fd5b60209290920196919550909350505050565b600060208083528351808285015260005b818110156103c2578581018301518582016040015282016103a6565b818111156103d4576000604083870101525b50601f01601f1916929092016040019392505050565b6000602082840312156103fc57600080fd5b5051919050565b600081600019048311821515161561042b57634e487b7160e01b600052601160045260246000fd5b500290565b60008261044d57634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220a237b19474f742898c47d57418a3398250303c9a885f8f597ee8c7310ec5533b64736f6c634300080a0033", + "devdoc": { + "kind": "dev", + "methods": { + "get(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "_0": "if no valid (recent) rate is available, return false else true.", + "_1": "The rate of the requested asset / pair / pool." + } + }, + "name(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "_0": "(string) A human readable name about this oracle." + } + }, + "peek(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "_0": "if no valid (recent) rate is available, return false else true.", + "_1": "The rate of the requested asset / pair / pool." + } + }, + "peekSpot(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "rate": "The rate of the requested asset / pair / pool." + } + }, + "symbol(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "_0": "(string) A human readable symbol name about this oracle." + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "get(bytes)": { + "notice": "Get the latest exchange rate." + }, + "name(bytes)": { + "notice": "Returns a human readable name about this oracle." + }, + "peek(bytes)": { + "notice": "Check the last exchange rate without any state changes." + }, + "peekSpot(bytes)": { + "notice": "Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek()." + }, + "symbol(bytes)": { + "notice": "Returns a human readable (short) name about this oracle." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/mainnet/WBTCMigProxyOracle.json b/deployments/mainnet/WBTCMigProxyOracle.json new file mode 100644 index 00000000..314ff721 --- /dev/null +++ b/deployments/mainnet/WBTCMigProxyOracle.json @@ -0,0 +1,397 @@ +{ + "address": "0x0f75c5f723681A6897dc2fb6fFA672a4929028A6", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IOracle", + "name": "oldOracle", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IOracle", + "name": "newOracle", + "type": "address" + } + ], + "name": "LogOracleImplementationChange", + "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" + }, + { + "inputs": [ + { + "internalType": "contract IOracle", + "name": "newOracle", + "type": "address" + } + ], + "name": "changeOracleImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "get", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracleImplementation", + "outputs": [ + { + "internalType": "contract IOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "peek", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "peekSpot", + "outputs": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + }, + { + "internalType": "bool", + "name": "direct", + "type": "bool" + }, + { + "internalType": "bool", + "name": "renounce", + "type": "bool" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x6d1da288ae9286d42fb431425a8c75378332cece3449f4795df013a208caf8b9", + "receipt": { + "to": null, + "from": "0xb4EfdA6DAf5ef75D08869A0f9C0213278fb43b6C", + "contractAddress": "0x0f75c5f723681A6897dc2fb6fFA672a4929028A6", + "transactionIndex": 247, + "gasUsed": "611170", + "logsBloom": "0x00000000000000000000000000000000000004000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000020000000000000000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000080000020000008000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x110257a4a59581b0abe063d0598de74a00320739994e885afa5dae419ed4c716", + "transactionHash": "0x6d1da288ae9286d42fb431425a8c75378332cece3449f4795df013a208caf8b9", + "logs": [ + { + "transactionIndex": 247, + "blockNumber": 14818518, + "transactionHash": "0x6d1da288ae9286d42fb431425a8c75378332cece3449f4795df013a208caf8b9", + "address": "0x0f75c5f723681A6897dc2fb6fFA672a4929028A6", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000b4efda6daf5ef75d08869a0f9c0213278fb43b6c" + ], + "data": "0x", + "logIndex": 439, + "blockHash": "0x110257a4a59581b0abe063d0598de74a00320739994e885afa5dae419ed4c716" + } + ], + "blockNumber": 14818518, + "cumulativeGasUsed": "21604890", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "a8287f9582549e1e61e2a34e7021b1e9", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IOracle\",\"name\":\"oldOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract IOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"LogOracleImplementationChange\",\"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\"},{\"inputs\":[{\"internalType\":\"contract IOracle\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"changeOracleImplementation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"get\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracleImplementation\",\"outputs\":[{\"internalType\":\"contract IOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"peek\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"peekSpot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"rate\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"direct\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"renounce\",\"type\":\"bool\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"0xMerlin\",\"kind\":\"dev\",\"methods\":{\"get(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"_0\":\"success if no valid (recent) rate is available, return false else true.\",\"_1\":\"rate The rate of the requested asset / pair / pool.\"}},\"name(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"_0\":\"(string) A human readable name about this oracle.\"}},\"peek(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"_0\":\"success if no valid (recent) rate is available, return false else true.\",\"_1\":\"rate The rate of the requested asset / pair / pool.\"}},\"peekSpot(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"rate\":\"The rate of the requested asset / pair / pool.\"}},\"symbol(bytes)\":{\"params\":{\"data\":\"Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\"},\"returns\":{\"_0\":\"(string) A human readable symbol name about this oracle.\"}},\"transferOwnership(address,bool,bool)\":{\"params\":{\"direct\":\"True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\",\"newOwner\":\"Address of the new owner.\",\"renounce\":\"Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\"}}},\"title\":\"ProxyOracle\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"claimOwnership()\":{\"notice\":\"Needs to be called by `pendingOwner` to claim ownership.\"},\"get(bytes)\":{\"notice\":\"Get the latest exchange rate.\"},\"name(bytes)\":{\"notice\":\"Returns a human readable name about this oracle.\"},\"peek(bytes)\":{\"notice\":\"Check the last exchange rate without any state changes.\"},\"peekSpot(bytes)\":{\"notice\":\"Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().\"},\"symbol(bytes)\":{\"notice\":\"Returns a human readable (short) name about this oracle.\"},\"transferOwnership(address,bool,bool)\":{\"notice\":\"Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner. Can only be invoked by the current `owner`.\"}},\"notice\":\"Oracle used for getting the price of an oracle implementation\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/oracles/ProxyOracle.sol\":\"ProxyOracle\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":690},\"remappings\":[]},\"sources\":{\"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\\n// Edited by BoringCrypto\\n\\ncontract BoringOwnableData {\\n address public owner;\\n address public pendingOwner;\\n}\\n\\ncontract BoringOwnable is BoringOwnableData {\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /// @notice `owner` defaults to msg.sender on construction.\\n constructor() public {\\n owner = msg.sender;\\n emit OwnershipTransferred(address(0), msg.sender);\\n }\\n\\n /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.\\n /// Can only be invoked by the current `owner`.\\n /// @param newOwner Address of the new owner.\\n /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\\n /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\\n function transferOwnership(\\n address newOwner,\\n bool direct,\\n bool renounce\\n ) public onlyOwner {\\n if (direct) {\\n // Checks\\n require(newOwner != address(0) || renounce, \\\"Ownable: zero address\\\");\\n\\n // Effects\\n emit OwnershipTransferred(owner, newOwner);\\n owner = newOwner;\\n pendingOwner = address(0);\\n } else {\\n // Effects\\n pendingOwner = newOwner;\\n }\\n }\\n\\n /// @notice Needs to be called by `pendingOwner` to claim ownership.\\n function claimOwnership() public {\\n address _pendingOwner = pendingOwner;\\n\\n // Checks\\n require(msg.sender == _pendingOwner, \\\"Ownable: caller != pending owner\\\");\\n\\n // Effects\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = address(0);\\n }\\n\\n /// @notice Only allows the `owner` to execute the function.\\n modifier onlyOwner() {\\n require(msg.sender == owner, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n}\\n\",\"keccak256\":\"0xbde1619421fef865bf5f5f806e319900fb862e27f0aef6e0878e93f04f477601\",\"license\":\"MIT\"},\"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\ninterface IERC20 {\\n function totalSupply() external view returns (uint256);\\n\\n function balanceOf(address account) external view returns (uint256);\\n\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /// @notice EIP 2612\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0xf0da35541d6ae9e3c12fdd7c8d5d9584c56f9ac50d062efb8ca353ebd6ffd47d\",\"license\":\"MIT\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.6.12;\\n\\ninterface IOracle {\\n /// @notice Get the latest exchange rate.\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return success if no valid (recent) rate is available, return false else true.\\n /// @return rate The rate of the requested asset / pair / pool.\\n function get(bytes calldata data) external returns (bool success, uint256 rate);\\n\\n /// @notice Check the last exchange rate without any state changes.\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return success if no valid (recent) rate is available, return false else true.\\n /// @return rate The rate of the requested asset / pair / pool.\\n function peek(bytes calldata data) external view returns (bool success, uint256 rate);\\n\\n /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return rate The rate of the requested asset / pair / pool.\\n function peekSpot(bytes calldata data) external view returns (uint256 rate);\\n\\n /// @notice Returns a human readable (short) name about this oracle.\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return (string) A human readable symbol name about this oracle.\\n function symbol(bytes calldata data) external view returns (string memory);\\n\\n /// @notice Returns a human readable name about this oracle.\\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\\n /// For example:\\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\\n /// @return (string) A human readable name about this oracle.\\n function name(bytes calldata data) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x4b3446c52308ff064dc7caa7cddd05aed7d999f1aa269a5a1d26792753a99b58\",\"license\":\"MIT\"},\"contracts/oracles/ProxyOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.6.12;\\n\\nimport \\\"../interfaces/IOracle.sol\\\";\\nimport \\\"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\\\";\\nimport \\\"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\\\";\\n\\n/// @title ProxyOracle\\n/// @author 0xMerlin\\n/// @notice Oracle used for getting the price of an oracle implementation\\ncontract ProxyOracle is IOracle, BoringOwnable {\\n IOracle public oracleImplementation;\\n\\n event LogOracleImplementationChange(IOracle indexed oldOracle, IOracle indexed newOracle);\\n\\n constructor() public {}\\n\\n function changeOracleImplementation(IOracle newOracle) external onlyOwner {\\n IOracle oldOracle = oracleImplementation;\\n oracleImplementation = newOracle;\\n emit LogOracleImplementationChange(oldOracle, newOracle);\\n }\\n\\n // Get the latest exchange rate\\n /// @inheritdoc IOracle\\n function get(bytes calldata data) public override returns (bool, uint256) {\\n return oracleImplementation.get(data);\\n }\\n\\n // Check the last exchange rate without any state changes\\n /// @inheritdoc IOracle\\n function peek(bytes calldata data) public view override returns (bool, uint256) {\\n return oracleImplementation.peek(data);\\n }\\n\\n // Check the current spot exchange rate without any state changes\\n /// @inheritdoc IOracle\\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\\n return oracleImplementation.peekSpot(data);\\n }\\n\\n /// @inheritdoc IOracle\\n function name(bytes calldata) public view override returns (string memory) {\\n return \\\"Proxy Oracle\\\";\\n }\\n\\n /// @inheritdoc IOracle\\n function symbol(bytes calldata) public view override returns (string memory) {\\n return \\\"Proxy\\\";\\n }\\n}\\n\",\"keccak256\":\"0x6bd6ab151c747a36b2a2f36062154ccb42cd2d5112ea451d1d55c08da7c1c1e3\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36109a98061005f6000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063cb19341011610081578063d6d7d5251161005b578063d6d7d52514610337578063e30c3978146103c2578063eeb8a8d3146103ca576100c9565b8063cb1934101461023d578063d39bbef014610245578063d568866c146102c7576100c9565b8063784ce806116100b2578063784ce8061461010e5780638da5cb5b14610134578063c699c4d614610158576100c9565b8063078dfbe7146100ce5780634e71e0c814610106575b600080fd5b610104600480360360608110156100e457600080fd5b506001600160a01b0381351690602081013515159060400135151561043a565b005b61010461058a565b6101046004803603602081101561012457600080fd5b50356001600160a01b031661064c565b61013c6106fd565b604080516001600160a01b039092168252519081900360200190f35b6101c86004803603602081101561016e57600080fd5b81019060208101813564010000000081111561018957600080fd5b82018360208201111561019b57600080fd5b803590602001918460018302840111640100000000831117156101bd57600080fd5b50909250905061070c565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102025781810151838201526020016101ea565b50505050905090810190601f16801561022f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61013c61072d565b6102b56004803603602081101561025b57600080fd5b81019060208101813564010000000081111561027657600080fd5b82018360208201111561028857600080fd5b803590602001918460018302840111640100000000831117156102aa57600080fd5b50909250905061073c565b60408051918252519081900360200190f35b6101c8600480360360208110156102dd57600080fd5b8101906020810181356401000000008111156102f857600080fd5b82018360208201111561030a57600080fd5b8035906020019184600183028401116401000000008311171561032c57600080fd5b5090925090506107e5565b6103a76004803603602081101561034d57600080fd5b81019060208101813564010000000081111561036857600080fd5b82018360208201111561037a57600080fd5b8035906020019184600183028401116401000000008311171561039c57600080fd5b50909250905061081e565b60408051921515835260208301919091528051918290030190f35b61013c6108d7565b6103a7600480360360208110156103e057600080fd5b8101906020810181356401000000008111156103fb57600080fd5b82018360208201111561040d57600080fd5b8035906020019184600183028401116401000000008311171561042f57600080fd5b5090925090506108e6565b6000546001600160a01b03163314610499576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b8115610569576001600160a01b0383161515806104b35750805b610504576040805162461bcd60e51b815260206004820152601560248201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604482015290519081900360640190fd5b600080546040516001600160a01b03808716939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0385166001600160a01b031991821617909155600180549091169055610585565b600180546001600160a01b0319166001600160a01b0385161790555b505050565b6001546001600160a01b03163381146105ea576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b6000546001600160a01b031633146106ab576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8e0352ee1de57032a7c8ddf4cb1daa3ff929d0a8534e42a124811b2fa033cccd90600090a35050565b6000546001600160a01b031681565b505060408051808201909152600581526450726f787960d81b602082015290565b6002546001600160a01b031681565b600254604051630d39bbef60e41b8152602060048201908152602482018490526000926001600160a01b03169163d39bbef09186918691908190604401848480828437600083820152604051601f909101601f191690920195506020945090925050508083038186803b1580156107b257600080fd5b505afa1580156107c6573d6000803e3d6000fd5b505050506040513d60208110156107dc57600080fd5b50519392505050565b505060408051808201909152600c81527f50726f7879204f7261636c650000000000000000000000000000000000000000602082015290565b60025460405163d6d7d52560e01b81526020600482019081526024820184905260009283926001600160a01b039091169163d6d7d52591879187918190604401848480828437600081840152601f19601f82011690508083019250505093505050506040805180830381600087803b15801561089957600080fd5b505af11580156108ad573d6000803e3d6000fd5b505050506040513d60408110156108c357600080fd5b508051602090910151909590945092505050565b6001546001600160a01b031681565b60025460405163eeb8a8d360e01b81526020600482019081526024820184905260009283926001600160a01b039091169163eeb8a8d39187918791819060440184848082843760008382015260408051601f909201601f1916909301965091945090925050508083038186803b15801561095f57600080fd5b505afa1580156108ad573d6000803e3d6000fdfea26469706673582212205ea52aa47b905bf6fdc81e8f6828f166ea25fb69aefed1fe725c3cdbf8cd474164736f6c634300060c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100c95760003560e01c8063cb19341011610081578063d6d7d5251161005b578063d6d7d52514610337578063e30c3978146103c2578063eeb8a8d3146103ca576100c9565b8063cb1934101461023d578063d39bbef014610245578063d568866c146102c7576100c9565b8063784ce806116100b2578063784ce8061461010e5780638da5cb5b14610134578063c699c4d614610158576100c9565b8063078dfbe7146100ce5780634e71e0c814610106575b600080fd5b610104600480360360608110156100e457600080fd5b506001600160a01b0381351690602081013515159060400135151561043a565b005b61010461058a565b6101046004803603602081101561012457600080fd5b50356001600160a01b031661064c565b61013c6106fd565b604080516001600160a01b039092168252519081900360200190f35b6101c86004803603602081101561016e57600080fd5b81019060208101813564010000000081111561018957600080fd5b82018360208201111561019b57600080fd5b803590602001918460018302840111640100000000831117156101bd57600080fd5b50909250905061070c565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102025781810151838201526020016101ea565b50505050905090810190601f16801561022f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61013c61072d565b6102b56004803603602081101561025b57600080fd5b81019060208101813564010000000081111561027657600080fd5b82018360208201111561028857600080fd5b803590602001918460018302840111640100000000831117156102aa57600080fd5b50909250905061073c565b60408051918252519081900360200190f35b6101c8600480360360208110156102dd57600080fd5b8101906020810181356401000000008111156102f857600080fd5b82018360208201111561030a57600080fd5b8035906020019184600183028401116401000000008311171561032c57600080fd5b5090925090506107e5565b6103a76004803603602081101561034d57600080fd5b81019060208101813564010000000081111561036857600080fd5b82018360208201111561037a57600080fd5b8035906020019184600183028401116401000000008311171561039c57600080fd5b50909250905061081e565b60408051921515835260208301919091528051918290030190f35b61013c6108d7565b6103a7600480360360208110156103e057600080fd5b8101906020810181356401000000008111156103fb57600080fd5b82018360208201111561040d57600080fd5b8035906020019184600183028401116401000000008311171561042f57600080fd5b5090925090506108e6565b6000546001600160a01b03163314610499576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b8115610569576001600160a01b0383161515806104b35750805b610504576040805162461bcd60e51b815260206004820152601560248201527f4f776e61626c653a207a65726f20616464726573730000000000000000000000604482015290519081900360640190fd5b600080546040516001600160a01b03808716939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0385166001600160a01b031991821617909155600180549091169055610585565b600180546001600160a01b0319166001600160a01b0385161790555b505050565b6001546001600160a01b03163381146105ea576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092166001600160a01b0319928316179055600180549091169055565b6000546001600160a01b031633146106ab576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8e0352ee1de57032a7c8ddf4cb1daa3ff929d0a8534e42a124811b2fa033cccd90600090a35050565b6000546001600160a01b031681565b505060408051808201909152600581526450726f787960d81b602082015290565b6002546001600160a01b031681565b600254604051630d39bbef60e41b8152602060048201908152602482018490526000926001600160a01b03169163d39bbef09186918691908190604401848480828437600083820152604051601f909101601f191690920195506020945090925050508083038186803b1580156107b257600080fd5b505afa1580156107c6573d6000803e3d6000fd5b505050506040513d60208110156107dc57600080fd5b50519392505050565b505060408051808201909152600c81527f50726f7879204f7261636c650000000000000000000000000000000000000000602082015290565b60025460405163d6d7d52560e01b81526020600482019081526024820184905260009283926001600160a01b039091169163d6d7d52591879187918190604401848480828437600081840152601f19601f82011690508083019250505093505050506040805180830381600087803b15801561089957600080fd5b505af11580156108ad573d6000803e3d6000fd5b505050506040513d60408110156108c357600080fd5b508051602090910151909590945092505050565b6001546001600160a01b031681565b60025460405163eeb8a8d360e01b81526020600482019081526024820184905260009283926001600160a01b039091169163eeb8a8d39187918791819060440184848082843760008382015260408051601f909201601f1916909301965091945090925050508083038186803b15801561095f57600080fd5b505afa1580156108ad573d6000803e3d6000fdfea26469706673582212205ea52aa47b905bf6fdc81e8f6828f166ea25fb69aefed1fe725c3cdbf8cd474164736f6c634300060c0033", + "devdoc": { + "author": "0xMerlin", + "kind": "dev", + "methods": { + "get(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "_0": "success if no valid (recent) rate is available, return false else true.", + "_1": "rate The rate of the requested asset / pair / pool." + } + }, + "name(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "_0": "(string) A human readable name about this oracle." + } + }, + "peek(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "_0": "success if no valid (recent) rate is available, return false else true.", + "_1": "rate The rate of the requested asset / pair / pool." + } + }, + "peekSpot(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "rate": "The rate of the requested asset / pair / pool." + } + }, + "symbol(bytes)": { + "params": { + "data": "Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle. For example: (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));" + }, + "returns": { + "_0": "(string) A human readable symbol name about this oracle." + } + }, + "transferOwnership(address,bool,bool)": { + "params": { + "direct": "True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.", + "newOwner": "Address of the new owner.", + "renounce": "Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise." + } + } + }, + "title": "ProxyOracle", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "claimOwnership()": { + "notice": "Needs to be called by `pendingOwner` to claim ownership." + }, + "get(bytes)": { + "notice": "Get the latest exchange rate." + }, + "name(bytes)": { + "notice": "Returns a human readable name about this oracle." + }, + "peek(bytes)": { + "notice": "Check the last exchange rate without any state changes." + }, + "peekSpot(bytes)": { + "notice": "Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek()." + }, + "symbol(bytes)": { + "notice": "Returns a human readable (short) name about this oracle." + }, + "transferOwnership(address,bool,bool)": { + "notice": "Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner. Can only be invoked by the current `owner`." + } + }, + "notice": "Oracle used for getting the price of an oracle implementation", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 118, + "contract": "contracts/oracles/ProxyOracle.sol:ProxyOracle", + "label": "owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 120, + "contract": "contracts/oracles/ProxyOracle.sol:ProxyOracle", + "label": "pendingOwner", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 9070, + "contract": "contracts/oracles/ProxyOracle.sol:ProxyOracle", + "label": "oracleImplementation", + "offset": 0, + "slot": "2", + "type": "t_contract(IOracle)6101" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_contract(IOracle)6101": { + "encoding": "inplace", + "label": "contract IOracle", + "numberOfBytes": "20" + } + } + } +} \ No newline at end of file diff --git a/deployments/mainnet/solcInputs/9f4bd60296ecc46266e9c6fc79b5f896.json b/deployments/mainnet/solcInputs/9f4bd60296ecc46266e9c6fc79b5f896.json new file mode 100644 index 00000000..a2fb3521 --- /dev/null +++ b/deployments/mainnet/solcInputs/9f4bd60296ecc46266e9c6fc79b5f896.json @@ -0,0 +1,73 @@ +{ + "language": "Solidity", + "sources": { + "contracts/CauldronV3.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\n// Cauldron\n\n// ( ( (\n// )\\ ) ( )\\ )\\ ) (\n// (((_) ( /( ))\\ ((_)(()/( )( ( (\n// )\\___ )(_)) /((_) _ ((_))(()\\ )\\ )\\ )\n// ((/ __|((_)_ (_))( | | _| | ((_) ((_) _(_/(\n// | (__ / _` || || || |/ _` | | '_|/ _ \\| ' \\))\n// \\___|\\__,_| \\_,_||_|\\__,_| |_| \\___/|_||_|\n\n// Copyright (c) 2021 BoringCrypto - All rights reserved\n// Twitter: @Boring_Crypto\n\n// Special thanks to:\n// @0xKeno - for all his invaluable contributions\n// @burger_crypto - for the idea of trying to let the LPs benefit from liquidations\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/ERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IMasterContract.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"./MagicInternetMoney.sol\";\nimport \"./interfaces/IOracle.sol\";\nimport \"./interfaces/ISwapper.sol\";\n\n// solhint-disable avoid-low-level-calls\n// solhint-disable no-inline-assembly\n\n/// @title Cauldron\n/// @dev This contract allows contract calls to any contract (except BentoBox)\n/// from arbitrary callers thus, don't trust calls from this contract in any circumstances.\ncontract CauldronV3 is BoringOwnable, IMasterContract {\n using BoringMath for uint256;\n using BoringMath128 for uint128;\n using RebaseLibrary for Rebase;\n using BoringERC20 for IERC20;\n\n event LogExchangeRate(uint256 rate);\n event LogAccrue(uint128 accruedAmount);\n event LogAddCollateral(address indexed from, address indexed to, uint256 share);\n event LogRemoveCollateral(address indexed from, address indexed to, uint256 share);\n event LogBorrow(address indexed from, address indexed to, uint256 amount, uint256 part);\n event LogRepay(address indexed from, address indexed to, uint256 amount, uint256 part);\n event LogFeeTo(address indexed newFeeTo);\n event LogWithdrawFees(address indexed feeTo, uint256 feesEarnedFraction);\n event LogInterestChange(uint64 oldInterestRate, uint64 newInterestRate);\n event LogChangeBorrowLimit(uint128 newLimit, uint128 perAddressPart);\n event LogLiquidation(\n address indexed from,\n address indexed user,\n address indexed to,\n uint256 collateralShare,\n uint256 borrowAmount,\n uint256 borrowPart\n );\n\n // Immutables (for MasterContract and all clones)\n IBentoBoxV1 public immutable bentoBox;\n CauldronV3 public immutable masterContract;\n IERC20 public immutable magicInternetMoney;\n\n // MasterContract variables\n address public feeTo;\n\n // Per clone variables\n // Clone init settings\n IERC20 public collateral;\n IOracle public oracle;\n bytes public oracleData;\n\n struct BorrowCap {\n uint128 total;\n uint128 borrowPartPerAddress;\n }\n\n BorrowCap public borrowLimit;\n\n // Total amounts\n uint256 public totalCollateralShare; // Total collateral supplied\n Rebase public totalBorrow; // elastic = Total token amount to be repayed by borrowers, base = Total parts of the debt held by borrowers\n\n // User balances\n mapping(address => uint256) public userCollateralShare;\n mapping(address => uint256) public userBorrowPart;\n\n /// @notice Exchange and interest rate tracking.\n /// This is 'cached' here because calls to Oracles can be very expensive.\n uint256 public exchangeRate;\n\n struct AccrueInfo {\n uint64 lastAccrued;\n uint128 feesEarned;\n uint64 INTEREST_PER_SECOND;\n }\n\n AccrueInfo public accrueInfo;\n\n uint64 private constant ONE_PERCENT_RATE = 317097920;\n\n /// @notice tracking of last interest update\n uint256 private lastInterestUpdate;\n\n // Settings\n uint256 public COLLATERIZATION_RATE;\n uint256 private constant COLLATERIZATION_RATE_PRECISION = 1e5; // Must be less than EXCHANGE_RATE_PRECISION (due to optimization in math)\n\n uint256 private constant EXCHANGE_RATE_PRECISION = 1e18;\n\n uint256 public LIQUIDATION_MULTIPLIER; \n uint256 private constant LIQUIDATION_MULTIPLIER_PRECISION = 1e5;\n\n uint256 public BORROW_OPENING_FEE;\n uint256 private constant BORROW_OPENING_FEE_PRECISION = 1e5;\n\n uint256 private constant DISTRIBUTION_PART = 10;\n uint256 private constant DISTRIBUTION_PRECISION = 100;\n\n modifier onlyMasterContractOwner() {\n require(msg.sender == masterContract.owner(), \"Caller is not the owner\");\n _;\n }\n\n /// @notice The constructor is only used for the initial master contract. Subsequent clones are initialised via `init`.\n constructor(IBentoBoxV1 bentoBox_, IERC20 magicInternetMoney_) public {\n bentoBox = bentoBox_;\n magicInternetMoney = magicInternetMoney_;\n masterContract = this;\n }\n\n /// @notice Serves as the constructor for clones, as clones can't have a regular constructor\n /// @dev `data` is abi encoded in the format: (IERC20 collateral, IERC20 asset, IOracle oracle, bytes oracleData)\n function init(bytes calldata data) public payable override {\n require(address(collateral) == address(0), \"Cauldron: already initialized\");\n (collateral, oracle, oracleData, accrueInfo.INTEREST_PER_SECOND, LIQUIDATION_MULTIPLIER, COLLATERIZATION_RATE, BORROW_OPENING_FEE) = abi.decode(data, (IERC20, IOracle, bytes, uint64, uint256, uint256, uint256));\n borrowLimit = BorrowCap(type(uint128).max, type(uint128).max);\n require(address(collateral) != address(0), \"Cauldron: bad pair\");\n\n (, exchangeRate) = oracle.get(oracleData);\n }\n\n /// @notice Accrues the interest on the borrowed tokens and handles the accumulation of fees.\n function accrue() public {\n AccrueInfo memory _accrueInfo = accrueInfo;\n // Number of seconds since accrue was called\n uint256 elapsedTime = block.timestamp - _accrueInfo.lastAccrued;\n if (elapsedTime == 0) {\n return;\n }\n _accrueInfo.lastAccrued = uint64(block.timestamp);\n\n Rebase memory _totalBorrow = totalBorrow;\n if (_totalBorrow.base == 0) {\n accrueInfo = _accrueInfo;\n return;\n }\n\n // Accrue interest\n uint128 extraAmount = (uint256(_totalBorrow.elastic).mul(_accrueInfo.INTEREST_PER_SECOND).mul(elapsedTime) / 1e18).to128();\n _totalBorrow.elastic = _totalBorrow.elastic.add(extraAmount);\n\n _accrueInfo.feesEarned = _accrueInfo.feesEarned.add(extraAmount);\n totalBorrow = _totalBorrow;\n accrueInfo = _accrueInfo;\n\n emit LogAccrue(extraAmount);\n }\n\n /// @notice Concrete implementation of `isSolvent`. Includes a third parameter to allow caching `exchangeRate`.\n /// @param _exchangeRate The exchange rate. Used to cache the `exchangeRate` between calls.\n function _isSolvent(address user, uint256 _exchangeRate) internal view returns (bool) {\n // accrue must have already been called!\n uint256 borrowPart = userBorrowPart[user];\n if (borrowPart == 0) return true;\n uint256 collateralShare = userCollateralShare[user];\n if (collateralShare == 0) return false;\n\n Rebase memory _totalBorrow = totalBorrow;\n\n return\n bentoBox.toAmount(\n collateral,\n collateralShare.mul(EXCHANGE_RATE_PRECISION / COLLATERIZATION_RATE_PRECISION).mul(COLLATERIZATION_RATE),\n false\n ) >=\n // Moved exchangeRate here instead of dividing the other side to preserve more precision\n borrowPart.mul(_totalBorrow.elastic).mul(_exchangeRate) / _totalBorrow.base;\n }\n\n /// @dev Checks if the user is solvent in the closed liquidation case at the end of the function body.\n modifier solvent() {\n _;\n (, uint256 _exchangeRate) = updateExchangeRate();\n require(_isSolvent(msg.sender, _exchangeRate), \"Cauldron: user insolvent\");\n }\n\n /// @notice Gets the exchange rate. I.e how much collateral to buy 1e18 asset.\n /// This function is supposed to be invoked if needed because Oracle queries can be expensive.\n /// @return updated True if `exchangeRate` was updated.\n /// @return rate The new exchange rate.\n function updateExchangeRate() public returns (bool updated, uint256 rate) {\n (updated, rate) = oracle.get(oracleData);\n\n if (updated) {\n exchangeRate = rate;\n emit LogExchangeRate(rate);\n } else {\n // Return the old rate if fetching wasn't successful\n rate = exchangeRate;\n }\n }\n\n /// @dev Helper function to move tokens.\n /// @param token The ERC-20 token.\n /// @param share The amount in shares to add.\n /// @param total Grand total amount to deduct from this contract's balance. Only applicable if `skim` is True.\n /// Only used for accounting checks.\n /// @param skim If True, only does a balance check on this contract.\n /// False if tokens from msg.sender in `bentoBox` should be transferred.\n function _addTokens(\n IERC20 token,\n uint256 share,\n uint256 total,\n bool skim\n ) internal {\n if (skim) {\n require(share <= bentoBox.balanceOf(token, address(this)).sub(total), \"Cauldron: Skim too much\");\n } else {\n bentoBox.transfer(token, msg.sender, address(this), share);\n }\n }\n\n /// @notice Adds `collateral` from msg.sender to the account `to`.\n /// @param to The receiver of the tokens.\n /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.x\n /// False if tokens from msg.sender in `bentoBox` should be transferred.\n /// @param share The amount of shares to add for `to`.\n function addCollateral(\n address to,\n bool skim,\n uint256 share\n ) public {\n userCollateralShare[to] = userCollateralShare[to].add(share);\n uint256 oldTotalCollateralShare = totalCollateralShare;\n totalCollateralShare = oldTotalCollateralShare.add(share);\n _addTokens(collateral, share, oldTotalCollateralShare, skim);\n emit LogAddCollateral(skim ? address(bentoBox) : msg.sender, to, share);\n }\n\n /// @dev Concrete implementation of `removeCollateral`.\n function _removeCollateral(address to, uint256 share) internal {\n userCollateralShare[msg.sender] = userCollateralShare[msg.sender].sub(share);\n totalCollateralShare = totalCollateralShare.sub(share);\n emit LogRemoveCollateral(msg.sender, to, share);\n bentoBox.transfer(collateral, address(this), to, share);\n }\n\n /// @notice Removes `share` amount of collateral and transfers it to `to`.\n /// @param to The receiver of the shares.\n /// @param share Amount of shares to remove.\n function removeCollateral(address to, uint256 share) public solvent {\n // accrue must be called because we check solvency\n accrue();\n _removeCollateral(to, share);\n }\n\n /// @dev Concrete implementation of `borrow`.\n function _borrow(address to, uint256 amount) internal returns (uint256 part, uint256 share) {\n uint256 feeAmount = amount.mul(BORROW_OPENING_FEE) / BORROW_OPENING_FEE_PRECISION; // A flat % fee is charged for any borrow\n (totalBorrow, part) = totalBorrow.add(amount.add(feeAmount), true);\n\n BorrowCap memory cap = borrowLimit;\n\n require(totalBorrow.elastic <= cap.total, \"Borrow Limit reached\");\n\n accrueInfo.feesEarned = accrueInfo.feesEarned.add(uint128(feeAmount));\n \n uint256 newBorrowPart = userBorrowPart[msg.sender].add(part);\n require(newBorrowPart <= cap.borrowPartPerAddress, \"Borrow Limit reached\");\n\n userBorrowPart[msg.sender] = newBorrowPart;\n\n // As long as there are tokens on this contract you can 'mint'... this enables limiting borrows\n share = bentoBox.toShare(magicInternetMoney, amount, false);\n bentoBox.transfer(magicInternetMoney, address(this), to, share);\n\n emit LogBorrow(msg.sender, to, amount.add(feeAmount), part);\n }\n\n /// @notice Sender borrows `amount` and transfers it to `to`.\n /// @return part Total part of the debt held by borrowers.\n /// @return share Total amount in shares borrowed.\n function borrow(address to, uint256 amount) public solvent returns (uint256 part, uint256 share) {\n accrue();\n (part, share) = _borrow(to, amount);\n }\n\n /// @dev Concrete implementation of `repay`.\n function _repay(\n address to,\n bool skim,\n uint256 part\n ) internal returns (uint256 amount) {\n (totalBorrow, amount) = totalBorrow.sub(part, true);\n userBorrowPart[to] = userBorrowPart[to].sub(part);\n\n uint256 share = bentoBox.toShare(magicInternetMoney, amount, true);\n bentoBox.transfer(magicInternetMoney, skim ? address(bentoBox) : msg.sender, address(this), share);\n emit LogRepay(skim ? address(bentoBox) : msg.sender, to, amount, part);\n }\n\n /// @notice Repays a loan.\n /// @param to Address of the user this payment should go.\n /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.\n /// False if tokens from msg.sender in `bentoBox` should be transferred.\n /// @param part The amount to repay. See `userBorrowPart`.\n /// @return amount The total amount repayed.\n function repay(\n address to,\n bool skim,\n uint256 part\n ) public returns (uint256 amount) {\n accrue();\n amount = _repay(to, skim, part);\n }\n\n // Functions that need accrue to be called\n uint8 internal constant ACTION_REPAY = 2;\n uint8 internal constant ACTION_REMOVE_COLLATERAL = 4;\n uint8 internal constant ACTION_BORROW = 5;\n uint8 internal constant ACTION_GET_REPAY_SHARE = 6;\n uint8 internal constant ACTION_GET_REPAY_PART = 7;\n uint8 internal constant ACTION_ACCRUE = 8;\n\n // Functions that don't need accrue to be called\n uint8 internal constant ACTION_ADD_COLLATERAL = 10;\n uint8 internal constant ACTION_UPDATE_EXCHANGE_RATE = 11;\n\n // Function on BentoBox\n uint8 internal constant ACTION_BENTO_DEPOSIT = 20;\n uint8 internal constant ACTION_BENTO_WITHDRAW = 21;\n uint8 internal constant ACTION_BENTO_TRANSFER = 22;\n uint8 internal constant ACTION_BENTO_TRANSFER_MULTIPLE = 23;\n uint8 internal constant ACTION_BENTO_SETAPPROVAL = 24;\n\n // Any external call (except to BentoBox)\n uint8 internal constant ACTION_CALL = 30;\n\n int256 internal constant USE_VALUE1 = -1;\n int256 internal constant USE_VALUE2 = -2;\n\n /// @dev Helper function for choosing the correct value (`value1` or `value2`) depending on `inNum`.\n function _num(\n int256 inNum,\n uint256 value1,\n uint256 value2\n ) internal pure returns (uint256 outNum) {\n outNum = inNum >= 0 ? uint256(inNum) : (inNum == USE_VALUE1 ? value1 : value2);\n }\n\n /// @dev Helper function for depositing into `bentoBox`.\n function _bentoDeposit(\n bytes memory data,\n uint256 value,\n uint256 value1,\n uint256 value2\n ) internal returns (uint256, uint256) {\n (IERC20 token, address to, int256 amount, int256 share) = abi.decode(data, (IERC20, address, int256, int256));\n amount = int256(_num(amount, value1, value2)); // Done this way to avoid stack too deep errors\n share = int256(_num(share, value1, value2));\n return bentoBox.deposit{value: value}(token, msg.sender, to, uint256(amount), uint256(share));\n }\n\n /// @dev Helper function to withdraw from the `bentoBox`.\n function _bentoWithdraw(\n bytes memory data,\n uint256 value1,\n uint256 value2\n ) internal returns (uint256, uint256) {\n (IERC20 token, address to, int256 amount, int256 share) = abi.decode(data, (IERC20, address, int256, int256));\n return bentoBox.withdraw(token, msg.sender, to, _num(amount, value1, value2), _num(share, value1, value2));\n }\n\n /// @dev Helper function to perform a contract call and eventually extracting revert messages on failure.\n /// Calls to `bentoBox` are not allowed for obvious security reasons.\n /// This also means that calls made from this contract shall *not* be trusted.\n function _call(\n uint256 value,\n bytes memory data,\n uint256 value1,\n uint256 value2\n ) internal returns (bytes memory, uint8) {\n (address callee, bytes memory callData, bool useValue1, bool useValue2, uint8 returnValues) =\n abi.decode(data, (address, bytes, bool, bool, uint8));\n\n if (useValue1 && !useValue2) {\n callData = abi.encodePacked(callData, value1);\n } else if (!useValue1 && useValue2) {\n callData = abi.encodePacked(callData, value2);\n } else if (useValue1 && useValue2) {\n callData = abi.encodePacked(callData, value1, value2);\n }\n\n require(callee != address(bentoBox) && callee != address(this), \"Cauldron: can't call\");\n\n (bool success, bytes memory returnData) = callee.call{value: value}(callData);\n require(success, \"Cauldron: call failed\");\n return (returnData, returnValues);\n }\n\n struct CookStatus {\n bool needsSolvencyCheck;\n bool hasAccrued;\n }\n\n /// @notice Executes a set of actions and allows composability (contract calls) to other contracts.\n /// @param actions An array with a sequence of actions to execute (see ACTION_ declarations).\n /// @param values A one-to-one mapped array to `actions`. ETH amounts to send along with the actions.\n /// Only applicable to `ACTION_CALL`, `ACTION_BENTO_DEPOSIT`.\n /// @param datas A one-to-one mapped array to `actions`. Contains abi encoded data of function arguments.\n /// @return value1 May contain the first positioned return value of the last executed action (if applicable).\n /// @return value2 May contain the second positioned return value of the last executed action which returns 2 values (if applicable).\n function cook(\n uint8[] calldata actions,\n uint256[] calldata values,\n bytes[] calldata datas\n ) external payable returns (uint256 value1, uint256 value2) {\n CookStatus memory status;\n for (uint256 i = 0; i < actions.length; i++) {\n uint8 action = actions[i];\n if (!status.hasAccrued && action < 10) {\n accrue();\n status.hasAccrued = true;\n }\n if (action == ACTION_ADD_COLLATERAL) {\n (int256 share, address to, bool skim) = abi.decode(datas[i], (int256, address, bool));\n addCollateral(to, skim, _num(share, value1, value2));\n } else if (action == ACTION_REPAY) {\n (int256 part, address to, bool skim) = abi.decode(datas[i], (int256, address, bool));\n _repay(to, skim, _num(part, value1, value2));\n } else if (action == ACTION_REMOVE_COLLATERAL) {\n (int256 share, address to) = abi.decode(datas[i], (int256, address));\n _removeCollateral(to, _num(share, value1, value2));\n status.needsSolvencyCheck = true;\n } else if (action == ACTION_BORROW) {\n (int256 amount, address to) = abi.decode(datas[i], (int256, address));\n (value1, value2) = _borrow(to, _num(amount, value1, value2));\n status.needsSolvencyCheck = true;\n } else if (action == ACTION_UPDATE_EXCHANGE_RATE) {\n (bool must_update, uint256 minRate, uint256 maxRate) = abi.decode(datas[i], (bool, uint256, uint256));\n (bool updated, uint256 rate) = updateExchangeRate();\n require((!must_update || updated) && rate > minRate && (maxRate == 0 || rate > maxRate), \"Cauldron: rate not ok\");\n } else if (action == ACTION_BENTO_SETAPPROVAL) {\n (address user, address _masterContract, bool approved, uint8 v, bytes32 r, bytes32 s) =\n abi.decode(datas[i], (address, address, bool, uint8, bytes32, bytes32));\n bentoBox.setMasterContractApproval(user, _masterContract, approved, v, r, s);\n } else if (action == ACTION_BENTO_DEPOSIT) {\n (value1, value2) = _bentoDeposit(datas[i], values[i], value1, value2);\n } else if (action == ACTION_BENTO_WITHDRAW) {\n (value1, value2) = _bentoWithdraw(datas[i], value1, value2);\n } else if (action == ACTION_BENTO_TRANSFER) {\n (IERC20 token, address to, int256 share) = abi.decode(datas[i], (IERC20, address, int256));\n bentoBox.transfer(token, msg.sender, to, _num(share, value1, value2));\n } else if (action == ACTION_BENTO_TRANSFER_MULTIPLE) {\n (IERC20 token, address[] memory tos, uint256[] memory shares) = abi.decode(datas[i], (IERC20, address[], uint256[]));\n bentoBox.transferMultiple(token, msg.sender, tos, shares);\n } else if (action == ACTION_CALL) {\n (bytes memory returnData, uint8 returnValues) = _call(values[i], datas[i], value1, value2);\n\n if (returnValues == 1) {\n (value1) = abi.decode(returnData, (uint256));\n } else if (returnValues == 2) {\n (value1, value2) = abi.decode(returnData, (uint256, uint256));\n }\n } else if (action == ACTION_GET_REPAY_SHARE) {\n int256 part = abi.decode(datas[i], (int256));\n value1 = bentoBox.toShare(magicInternetMoney, totalBorrow.toElastic(_num(part, value1, value2), true), true);\n } else if (action == ACTION_GET_REPAY_PART) {\n int256 amount = abi.decode(datas[i], (int256));\n value1 = totalBorrow.toBase(_num(amount, value1, value2), false);\n }\n }\n\n if (status.needsSolvencyCheck) {\n (, uint256 _exchangeRate) = updateExchangeRate();\n require(_isSolvent(msg.sender, _exchangeRate), \"Cauldron: user insolvent\");\n }\n }\n\n /// @notice Handles the liquidation of users' balances, once the users' amount of collateral is too low.\n /// @param users An array of user addresses.\n /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.\n /// @param to Address of the receiver in open liquidations if `swapper` is zero.\n function liquidate(\n address[] calldata users,\n uint256[] calldata maxBorrowParts,\n address to,\n ISwapper swapper\n ) public {\n // Oracle can fail but we still need to allow liquidations\n (, uint256 _exchangeRate) = updateExchangeRate();\n accrue();\n\n uint256 allCollateralShare;\n uint256 allBorrowAmount;\n uint256 allBorrowPart;\n Rebase memory _totalBorrow = totalBorrow;\n Rebase memory bentoBoxTotals = bentoBox.totals(collateral);\n for (uint256 i = 0; i < users.length; i++) {\n address user = users[i];\n if (!_isSolvent(user, _exchangeRate)) {\n uint256 borrowPart;\n {\n uint256 availableBorrowPart = userBorrowPart[user];\n borrowPart = maxBorrowParts[i] > availableBorrowPart ? availableBorrowPart : maxBorrowParts[i];\n userBorrowPart[user] = availableBorrowPart.sub(borrowPart);\n }\n uint256 borrowAmount = _totalBorrow.toElastic(borrowPart, false);\n uint256 collateralShare =\n bentoBoxTotals.toBase(\n borrowAmount.mul(LIQUIDATION_MULTIPLIER).mul(_exchangeRate) /\n (LIQUIDATION_MULTIPLIER_PRECISION * EXCHANGE_RATE_PRECISION),\n false\n );\n\n userCollateralShare[user] = userCollateralShare[user].sub(collateralShare);\n emit LogRemoveCollateral(user, to, collateralShare);\n emit LogRepay(msg.sender, user, borrowAmount, borrowPart);\n emit LogLiquidation(msg.sender, user, to, collateralShare, borrowAmount, borrowPart);\n\n // Keep totals\n allCollateralShare = allCollateralShare.add(collateralShare);\n allBorrowAmount = allBorrowAmount.add(borrowAmount);\n allBorrowPart = allBorrowPart.add(borrowPart);\n }\n }\n require(allBorrowAmount != 0, \"Cauldron: all are solvent\");\n _totalBorrow.elastic = _totalBorrow.elastic.sub(allBorrowAmount.to128());\n _totalBorrow.base = _totalBorrow.base.sub(allBorrowPart.to128());\n totalBorrow = _totalBorrow;\n totalCollateralShare = totalCollateralShare.sub(allCollateralShare);\n\n // Apply a percentual fee share to sSpell holders\n \n {\n uint256 distributionAmount = (allBorrowAmount.mul(LIQUIDATION_MULTIPLIER) / LIQUIDATION_MULTIPLIER_PRECISION).sub(allBorrowAmount).mul(DISTRIBUTION_PART) / DISTRIBUTION_PRECISION; // Distribution Amount\n allBorrowAmount = allBorrowAmount.add(distributionAmount);\n accrueInfo.feesEarned = accrueInfo.feesEarned.add(distributionAmount.to128());\n }\n\n uint256 allBorrowShare = bentoBox.toShare(magicInternetMoney, allBorrowAmount, true);\n\n // Swap using a swapper freely chosen by the caller\n // Open (flash) liquidation: get proceeds first and provide the borrow after\n bentoBox.transfer(collateral, address(this), to, allCollateralShare);\n if (swapper != ISwapper(0)) {\n swapper.swap(collateral, magicInternetMoney, msg.sender, allBorrowShare, allCollateralShare);\n }\n\n allBorrowShare = bentoBox.toShare(magicInternetMoney, allBorrowAmount, true);\n bentoBox.transfer(magicInternetMoney, msg.sender, address(this), allBorrowShare);\n }\n\n /// @notice Withdraws the fees accumulated.\n function withdrawFees() public {\n accrue();\n address _feeTo = masterContract.feeTo();\n uint256 _feesEarned = accrueInfo.feesEarned;\n uint256 share = bentoBox.toShare(magicInternetMoney, _feesEarned, false);\n bentoBox.transfer(magicInternetMoney, address(this), _feeTo, share);\n accrueInfo.feesEarned = 0;\n\n emit LogWithdrawFees(_feeTo, _feesEarned);\n }\n\n /// @notice Sets the beneficiary of interest accrued.\n /// MasterContract Only Admin function.\n /// @param newFeeTo The address of the receiver.\n function setFeeTo(address newFeeTo) public onlyOwner {\n feeTo = newFeeTo;\n emit LogFeeTo(newFeeTo);\n }\n\n /// @notice reduces the supply of MIM\n /// @param amount amount to reduce supply by\n function reduceSupply(uint256 amount) public onlyMasterContractOwner {\n bentoBox.withdraw(magicInternetMoney, address(this), masterContract.owner(), amount, 0);\n }\n\n /// @notice allows to change the interest rate\n /// @param newInterestRate new interest rate\n function changeInterestRate(uint64 newInterestRate) public onlyMasterContractOwner {\n uint64 oldInterestRate = accrueInfo.INTEREST_PER_SECOND;\n\n require(newInterestRate < oldInterestRate + oldInterestRate * 3 / 4 || newInterestRate <= ONE_PERCENT_RATE, \"Interest rate increase > 75%\");\n require(lastInterestUpdate + 3 days < block.timestamp, \"Update only every 3 days\");\n\n lastInterestUpdate = block.timestamp;\n accrueInfo.INTEREST_PER_SECOND = newInterestRate;\n emit LogInterestChange(oldInterestRate, newInterestRate);\n }\n\n /// @notice allows to change the borrow limit\n /// @param newBorrowLimit new borrow limit\n /// @param perAddressPart new borrow limit per address\n function changeBorrowLimit(uint128 newBorrowLimit, uint128 perAddressPart) public onlyMasterContractOwner {\n borrowLimit = BorrowCap(newBorrowLimit, perAddressPart);\n emit LogChangeBorrowLimit(newBorrowLimit, perAddressPart);\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\n/// @notice A library for performing overflow-/underflow-safe math,\n/// updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math).\nlibrary BoringMath {\n function add(uint256 a, uint256 b) internal pure returns (uint256 c) {\n require((c = a + b) >= b, \"BoringMath: Add Overflow\");\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {\n require((c = a - b) <= a, \"BoringMath: Underflow\");\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {\n require(b == 0 || (c = a * b) / b == a, \"BoringMath: Mul Overflow\");\n }\n\n function to128(uint256 a) internal pure returns (uint128 c) {\n require(a <= uint128(-1), \"BoringMath: uint128 Overflow\");\n c = uint128(a);\n }\n\n function to64(uint256 a) internal pure returns (uint64 c) {\n require(a <= uint64(-1), \"BoringMath: uint64 Overflow\");\n c = uint64(a);\n }\n\n function to32(uint256 a) internal pure returns (uint32 c) {\n require(a <= uint32(-1), \"BoringMath: uint32 Overflow\");\n c = uint32(a);\n }\n}\n\n/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint128.\nlibrary BoringMath128 {\n function add(uint128 a, uint128 b) internal pure returns (uint128 c) {\n require((c = a + b) >= b, \"BoringMath: Add Overflow\");\n }\n\n function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {\n require((c = a - b) <= a, \"BoringMath: Underflow\");\n }\n}\n\n/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint64.\nlibrary BoringMath64 {\n function add(uint64 a, uint64 b) internal pure returns (uint64 c) {\n require((c = a + b) >= b, \"BoringMath: Add Overflow\");\n }\n\n function sub(uint64 a, uint64 b) internal pure returns (uint64 c) {\n require((c = a - b) <= a, \"BoringMath: Underflow\");\n }\n}\n\n/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint32.\nlibrary BoringMath32 {\n function add(uint32 a, uint32 b) internal pure returns (uint32 c) {\n require((c = a + b) >= b, \"BoringMath: Add Overflow\");\n }\n\n function sub(uint32 a, uint32 b) internal pure returns (uint32 c) {\n require((c = a - b) <= a, \"BoringMath: Underflow\");\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\n// Edited by BoringCrypto\n\ncontract BoringOwnableData {\n address public owner;\n address public pendingOwner;\n}\n\ncontract BoringOwnable is BoringOwnableData {\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /// @notice `owner` defaults to msg.sender on construction.\n constructor() public {\n owner = msg.sender;\n emit OwnershipTransferred(address(0), msg.sender);\n }\n\n /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.\n /// Can only be invoked by the current `owner`.\n /// @param newOwner Address of the new owner.\n /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\n /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\n function transferOwnership(\n address newOwner,\n bool direct,\n bool renounce\n ) public onlyOwner {\n if (direct) {\n // Checks\n require(newOwner != address(0) || renounce, \"Ownable: zero address\");\n\n // Effects\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n pendingOwner = address(0);\n } else {\n // Effects\n pendingOwner = newOwner;\n }\n }\n\n /// @notice Needs to be called by `pendingOwner` to claim ownership.\n function claimOwnership() public {\n address _pendingOwner = pendingOwner;\n\n // Checks\n require(msg.sender == _pendingOwner, \"Ownable: caller != pending owner\");\n\n // Effects\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = address(0);\n }\n\n /// @notice Only allows the `owner` to execute the function.\n modifier onlyOwner() {\n require(msg.sender == owner, \"Ownable: caller is not the owner\");\n _;\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"./interfaces/IERC20.sol\";\nimport \"./Domain.sol\";\n\n// solhint-disable no-inline-assembly\n// solhint-disable not-rely-on-time\n\n// Data part taken out for building of contracts that receive delegate calls\ncontract ERC20Data {\n /// @notice owner > balance mapping.\n mapping(address => uint256) public balanceOf;\n /// @notice owner > spender > allowance mapping.\n mapping(address => mapping(address => uint256)) public allowance;\n /// @notice owner > nonce mapping. Used in `permit`.\n mapping(address => uint256) public nonces;\n}\n\nabstract contract ERC20 is IERC20, Domain {\n /// @notice owner > balance mapping.\n mapping(address => uint256) public override balanceOf;\n /// @notice owner > spender > allowance mapping.\n mapping(address => mapping(address => uint256)) public override allowance;\n /// @notice owner > nonce mapping. Used in `permit`.\n mapping(address => uint256) public nonces;\n\n event Transfer(address indexed _from, address indexed _to, uint256 _value);\n event Approval(address indexed _owner, address indexed _spender, uint256 _value);\n\n /// @notice Transfers `amount` tokens from `msg.sender` to `to`.\n /// @param to The address to move the tokens.\n /// @param amount of the tokens to move.\n /// @return (bool) Returns True if succeeded.\n function transfer(address to, uint256 amount) public returns (bool) {\n // If `amount` is 0, or `msg.sender` is `to` nothing happens\n if (amount != 0 || msg.sender == to) {\n uint256 srcBalance = balanceOf[msg.sender];\n require(srcBalance >= amount, \"ERC20: balance too low\");\n if (msg.sender != to) {\n require(to != address(0), \"ERC20: no zero address\"); // Moved down so low balance calls safe some gas\n\n balanceOf[msg.sender] = srcBalance - amount; // Underflow is checked\n balanceOf[to] += amount;\n }\n }\n emit Transfer(msg.sender, to, amount);\n return true;\n }\n\n /// @notice Transfers `amount` tokens from `from` to `to`. Caller needs approval for `from`.\n /// @param from Address to draw tokens from.\n /// @param to The address to move the tokens.\n /// @param amount The token amount to move.\n /// @return (bool) Returns True if succeeded.\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public returns (bool) {\n // If `amount` is 0, or `from` is `to` nothing happens\n if (amount != 0) {\n uint256 srcBalance = balanceOf[from];\n require(srcBalance >= amount, \"ERC20: balance too low\");\n\n if (from != to) {\n uint256 spenderAllowance = allowance[from][msg.sender];\n // If allowance is infinite, don't decrease it to save on gas (breaks with EIP-20).\n if (spenderAllowance != type(uint256).max) {\n require(spenderAllowance >= amount, \"ERC20: allowance too low\");\n allowance[from][msg.sender] = spenderAllowance - amount; // Underflow is checked\n }\n require(to != address(0), \"ERC20: no zero address\"); // Moved down so other failed calls safe some gas\n\n balanceOf[from] = srcBalance - amount; // Underflow is checked\n balanceOf[to] += amount;\n }\n }\n emit Transfer(from, to, amount);\n return true;\n }\n\n /// @notice Approves `amount` from sender to be spend by `spender`.\n /// @param spender Address of the party that can draw from msg.sender's account.\n /// @param amount The maximum collective amount that `spender` can draw.\n /// @return (bool) Returns True if approved.\n function approve(address spender, uint256 amount) public override returns (bool) {\n allowance[msg.sender][spender] = amount;\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32) {\n return _domainSeparator();\n }\n\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 private constant PERMIT_SIGNATURE_HASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n\n /// @notice Approves `value` from `owner_` to be spend by `spender`.\n /// @param owner_ Address of the owner.\n /// @param spender The address of the spender that gets approved to draw from `owner_`.\n /// @param value The maximum collective amount that `spender` can draw.\n /// @param deadline This permit must be redeemed before this deadline (UTC timestamp in seconds).\n function permit(\n address owner_,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external override {\n require(owner_ != address(0), \"ERC20: Owner cannot be 0\");\n require(block.timestamp < deadline, \"ERC20: Expired\");\n require(\n ecrecover(_getDigest(keccak256(abi.encode(PERMIT_SIGNATURE_HASH, owner_, spender, value, nonces[owner_]++, deadline))), v, r, s) ==\n owner_,\n \"ERC20: Invalid Signature\"\n );\n allowance[owner_][spender] = value;\n emit Approval(owner_, spender, value);\n }\n}\n\ncontract ERC20WithSupply is IERC20, ERC20 {\n uint256 public override totalSupply;\n\n function _mint(address user, uint256 amount) private {\n uint256 newTotalSupply = totalSupply + amount;\n require(newTotalSupply >= totalSupply, \"Mint overflow\");\n totalSupply = newTotalSupply;\n balanceOf[user] += amount;\n }\n\n function _burn(address user, uint256 amount) private {\n require(balanceOf[user] >= amount, \"Burn too much\");\n totalSupply -= amount;\n balanceOf[user] -= amount;\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/interfaces/IMasterContract.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\ninterface IMasterContract {\n /// @notice Init function that gets called from `BoringFactory.deploy`.\n /// Also kown as the constructor for cloned contracts.\n /// Any ETH send to `BoringFactory.deploy` ends up here.\n /// @param data Can be abi encoded arguments or anything else.\n function init(bytes calldata data) external payable;\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"./BoringMath.sol\";\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\n/// @notice A rebasing library using overflow-/underflow-safe math.\nlibrary RebaseLibrary {\n using BoringMath for uint256;\n using BoringMath128 for uint128;\n\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(\n Rebase memory total,\n uint256 elastic,\n bool roundUp\n ) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = elastic.mul(total.base) / total.elastic;\n if (roundUp && base.mul(total.elastic) / total.base < elastic) {\n base = base.add(1);\n }\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(\n Rebase memory total,\n uint256 base,\n bool roundUp\n ) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = base.mul(total.elastic) / total.base;\n if (roundUp && elastic.mul(total.base) / total.elastic < base) {\n elastic = elastic.add(1);\n }\n }\n }\n\n /// @notice Add `elastic` to `total` and doubles `total.base`.\n /// @return (Rebase) The new total.\n /// @return base in relationship to `elastic`.\n function add(\n Rebase memory total,\n uint256 elastic,\n bool roundUp\n ) internal pure returns (Rebase memory, uint256 base) {\n base = toBase(total, elastic, roundUp);\n total.elastic = total.elastic.add(elastic.to128());\n total.base = total.base.add(base.to128());\n return (total, base);\n }\n\n /// @notice Sub `base` from `total` and update `total.elastic`.\n /// @return (Rebase) The new total.\n /// @return elastic in relationship to `base`.\n function sub(\n Rebase memory total,\n uint256 base,\n bool roundUp\n ) internal pure returns (Rebase memory, uint256 elastic) {\n elastic = toElastic(total, base, roundUp);\n total.elastic = total.elastic.sub(elastic.to128());\n total.base = total.base.sub(base.to128());\n return (total, elastic);\n }\n\n /// @notice Add `elastic` and `base` to `total`.\n function add(\n Rebase memory total,\n uint256 elastic,\n uint256 base\n ) internal pure returns (Rebase memory) {\n total.elastic = total.elastic.add(elastic.to128());\n total.base = total.base.add(base.to128());\n return total;\n }\n\n /// @notice Subtract `elastic` and `base` to `total`.\n function sub(\n Rebase memory total,\n uint256 elastic,\n uint256 base\n ) internal pure returns (Rebase memory) {\n total.elastic = total.elastic.sub(elastic.to128());\n total.base = total.base.sub(base.to128());\n return total;\n }\n\n /// @notice Add `elastic` to `total` and update storage.\n /// @return newElastic Returns updated `elastic`.\n function addElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {\n newElastic = total.elastic = total.elastic.add(elastic.to128());\n }\n\n /// @notice Subtract `elastic` from `total` and update storage.\n /// @return newElastic Returns updated `elastic`.\n function subElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {\n newElastic = total.elastic = total.elastic.sub(elastic.to128());\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"../interfaces/IERC20.sol\";\n\n// solhint-disable avoid-low-level-calls\n\nlibrary BoringERC20 {\n bytes4 private constant SIG_SYMBOL = 0x95d89b41; // symbol()\n bytes4 private constant SIG_NAME = 0x06fdde03; // name()\n bytes4 private constant SIG_DECIMALS = 0x313ce567; // decimals()\n bytes4 private constant SIG_TRANSFER = 0xa9059cbb; // transfer(address,uint256)\n bytes4 private constant SIG_TRANSFER_FROM = 0x23b872dd; // transferFrom(address,address,uint256)\n\n function returnDataToString(bytes memory data) internal pure returns (string memory) {\n if (data.length >= 64) {\n return abi.decode(data, (string));\n } else if (data.length == 32) {\n uint8 i = 0;\n while(i < 32 && data[i] != 0) {\n i++;\n }\n bytes memory bytesArray = new bytes(i);\n for (i = 0; i < 32 && data[i] != 0; i++) {\n bytesArray[i] = data[i];\n }\n return string(bytesArray);\n } else {\n return \"???\";\n }\n }\n\n /// @notice Provides a safe ERC20.symbol version which returns '???' as fallback string.\n /// @param token The address of the ERC-20 token contract.\n /// @return (string) Token symbol.\n function safeSymbol(IERC20 token) internal view returns (string memory) {\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_SYMBOL));\n return success ? returnDataToString(data) : \"???\";\n }\n\n /// @notice Provides a safe ERC20.name version which returns '???' as fallback string.\n /// @param token The address of the ERC-20 token contract.\n /// @return (string) Token name.\n function safeName(IERC20 token) internal view returns (string memory) {\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_NAME));\n return success ? returnDataToString(data) : \"???\";\n }\n\n /// @notice Provides a safe ERC20.decimals version which returns '18' as fallback value.\n /// @param token The address of the ERC-20 token contract.\n /// @return (uint8) Token decimals.\n function safeDecimals(IERC20 token) internal view returns (uint8) {\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_DECIMALS));\n return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;\n }\n\n /// @notice Provides a safe ERC20.transfer version for different ERC-20 implementations.\n /// Reverts on a failed transfer.\n /// @param token The address of the ERC-20 token.\n /// @param to Transfer tokens to.\n /// @param amount The token amount.\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 amount\n ) internal {\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(SIG_TRANSFER, to, amount));\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: Transfer failed\");\n }\n\n /// @notice Provides a safe ERC20.transferFrom version for different ERC-20 implementations.\n /// Reverts on a failed transfer.\n /// @param token The address of the ERC-20 token.\n /// @param from Transfer tokens from.\n /// @param to Transfer tokens to.\n /// @param amount The token amount.\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(SIG_TRANSFER_FROM, from, to, amount));\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: TransferFrom failed\");\n }\n}\n" + }, + "@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol';\nimport '@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol';\nimport './IBatchFlashBorrower.sol';\nimport './IFlashBorrower.sol';\nimport './IStrategy.sol';\n\ninterface IBentoBoxV1 {\n event LogDeploy(address indexed masterContract, bytes data, address indexed cloneAddress);\n event LogDeposit(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);\n event LogFlashLoan(address indexed borrower, address indexed token, uint256 amount, uint256 feeAmount, address indexed receiver);\n event LogRegisterProtocol(address indexed protocol);\n event LogSetMasterContractApproval(address indexed masterContract, address indexed user, bool approved);\n event LogStrategyDivest(address indexed token, uint256 amount);\n event LogStrategyInvest(address indexed token, uint256 amount);\n event LogStrategyLoss(address indexed token, uint256 amount);\n event LogStrategyProfit(address indexed token, uint256 amount);\n event LogStrategyQueued(address indexed token, address indexed strategy);\n event LogStrategySet(address indexed token, address indexed strategy);\n event LogStrategyTargetPercentage(address indexed token, uint256 targetPercentage);\n event LogTransfer(address indexed token, address indexed from, address indexed to, uint256 share);\n event LogWhiteListMasterContract(address indexed masterContract, bool approved);\n event LogWithdraw(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n function balanceOf(IERC20, address) external view returns (uint256);\n function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results);\n function batchFlashLoan(IBatchFlashBorrower borrower, address[] calldata receivers, IERC20[] calldata tokens, uint256[] calldata amounts, bytes calldata data) external;\n function claimOwnership() external;\n function deploy(address masterContract, bytes calldata data, bool useCreate2) external payable;\n function deposit(IERC20 token_, address from, address to, uint256 amount, uint256 share) external payable returns (uint256 amountOut, uint256 shareOut);\n function flashLoan(IFlashBorrower borrower, address receiver, IERC20 token, uint256 amount, bytes calldata data) external;\n function harvest(IERC20 token, bool balance, uint256 maxChangeAmount) external;\n function masterContractApproved(address, address) external view returns (bool);\n function masterContractOf(address) external view returns (address);\n function nonces(address) external view returns (uint256);\n function owner() external view returns (address);\n function pendingOwner() external view returns (address);\n function pendingStrategy(IERC20) external view returns (IStrategy);\n function permitToken(IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n function registerProtocol() external;\n function setMasterContractApproval(address user, address masterContract, bool approved, uint8 v, bytes32 r, bytes32 s) external;\n function setStrategy(IERC20 token, IStrategy newStrategy) external;\n function setStrategyTargetPercentage(IERC20 token, uint64 targetPercentage_) external;\n function strategy(IERC20) external view returns (IStrategy);\n function strategyData(IERC20) external view returns (uint64 strategyStartDate, uint64 targetPercentage, uint128 balance);\n function toAmount(IERC20 token, uint256 share, bool roundUp) external view returns (uint256 amount);\n function toShare(IERC20 token, uint256 amount, bool roundUp) external view returns (uint256 share);\n function totals(IERC20) external view returns (Rebase memory totals_);\n function transfer(IERC20 token, address from, address to, uint256 share) external;\n function transferMultiple(IERC20 token, address from, address[] calldata tos, uint256[] calldata shares) external;\n function transferOwnership(address newOwner, bool direct, bool renounce) external;\n function whitelistMasterContract(address masterContract, bool approved) external;\n function whitelistedMasterContracts(address) external view returns (bool);\n function withdraw(IERC20 token_, address from, address to, uint256 amount, uint256 share) external returns (uint256 amountOut, uint256 shareOut);\n}" + }, + "contracts/MagicInternetMoney.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n\r\n// Magic Internet Money\r\n\r\n// ███╗ ███╗██╗███╗ ███╗\r\n// ████╗ ████║██║████╗ ████║\r\n// ██╔████╔██║██║██╔████╔██║\r\n// ██║╚██╔╝██║██║██║╚██╔╝██║\r\n// ██║ ╚═╝ ██║██║██║ ╚═╝ ██║\r\n// ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝\r\n\r\n// BoringCrypto, 0xMerlin\r\n\r\npragma solidity 0.6.12;\r\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\r\nimport \"@boringcrypto/boring-solidity/contracts/ERC20.sol\";\r\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\r\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\r\n\r\n/// @title Cauldron\r\n/// @dev This contract allows contract calls to any contract (except BentoBox)\r\n/// from arbitrary callers thus, don't trust calls from this contract in any circumstances.\r\ncontract MagicInternetMoney is ERC20, BoringOwnable {\r\n using BoringMath for uint256;\r\n // ERC20 'variables'\r\n string public constant symbol = \"MIM\";\r\n string public constant name = \"Magic Internet Money\";\r\n uint8 public constant decimals = 18;\r\n uint256 public override totalSupply;\r\n\r\n struct Minting {\r\n uint128 time;\r\n uint128 amount;\r\n }\r\n\r\n Minting public lastMint;\r\n uint256 private constant MINTING_PERIOD = 24 hours;\r\n uint256 private constant MINTING_INCREASE = 15000;\r\n uint256 private constant MINTING_PRECISION = 1e5;\r\n\r\n function mint(address to, uint256 amount) public onlyOwner {\r\n require(to != address(0), \"MIM: no mint to zero address\");\r\n\r\n // Limits the amount minted per period to a convergence function, with the period duration restarting on every mint\r\n uint256 totalMintedAmount = uint256(lastMint.time < block.timestamp - MINTING_PERIOD ? 0 : lastMint.amount).add(amount);\r\n require(totalSupply == 0 || totalSupply.mul(MINTING_INCREASE) / MINTING_PRECISION >= totalMintedAmount);\r\n\r\n lastMint.time = block.timestamp.to128();\r\n lastMint.amount = totalMintedAmount.to128();\r\n\r\n totalSupply = totalSupply + amount;\r\n balanceOf[to] += amount;\r\n emit Transfer(address(0), to, amount);\r\n }\r\n\r\n function mintToBentoBox(address clone, uint256 amount, IBentoBoxV1 bentoBox) public onlyOwner {\r\n mint(address(bentoBox), amount);\r\n bentoBox.deposit(IERC20(address(this)), address(bentoBox), clone, amount, 0);\r\n }\r\n\r\n function burn(uint256 amount) public {\r\n require(amount <= balanceOf[msg.sender], \"MIM: not enough\");\r\n\r\n balanceOf[msg.sender] -= amount;\r\n totalSupply -= amount;\r\n emit Transfer(msg.sender, address(0), amount);\r\n }\r\n}\r\n" + }, + "contracts/interfaces/IOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface IOracle {\n /// @notice Get the latest exchange rate.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return success if no valid (recent) rate is available, return false else true.\n /// @return rate The rate of the requested asset / pair / pool.\n function get(bytes calldata data) external returns (bool success, uint256 rate);\n\n /// @notice Check the last exchange rate without any state changes.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return success if no valid (recent) rate is available, return false else true.\n /// @return rate The rate of the requested asset / pair / pool.\n function peek(bytes calldata data) external view returns (bool success, uint256 rate);\n\n /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return rate The rate of the requested asset / pair / pool.\n function peekSpot(bytes calldata data) external view returns (uint256 rate);\n\n /// @notice Returns a human readable (short) name about this oracle.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return (string) A human readable symbol name about this oracle.\n function symbol(bytes calldata data) external view returns (string memory);\n\n /// @notice Returns a human readable name about this oracle.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return (string) A human readable name about this oracle.\n function name(bytes calldata data) external view returns (string memory);\n}\n" + }, + "contracts/interfaces/ISwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\";\n\ninterface ISwapper {\n /// @notice Withdraws 'amountFrom' of token 'from' from the BentoBox account for this swapper.\n /// Swaps it for at least 'amountToMin' of token 'to'.\n /// Transfers the swapped tokens of 'to' into the BentoBox using a plain ERC20 transfer.\n /// Returns the amount of tokens 'to' transferred to BentoBox.\n /// (The BentoBox skim function will be used by the caller to get the swapped funds).\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) external returns (uint256 extraShare, uint256 shareReturned);\n\n /// @notice Calculates the amount of token 'from' needed to complete the swap (amountFrom),\n /// this should be less than or equal to amountFromMax.\n /// Withdraws 'amountFrom' of token 'from' from the BentoBox account for this swapper.\n /// Swaps it for exactly 'exactAmountTo' of token 'to'.\n /// Transfers the swapped tokens of 'to' into the BentoBox using a plain ERC20 transfer.\n /// Transfers allocated, but unused 'from' tokens within the BentoBox to 'refundTo' (amountFromMax - amountFrom).\n /// Returns the amount of 'from' tokens withdrawn from BentoBox (amountFrom).\n /// (The BentoBox skim function will be used by the caller to get the swapped funds).\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) external returns (uint256 shareUsed, uint256 shareReturned);\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address account) external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function approve(address spender, uint256 amount) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /// @notice EIP 2612\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/Domain.sol": { + "content": "// SPDX-License-Identifier: MIT\n// Based on code and smartness by Ross Campbell and Keno\n// Uses immutable to store the domain separator to reduce gas usage\n// If the chain id changes due to a fork, the forked chain will calculate on the fly.\npragma solidity 0.6.12;\n\n// solhint-disable no-inline-assembly\n\ncontract Domain {\n bytes32 private constant DOMAIN_SEPARATOR_SIGNATURE_HASH = keccak256(\"EIP712Domain(uint256 chainId,address verifyingContract)\");\n // See https://eips.ethereum.org/EIPS/eip-191\n string private constant EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA = \"\\x19\\x01\";\n\n // solhint-disable var-name-mixedcase\n bytes32 private immutable _DOMAIN_SEPARATOR;\n uint256 private immutable DOMAIN_SEPARATOR_CHAIN_ID; \n\n /// @dev Calculate the DOMAIN_SEPARATOR\n function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n DOMAIN_SEPARATOR_SIGNATURE_HASH,\n chainId,\n address(this)\n )\n );\n }\n\n constructor() public {\n uint256 chainId; assembly {chainId := chainid()}\n _DOMAIN_SEPARATOR = _calculateDomainSeparator(DOMAIN_SEPARATOR_CHAIN_ID = chainId);\n }\n\n /// @dev Return the DOMAIN_SEPARATOR\n // It's named internal to allow making it public from the contract that uses it by creating a simple view function\n // with the desired public name, such as DOMAIN_SEPARATOR or domainSeparator.\n // solhint-disable-next-line func-name-mixedcase\n function _domainSeparator() internal view returns (bytes32) {\n uint256 chainId; assembly {chainId := chainid()}\n return chainId == DOMAIN_SEPARATOR_CHAIN_ID ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(chainId);\n }\n\n function _getDigest(bytes32 dataHash) internal view returns (bytes32 digest) {\n digest =\n keccak256(\n abi.encodePacked(\n EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA,\n _domainSeparator(),\n dataHash\n )\n );\n }\n}" + }, + "@sushiswap/bentobox-sdk/contracts/IBatchFlashBorrower.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport '@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol';\n\ninterface IBatchFlashBorrower {\n function onBatchFlashLoan(\n address sender,\n IERC20[] calldata tokens,\n uint256[] calldata amounts,\n uint256[] calldata fees,\n bytes calldata data\n ) external;\n}" + }, + "@sushiswap/bentobox-sdk/contracts/IFlashBorrower.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport '@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol';\n\ninterface IFlashBorrower {\n function onFlashLoan(\n address sender,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes calldata data\n ) external;\n}" + }, + "@sushiswap/bentobox-sdk/contracts/IStrategy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\ninterface IStrategy {\n // Send the assets to the Strategy and call skim to invest them\n function skim(uint256 amount) external;\n\n // Harvest any profits made converted to the asset and pass them to the caller\n function harvest(uint256 balance, address sender) external returns (int256 amountAdded);\n\n // Withdraw assets. The returned amount can differ from the requested amount due to rounding.\n // The actualAmount should be very close to the amount. The difference should NOT be used to report a loss. That's what harvest is for.\n function withdraw(uint256 amount) external returns (uint256 actualAmount);\n\n // Withdraw all assets in the safest way possible. This shouldn't fail.\n function exit(uint256 balance) external returns (int256 amountAdded);\n}" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 999999 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file diff --git a/deployments/mainnet/solcInputs/a8287f9582549e1e61e2a34e7021b1e9.json b/deployments/mainnet/solcInputs/a8287f9582549e1e61e2a34e7021b1e9.json new file mode 100644 index 00000000..e38ea534 --- /dev/null +++ b/deployments/mainnet/solcInputs/a8287f9582549e1e61e2a34e7021b1e9.json @@ -0,0 +1,344 @@ +{ + "language": "Solidity", + "sources": { + "contracts/interfaces/ISwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\";\n\ninterface ISwapper {\n /// @notice Withdraws 'amountFrom' of token 'from' from the BentoBox account for this swapper.\n /// Swaps it for at least 'amountToMin' of token 'to'.\n /// Transfers the swapped tokens of 'to' into the BentoBox using a plain ERC20 transfer.\n /// Returns the amount of tokens 'to' transferred to BentoBox.\n /// (The BentoBox skim function will be used by the caller to get the swapped funds).\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) external returns (uint256 extraShare, uint256 shareReturned);\n\n /// @notice Calculates the amount of token 'from' needed to complete the swap (amountFrom),\n /// this should be less than or equal to amountFromMax.\n /// Withdraws 'amountFrom' of token 'from' from the BentoBox account for this swapper.\n /// Swaps it for exactly 'exactAmountTo' of token 'to'.\n /// Transfers the swapped tokens of 'to' into the BentoBox using a plain ERC20 transfer.\n /// Transfers allocated, but unused 'from' tokens within the BentoBox to 'refundTo' (amountFromMax - amountFrom).\n /// Returns the amount of 'from' tokens withdrawn from BentoBox (amountFrom).\n /// (The BentoBox skim function will be used by the caller to get the swapped funds).\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) external returns (uint256 shareUsed, uint256 shareReturned);\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address account) external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function approve(address spender, uint256 amount) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /// @notice EIP 2612\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "contracts/swappers/Leverage/StkFrax3CrvLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address receiver\n ) external returns (uint256);\n\n function approve(address _spender, uint256 _value) external returns (bool);\n\n function add_liquidity(\n address pool,\n uint256[4] memory amounts,\n uint256 _min_mint_amount\n ) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ninterface IConvex is IERC20 {\n function withdrawAndUnwrap(uint256 _amount) external;\n\n //deposit a curve token\n function deposit(uint256 _amount, address _to) external;\n}\n\ncontract StkFrax3CrvLevSwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool public constant threePool = CurvePool(0xA79828DF1850E8a3A3064576f380D90aECDD3359);\n\n IConvex public immutable stkFrax3Crv;\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant FRAX3CRV = IERC20(0xd632f22692FaC7611d2AA1C0D552930D43CAEd3B);\n\n constructor(IConvex _stkFrax3Crv) public {\n stkFrax3Crv = _stkFrax3Crv;\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(threePool), type(uint256).max);\n FRAX3CRV.approve(address(_stkFrax3Crv), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountUSDT = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(this));\n\n // Pool token order is FRAX, DAI, USDC, USDT\n uint256[4] memory amountsAdded = [0, 0, 0, amountUSDT];\n uint256 frax3CrvAmount = threePool.add_liquidity(address(FRAX3CRV), amountsAdded, 0);\n\n stkFrax3Crv.deposit(frax3CrvAmount, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(stkFrax3Crv, address(bentoBox), recipient, frax3CrvAmount, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\n/// @notice A library for performing overflow-/underflow-safe math,\n/// updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math).\nlibrary BoringMath {\n function add(uint256 a, uint256 b) internal pure returns (uint256 c) {\n require((c = a + b) >= b, \"BoringMath: Add Overflow\");\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {\n require((c = a - b) <= a, \"BoringMath: Underflow\");\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {\n require(b == 0 || (c = a * b) / b == a, \"BoringMath: Mul Overflow\");\n }\n\n function to128(uint256 a) internal pure returns (uint128 c) {\n require(a <= uint128(-1), \"BoringMath: uint128 Overflow\");\n c = uint128(a);\n }\n\n function to64(uint256 a) internal pure returns (uint64 c) {\n require(a <= uint64(-1), \"BoringMath: uint64 Overflow\");\n c = uint64(a);\n }\n\n function to32(uint256 a) internal pure returns (uint32 c) {\n require(a <= uint32(-1), \"BoringMath: uint32 Overflow\");\n c = uint32(a);\n }\n}\n\n/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint128.\nlibrary BoringMath128 {\n function add(uint128 a, uint128 b) internal pure returns (uint128 c) {\n require((c = a + b) >= b, \"BoringMath: Add Overflow\");\n }\n\n function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {\n require((c = a - b) <= a, \"BoringMath: Underflow\");\n }\n}\n\n/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint64.\nlibrary BoringMath64 {\n function add(uint64 a, uint64 b) internal pure returns (uint64 c) {\n require((c = a + b) >= b, \"BoringMath: Add Overflow\");\n }\n\n function sub(uint64 a, uint64 b) internal pure returns (uint64 c) {\n require((c = a - b) <= a, \"BoringMath: Underflow\");\n }\n}\n\n/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint32.\nlibrary BoringMath32 {\n function add(uint32 a, uint32 b) internal pure returns (uint32 c) {\n require((c = a + b) >= b, \"BoringMath: Add Overflow\");\n }\n\n function sub(uint32 a, uint32 b) internal pure returns (uint32 c) {\n require((c = a - b) <= a, \"BoringMath: Underflow\");\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"../interfaces/IERC20.sol\";\n\n// solhint-disable avoid-low-level-calls\n\nlibrary BoringERC20 {\n bytes4 private constant SIG_SYMBOL = 0x95d89b41; // symbol()\n bytes4 private constant SIG_NAME = 0x06fdde03; // name()\n bytes4 private constant SIG_DECIMALS = 0x313ce567; // decimals()\n bytes4 private constant SIG_TRANSFER = 0xa9059cbb; // transfer(address,uint256)\n bytes4 private constant SIG_TRANSFER_FROM = 0x23b872dd; // transferFrom(address,address,uint256)\n\n function returnDataToString(bytes memory data) internal pure returns (string memory) {\n if (data.length >= 64) {\n return abi.decode(data, (string));\n } else if (data.length == 32) {\n uint8 i = 0;\n while(i < 32 && data[i] != 0) {\n i++;\n }\n bytes memory bytesArray = new bytes(i);\n for (i = 0; i < 32 && data[i] != 0; i++) {\n bytesArray[i] = data[i];\n }\n return string(bytesArray);\n } else {\n return \"???\";\n }\n }\n\n /// @notice Provides a safe ERC20.symbol version which returns '???' as fallback string.\n /// @param token The address of the ERC-20 token contract.\n /// @return (string) Token symbol.\n function safeSymbol(IERC20 token) internal view returns (string memory) {\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_SYMBOL));\n return success ? returnDataToString(data) : \"???\";\n }\n\n /// @notice Provides a safe ERC20.name version which returns '???' as fallback string.\n /// @param token The address of the ERC-20 token contract.\n /// @return (string) Token name.\n function safeName(IERC20 token) internal view returns (string memory) {\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_NAME));\n return success ? returnDataToString(data) : \"???\";\n }\n\n /// @notice Provides a safe ERC20.decimals version which returns '18' as fallback value.\n /// @param token The address of the ERC-20 token contract.\n /// @return (uint8) Token decimals.\n function safeDecimals(IERC20 token) internal view returns (uint8) {\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_DECIMALS));\n return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;\n }\n\n /// @notice Provides a safe ERC20.transfer version for different ERC-20 implementations.\n /// Reverts on a failed transfer.\n /// @param token The address of the ERC-20 token.\n /// @param to Transfer tokens to.\n /// @param amount The token amount.\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 amount\n ) internal {\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(SIG_TRANSFER, to, amount));\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: Transfer failed\");\n }\n\n /// @notice Provides a safe ERC20.transferFrom version for different ERC-20 implementations.\n /// Reverts on a failed transfer.\n /// @param token The address of the ERC-20 token.\n /// @param from Transfer tokens from.\n /// @param to Transfer tokens to.\n /// @param amount The token amount.\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(SIG_TRANSFER_FROM, from, to, amount));\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: TransferFrom failed\");\n }\n}\n" + }, + "@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport '@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol';\nimport '@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol';\nimport './IBatchFlashBorrower.sol';\nimport './IFlashBorrower.sol';\nimport './IStrategy.sol';\n\ninterface IBentoBoxV1 {\n event LogDeploy(address indexed masterContract, bytes data, address indexed cloneAddress);\n event LogDeposit(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);\n event LogFlashLoan(address indexed borrower, address indexed token, uint256 amount, uint256 feeAmount, address indexed receiver);\n event LogRegisterProtocol(address indexed protocol);\n event LogSetMasterContractApproval(address indexed masterContract, address indexed user, bool approved);\n event LogStrategyDivest(address indexed token, uint256 amount);\n event LogStrategyInvest(address indexed token, uint256 amount);\n event LogStrategyLoss(address indexed token, uint256 amount);\n event LogStrategyProfit(address indexed token, uint256 amount);\n event LogStrategyQueued(address indexed token, address indexed strategy);\n event LogStrategySet(address indexed token, address indexed strategy);\n event LogStrategyTargetPercentage(address indexed token, uint256 targetPercentage);\n event LogTransfer(address indexed token, address indexed from, address indexed to, uint256 share);\n event LogWhiteListMasterContract(address indexed masterContract, bool approved);\n event LogWithdraw(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n function balanceOf(IERC20, address) external view returns (uint256);\n function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results);\n function batchFlashLoan(IBatchFlashBorrower borrower, address[] calldata receivers, IERC20[] calldata tokens, uint256[] calldata amounts, bytes calldata data) external;\n function claimOwnership() external;\n function deploy(address masterContract, bytes calldata data, bool useCreate2) external payable;\n function deposit(IERC20 token_, address from, address to, uint256 amount, uint256 share) external payable returns (uint256 amountOut, uint256 shareOut);\n function flashLoan(IFlashBorrower borrower, address receiver, IERC20 token, uint256 amount, bytes calldata data) external;\n function harvest(IERC20 token, bool balance, uint256 maxChangeAmount) external;\n function masterContractApproved(address, address) external view returns (bool);\n function masterContractOf(address) external view returns (address);\n function nonces(address) external view returns (uint256);\n function owner() external view returns (address);\n function pendingOwner() external view returns (address);\n function pendingStrategy(IERC20) external view returns (IStrategy);\n function permitToken(IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n function registerProtocol() external;\n function setMasterContractApproval(address user, address masterContract, bool approved, uint8 v, bytes32 r, bytes32 s) external;\n function setStrategy(IERC20 token, IStrategy newStrategy) external;\n function setStrategyTargetPercentage(IERC20 token, uint64 targetPercentage_) external;\n function strategy(IERC20) external view returns (IStrategy);\n function strategyData(IERC20) external view returns (uint64 strategyStartDate, uint64 targetPercentage, uint128 balance);\n function toAmount(IERC20 token, uint256 share, bool roundUp) external view returns (uint256 amount);\n function toShare(IERC20 token, uint256 amount, bool roundUp) external view returns (uint256 share);\n function totals(IERC20) external view returns (Rebase memory totals_);\n function transfer(IERC20 token, address from, address to, uint256 share) external;\n function transferMultiple(IERC20 token, address from, address[] calldata tos, uint256[] calldata shares) external;\n function transferOwnership(address newOwner, bool direct, bool renounce) external;\n function whitelistMasterContract(address masterContract, bool approved) external;\n function whitelistedMasterContracts(address) external view returns (bool);\n function withdraw(IERC20 token_, address from, address to, uint256 amount, uint256 share) external returns (uint256 amountOut, uint256 shareOut);\n}" + }, + "@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"./BoringMath.sol\";\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\n/// @notice A rebasing library using overflow-/underflow-safe math.\nlibrary RebaseLibrary {\n using BoringMath for uint256;\n using BoringMath128 for uint128;\n\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(\n Rebase memory total,\n uint256 elastic,\n bool roundUp\n ) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = elastic.mul(total.base) / total.elastic;\n if (roundUp && base.mul(total.elastic) / total.base < elastic) {\n base = base.add(1);\n }\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(\n Rebase memory total,\n uint256 base,\n bool roundUp\n ) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = base.mul(total.elastic) / total.base;\n if (roundUp && elastic.mul(total.base) / total.elastic < base) {\n elastic = elastic.add(1);\n }\n }\n }\n\n /// @notice Add `elastic` to `total` and doubles `total.base`.\n /// @return (Rebase) The new total.\n /// @return base in relationship to `elastic`.\n function add(\n Rebase memory total,\n uint256 elastic,\n bool roundUp\n ) internal pure returns (Rebase memory, uint256 base) {\n base = toBase(total, elastic, roundUp);\n total.elastic = total.elastic.add(elastic.to128());\n total.base = total.base.add(base.to128());\n return (total, base);\n }\n\n /// @notice Sub `base` from `total` and update `total.elastic`.\n /// @return (Rebase) The new total.\n /// @return elastic in relationship to `base`.\n function sub(\n Rebase memory total,\n uint256 base,\n bool roundUp\n ) internal pure returns (Rebase memory, uint256 elastic) {\n elastic = toElastic(total, base, roundUp);\n total.elastic = total.elastic.sub(elastic.to128());\n total.base = total.base.sub(base.to128());\n return (total, elastic);\n }\n\n /// @notice Add `elastic` and `base` to `total`.\n function add(\n Rebase memory total,\n uint256 elastic,\n uint256 base\n ) internal pure returns (Rebase memory) {\n total.elastic = total.elastic.add(elastic.to128());\n total.base = total.base.add(base.to128());\n return total;\n }\n\n /// @notice Subtract `elastic` and `base` to `total`.\n function sub(\n Rebase memory total,\n uint256 elastic,\n uint256 base\n ) internal pure returns (Rebase memory) {\n total.elastic = total.elastic.sub(elastic.to128());\n total.base = total.base.sub(base.to128());\n return total;\n }\n\n /// @notice Add `elastic` to `total` and update storage.\n /// @return newElastic Returns updated `elastic`.\n function addElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {\n newElastic = total.elastic = total.elastic.add(elastic.to128());\n }\n\n /// @notice Subtract `elastic` from `total` and update storage.\n /// @return newElastic Returns updated `elastic`.\n function subElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {\n newElastic = total.elastic = total.elastic.sub(elastic.to128());\n }\n}\n" + }, + "@sushiswap/bentobox-sdk/contracts/IBatchFlashBorrower.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport '@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol';\n\ninterface IBatchFlashBorrower {\n function onBatchFlashLoan(\n address sender,\n IERC20[] calldata tokens,\n uint256[] calldata amounts,\n uint256[] calldata fees,\n bytes calldata data\n ) external;\n}" + }, + "@sushiswap/bentobox-sdk/contracts/IFlashBorrower.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport '@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol';\n\ninterface IFlashBorrower {\n function onFlashLoan(\n address sender,\n IERC20 token,\n uint256 amount,\n uint256 fee,\n bytes calldata data\n ) external;\n}" + }, + "@sushiswap/bentobox-sdk/contracts/IStrategy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\ninterface IStrategy {\n // Send the assets to the Strategy and call skim to invest them\n function skim(uint256 amount) external;\n\n // Harvest any profits made converted to the asset and pass them to the caller\n function harvest(uint256 balance, address sender) external returns (int256 amountAdded);\n\n // Withdraw assets. The returned amount can differ from the requested amount due to rounding.\n // The actualAmount should be very close to the amount. The difference should NOT be used to report a loss. That's what harvest is for.\n function withdraw(uint256 amount) external returns (uint256 actualAmount);\n\n // Withdraw all assets in the safest way possible. This shouldn't fail.\n function exit(uint256 balance) external returns (int256 amountAdded);\n}" + }, + "contracts/swappers/SushiSwapSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ncontract SushiSwapSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n IUniswapV2Factory public immutable factory;\n bytes32 public immutable pairCodeHash;\n\n constructor(\n IBentoBoxV1 bentoBox_,\n IUniswapV2Factory factory_,\n bytes32 pairCodeHash_\n ) public {\n bentoBox = bentoBox_;\n factory = factory_;\n pairCodeHash = pairCodeHash_;\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (IERC20 token0, IERC20 token1) = fromToken < toToken ? (fromToken, toToken) : (toToken, fromToken);\n IUniswapV2Pair pair = IUniswapV2Pair(\n uint256(\n keccak256(abi.encodePacked(hex\"ff\", factory, keccak256(abi.encodePacked(address(token0), address(token1))), pairCodeHash))\n )\n );\n\n (uint256 amountFrom, ) = bentoBox.withdraw(fromToken, address(this), address(pair), 0, shareFrom);\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n uint256 amountTo;\n if (toToken > fromToken) {\n amountTo = getAmountOut(amountFrom, reserve0, reserve1);\n pair.swap(0, amountTo, address(bentoBox), new bytes(0));\n } else {\n amountTo = getAmountOut(amountFrom, reserve1, reserve0);\n pair.swap(amountTo, 0, address(bentoBox), new bytes(0));\n }\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n IUniswapV2Pair pair;\n {\n (IERC20 token0, IERC20 token1) = fromToken < toToken ? (fromToken, toToken) : (toToken, fromToken);\n pair = IUniswapV2Pair(\n uint256(\n keccak256(\n abi.encodePacked(hex\"ff\", factory, keccak256(abi.encodePacked(address(token0), address(token1))), pairCodeHash)\n )\n )\n );\n }\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n\n uint256 amountToExact = bentoBox.toAmount(toToken, shareToExact, true);\n\n uint256 amountFrom;\n if (toToken > fromToken) {\n amountFrom = getAmountIn(amountToExact, reserve0, reserve1);\n (, shareUsed) = bentoBox.withdraw(fromToken, address(this), address(pair), amountFrom, 0);\n pair.swap(0, amountToExact, address(bentoBox), \"\");\n } else {\n amountFrom = getAmountIn(amountToExact, reserve1, reserve0);\n (, shareUsed) = bentoBox.withdraw(fromToken, address(this), address(pair), amountFrom, 0);\n pair.swap(amountToExact, 0, address(bentoBox), \"\");\n }\n bentoBox.deposit(toToken, address(bentoBox), recipient, 0, shareToExact);\n shareReturned = shareFromSupplied.sub(shareUsed);\n if (shareReturned > 0) {\n bentoBox.transfer(fromToken, address(this), refundTo, shareReturned);\n }\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Factory {\n event PairCreated(address indexed token0, address indexed token1, address pair, uint);\n\n function feeTo() external view returns (address);\n function feeToSetter() external view returns (address);\n function migrator() external view returns (address);\n\n function getPair(address tokenA, address tokenB) external view returns (address pair);\n function allPairs(uint) external view returns (address pair);\n function allPairsLength() external view returns (uint);\n\n function createPair(address tokenA, address tokenB) external returns (address pair);\n\n function setFeeTo(address) external;\n function setFeeToSetter(address) external;\n function setMigrator(address) external;\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "contracts/swappers/Liquidations/YVYFISwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw(uint256 maxShares, address recipient) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract YVYFISwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n YearnVault public constant YFI_VAULT = YearnVault(0xE14d13d8B3b85aF791b2AADD661cDBd5E6097Db1);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n IUniswapV2Pair constant YFI_WETH = IUniswapV2Pair(0x088ee5007C98a9677165D78dD2109AE4a3D04d0C);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n \n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n uint256 amountFirst;\n\n {\n\n bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n uint256 amountFrom = YFI_VAULT.withdraw(type(uint256).max, address(YFI_WETH));\n\n (uint256 reserve0, uint256 reserve1, ) = YFI_WETH.getReserves();\n \n amountFirst = getAmountOut(amountFrom, reserve0, reserve1);\n\n }\n \n YFI_WETH.swap(0, amountFirst, address(pair), new bytes(0));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n uint256 amountIntermediate = getAmountOut(amountFirst, reserve0, reserve1);\n pair.swap(0, amountIntermediate, address(this), new bytes(0));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/SushiSwapMultiSwapper.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../libraries/UniswapV2Library.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/libraries/TransferHelper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ncontract SushiSwapMultiSwapper {\n using BoringERC20 for IERC20;\n using BoringMath for uint256;\n\n address private immutable factory;\n\n IBentoBoxV1 private immutable bentoBox;\n\n bytes32 private immutable pairCodeHash;\n\n constructor(\n address _factory,\n IBentoBoxV1 _bentoBox,\n bytes32 _pairCodeHash\n ) public {\n factory = _factory;\n bentoBox = _bentoBox;\n pairCodeHash = _pairCodeHash;\n }\n\n function getOutputAmount(\n IERC20 tokenIn,\n IERC20 tokenOut,\n uint256 amountMinOut,\n address[] calldata path,\n uint256 shareIn\n ) external view returns (uint256 amountOut) {\n uint256 amountIn = bentoBox.toAmount(tokenIn, shareIn, false);\n uint256[] memory amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path, pairCodeHash);\n amountOut = amounts[amounts.length - 1];\n }\n\n function swap(\n IERC20 tokenIn,\n IERC20 tokenOut,\n uint256 amountMinOut,\n address[] calldata path,\n uint256 shareIn\n ) external returns (uint256 amountOut, uint256 shareOut) {\n (uint256 amountIn, ) = bentoBox.withdraw(tokenIn, address(this), address(this), 0, shareIn);\n amountOut = _swapExactTokensForTokens(amountIn, amountMinOut, path, address(bentoBox));\n (, shareOut) = bentoBox.deposit(tokenOut, address(bentoBox), msg.sender, amountOut, 0);\n }\n\n // Swaps an exact amount of tokens for another token through the path passed as an argument\n // Returns the amount of the final token\n function _swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] memory path,\n address to\n ) internal returns (uint256 amountOut) {\n uint256[] memory amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path, pairCodeHash);\n amountOut = amounts[amounts.length - 1];\n require(amountOut >= amountOutMin, \"insufficient-amount-out\");\n IERC20(path[0]).safeTransfer(UniswapV2Library.pairFor(factory, path[0], path[1], pairCodeHash), amountIn);\n _swap(amounts, path, to);\n }\n\n // requires the initial amount to have already been sent to the first pair\n function _swap(\n uint256[] memory amounts,\n address[] memory path,\n address _to\n ) internal virtual {\n for (uint256 i; i < path.length - 1; i++) {\n (address input, address output) = (path[i], path[i + 1]);\n (address token0, ) = UniswapV2Library.sortTokens(input, output);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = input == token0 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2], pairCodeHash) : _to;\n IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output, pairCodeHash)).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n }\n}\n" + }, + "contracts/libraries/UniswapV2Library.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\n\nimport \"@sushiswap/core/contracts/uniswapv2/libraries/SafeMath.sol\";\n\nlibrary UniswapV2Library {\n using SafeMathUniswap for uint256;\n\n // returns sorted token addresses, used to handle return values from pairs sorted in this order\n function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {\n require(tokenA != tokenB, \"UniswapV2Library: IDENTICAL_ADDRESSES\");\n (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), \"UniswapV2Library: ZERO_ADDRESS\");\n }\n\n // calculates the CREATE2 address for a pair without making any external calls\n function pairFor(\n address factory,\n address tokenA,\n address tokenB,\n bytes32 pairCodeHash\n ) internal pure returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1)),\n pairCodeHash // init code hash\n )\n )\n )\n );\n }\n\n // fetches and sorts the reserves for a pair\n function getReserves(\n address factory,\n address tokenA,\n address tokenB,\n bytes32 pairCodeHash\n ) internal view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB, pairCodeHash)).getReserves();\n (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n }\n\n // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n function quote(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) internal pure returns (uint256 amountB) {\n require(amountA > 0, \"UniswapV2Library: INSUFFICIENT_AMOUNT\");\n require(reserveA > 0 && reserveB > 0, \"UniswapV2Library: INSUFFICIENT_LIQUIDITY\");\n amountB = amountA.mul(reserveB) / reserveA;\n }\n\n // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n require(amountIn > 0, \"UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT\");\n require(reserveIn > 0 && reserveOut > 0, \"UniswapV2Library: INSUFFICIENT_LIQUIDITY\");\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n require(amountOut > 0, \"UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT\");\n require(reserveIn > 0 && reserveOut > 0, \"UniswapV2Library: INSUFFICIENT_LIQUIDITY\");\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // performs chained getAmountOut calculations on any number of pairs\n function getAmountsOut(\n address factory,\n uint256 amountIn,\n address[] memory path,\n bytes32 pairCodeHash\n ) internal view returns (uint256[] memory amounts) {\n require(path.length >= 2, \"UniswapV2Library: INVALID_PATH\");\n amounts = new uint256[](path.length);\n amounts[0] = amountIn;\n for (uint256 i; i < path.length - 1; i++) {\n (uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i], path[i + 1], pairCodeHash);\n amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);\n }\n }\n\n // performs chained getAmountIn calculations on any number of pairs\n function getAmountsIn(\n address factory,\n uint256 amountOut,\n address[] memory path,\n bytes32 pairCodeHash\n ) internal view returns (uint256[] memory amounts) {\n require(path.length >= 2, \"UniswapV2Library: INVALID_PATH\");\n amounts = new uint256[](path.length);\n amounts[amounts.length - 1] = amountOut;\n for (uint256 i = path.length - 1; i > 0; i--) {\n (uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i - 1], path[i], pairCodeHash);\n amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);\n }\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/libraries/TransferHelper.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.6.0;\n\n// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false\nlibrary TransferHelper {\n function safeApprove(address token, address to, uint value) internal {\n // bytes4(keccak256(bytes('approve(address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');\n }\n\n function safeTransfer(address token, address to, uint value) internal {\n // bytes4(keccak256(bytes('transfer(address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');\n }\n\n function safeTransferFrom(address token, address from, address to, uint value) internal {\n // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');\n }\n\n function safeTransferETH(address to, uint value) internal {\n (bool success,) = to.call{value:value}(new bytes(0));\n require(success, 'TransferHelper: ETH_TRANSFER_FAILED');\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/libraries/SafeMath.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity =0.6.12;\n\n// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)\n\nlibrary SafeMathUniswap {\n function add(uint x, uint y) internal pure returns (uint z) {\n require((z = x + y) >= x, 'ds-math-add-overflow');\n }\n\n function sub(uint x, uint y) internal pure returns (uint z) {\n require((z = x - y) <= x, 'ds-math-sub-underflow');\n }\n\n function mul(uint x, uint y) internal pure returns (uint z) {\n require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');\n }\n}\n" + }, + "contracts/swappers/SpellSwapper.sol": { + "content": "// License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../libraries/UniswapV2Library.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/libraries/TransferHelper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\n\ninterface CurvePool {\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address receiver\n ) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract SpellSwapper is BoringOwnable {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n IERC20 public constant SPELL = IERC20(0x090185f2135308BaD17527004364eBcC2D37e5F6);\n address public constant sSPELL = 0x26FA3fFFB6EfE8c1E69103aCb4044C26B9A106a9;\n IUniswapV2Pair constant SPELL_WETH = IUniswapV2Pair(0xb5De0C3753b6E1B4dBA616Db82767F17513E6d4E);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n address public constant treasury = 0x5A7C5505f3CFB9a0D9A8493EC41bf27EE48c406D;\n mapping(address => bool) public verified;\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n verified[msg.sender] = true;\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n modifier onlyVerified() {\n require(verified[msg.sender], \"Only verified operators\");\n _;\n }\n\n function setVerified(address operator, bool status) public onlyOwner {\n verified[operator] = status;\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(uint256 amountToMin) public onlyVerified {\n uint256 amountFirst;\n uint256 amountIntermediate;\n\n {\n uint256 shareFrom = bentoBox.balanceOf(MIM, address(this));\n\n uint256 treasuryShare = shareFrom / 4;\n\n bentoBox.withdraw(MIM, address(this), treasury, 0, treasuryShare);\n\n (uint256 amountMIMFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom.sub(treasuryShare));\n\n amountFirst = MIM3POOL.exchange_underlying(0, 3, amountMIMFrom, 0, address(pair));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n amountIntermediate = getAmountOut(amountFirst, reserve1, reserve0);\n }\n\n uint256 amountThird;\n\n {\n pair.swap(amountIntermediate, 0, address(SPELL_WETH), new bytes(0));\n\n (uint256 reserve0, uint256 reserve1, ) = SPELL_WETH.getReserves();\n\n amountThird = getAmountOut(amountIntermediate, reserve1, reserve0);\n\n require(amountThird >= amountToMin, \"Minimum must be reached\");\n }\n\n SPELL_WETH.swap(amountThird, 0, sSPELL, new bytes(0));\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\n// Edited by BoringCrypto\n\ncontract BoringOwnableData {\n address public owner;\n address public pendingOwner;\n}\n\ncontract BoringOwnable is BoringOwnableData {\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /// @notice `owner` defaults to msg.sender on construction.\n constructor() public {\n owner = msg.sender;\n emit OwnershipTransferred(address(0), msg.sender);\n }\n\n /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.\n /// Can only be invoked by the current `owner`.\n /// @param newOwner Address of the new owner.\n /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\n /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\n function transferOwnership(\n address newOwner,\n bool direct,\n bool renounce\n ) public onlyOwner {\n if (direct) {\n // Checks\n require(newOwner != address(0) || renounce, \"Ownable: zero address\");\n\n // Effects\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n pendingOwner = address(0);\n } else {\n // Effects\n pendingOwner = newOwner;\n }\n }\n\n /// @notice Needs to be called by `pendingOwner` to claim ownership.\n function claimOwnership() public {\n address _pendingOwner = pendingOwner;\n\n // Checks\n require(msg.sender == _pendingOwner, \"Ownable: caller != pending owner\");\n\n // Effects\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = address(0);\n }\n\n /// @notice Only allows the `owner` to execute the function.\n modifier onlyOwner() {\n require(msg.sender == owner, \"Ownable: caller is not the owner\");\n _;\n }\n}\n" + }, + "contracts/Spell.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// Spell\n\n// Special thanks to:\n// @BoringCrypto for his great libraries\n\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/ERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\n\n/// @title Spell\n/// @author 0xMerlin\n/// @dev This contract allows contract calls to any contract (except BentoBox)\n/// from arbitrary callers thus, don't trust calls from this contract in any circumstances.\ncontract Spell is ERC20, BoringOwnable {\n using BoringMath for uint256;\n // ERC20 'variables'\n string public constant symbol = \"SPELL\";\n string public constant name = \"Spell Token\";\n uint8 public constant decimals = 18;\n uint256 public override totalSupply;\n uint256 public constant MAX_SUPPLY = 420 * 1e27;\n\n function mint(address to, uint256 amount) public onlyOwner {\n require(to != address(0), \"SPELL: no mint to zero address\");\n require(MAX_SUPPLY >= totalSupply.add(amount), \"SPELL: Don't go over MAX\");\n\n totalSupply = totalSupply + amount;\n balanceOf[to] += amount;\n emit Transfer(address(0), to, amount);\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"./interfaces/IERC20.sol\";\nimport \"./Domain.sol\";\n\n// solhint-disable no-inline-assembly\n// solhint-disable not-rely-on-time\n\n// Data part taken out for building of contracts that receive delegate calls\ncontract ERC20Data {\n /// @notice owner > balance mapping.\n mapping(address => uint256) public balanceOf;\n /// @notice owner > spender > allowance mapping.\n mapping(address => mapping(address => uint256)) public allowance;\n /// @notice owner > nonce mapping. Used in `permit`.\n mapping(address => uint256) public nonces;\n}\n\nabstract contract ERC20 is IERC20, Domain {\n /// @notice owner > balance mapping.\n mapping(address => uint256) public override balanceOf;\n /// @notice owner > spender > allowance mapping.\n mapping(address => mapping(address => uint256)) public override allowance;\n /// @notice owner > nonce mapping. Used in `permit`.\n mapping(address => uint256) public nonces;\n\n event Transfer(address indexed _from, address indexed _to, uint256 _value);\n event Approval(address indexed _owner, address indexed _spender, uint256 _value);\n\n /// @notice Transfers `amount` tokens from `msg.sender` to `to`.\n /// @param to The address to move the tokens.\n /// @param amount of the tokens to move.\n /// @return (bool) Returns True if succeeded.\n function transfer(address to, uint256 amount) public returns (bool) {\n // If `amount` is 0, or `msg.sender` is `to` nothing happens\n if (amount != 0 || msg.sender == to) {\n uint256 srcBalance = balanceOf[msg.sender];\n require(srcBalance >= amount, \"ERC20: balance too low\");\n if (msg.sender != to) {\n require(to != address(0), \"ERC20: no zero address\"); // Moved down so low balance calls safe some gas\n\n balanceOf[msg.sender] = srcBalance - amount; // Underflow is checked\n balanceOf[to] += amount;\n }\n }\n emit Transfer(msg.sender, to, amount);\n return true;\n }\n\n /// @notice Transfers `amount` tokens from `from` to `to`. Caller needs approval for `from`.\n /// @param from Address to draw tokens from.\n /// @param to The address to move the tokens.\n /// @param amount The token amount to move.\n /// @return (bool) Returns True if succeeded.\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public returns (bool) {\n // If `amount` is 0, or `from` is `to` nothing happens\n if (amount != 0) {\n uint256 srcBalance = balanceOf[from];\n require(srcBalance >= amount, \"ERC20: balance too low\");\n\n if (from != to) {\n uint256 spenderAllowance = allowance[from][msg.sender];\n // If allowance is infinite, don't decrease it to save on gas (breaks with EIP-20).\n if (spenderAllowance != type(uint256).max) {\n require(spenderAllowance >= amount, \"ERC20: allowance too low\");\n allowance[from][msg.sender] = spenderAllowance - amount; // Underflow is checked\n }\n require(to != address(0), \"ERC20: no zero address\"); // Moved down so other failed calls safe some gas\n\n balanceOf[from] = srcBalance - amount; // Underflow is checked\n balanceOf[to] += amount;\n }\n }\n emit Transfer(from, to, amount);\n return true;\n }\n\n /// @notice Approves `amount` from sender to be spend by `spender`.\n /// @param spender Address of the party that can draw from msg.sender's account.\n /// @param amount The maximum collective amount that `spender` can draw.\n /// @return (bool) Returns True if approved.\n function approve(address spender, uint256 amount) public override returns (bool) {\n allowance[msg.sender][spender] = amount;\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32) {\n return _domainSeparator();\n }\n\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 private constant PERMIT_SIGNATURE_HASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n\n /// @notice Approves `value` from `owner_` to be spend by `spender`.\n /// @param owner_ Address of the owner.\n /// @param spender The address of the spender that gets approved to draw from `owner_`.\n /// @param value The maximum collective amount that `spender` can draw.\n /// @param deadline This permit must be redeemed before this deadline (UTC timestamp in seconds).\n function permit(\n address owner_,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external override {\n require(owner_ != address(0), \"ERC20: Owner cannot be 0\");\n require(block.timestamp < deadline, \"ERC20: Expired\");\n require(\n ecrecover(_getDigest(keccak256(abi.encode(PERMIT_SIGNATURE_HASH, owner_, spender, value, nonces[owner_]++, deadline))), v, r, s) ==\n owner_,\n \"ERC20: Invalid Signature\"\n );\n allowance[owner_][spender] = value;\n emit Approval(owner_, spender, value);\n }\n}\n\ncontract ERC20WithSupply is IERC20, ERC20 {\n uint256 public override totalSupply;\n\n function _mint(address user, uint256 amount) private {\n uint256 newTotalSupply = totalSupply + amount;\n require(newTotalSupply >= totalSupply, \"Mint overflow\");\n totalSupply = newTotalSupply;\n balanceOf[user] += amount;\n }\n\n function _burn(address user, uint256 amount) private {\n require(balanceOf[user] >= amount, \"Burn too much\");\n totalSupply -= amount;\n balanceOf[user] -= amount;\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/Domain.sol": { + "content": "// SPDX-License-Identifier: MIT\n// Based on code and smartness by Ross Campbell and Keno\n// Uses immutable to store the domain separator to reduce gas usage\n// If the chain id changes due to a fork, the forked chain will calculate on the fly.\npragma solidity 0.6.12;\n\n// solhint-disable no-inline-assembly\n\ncontract Domain {\n bytes32 private constant DOMAIN_SEPARATOR_SIGNATURE_HASH = keccak256(\"EIP712Domain(uint256 chainId,address verifyingContract)\");\n // See https://eips.ethereum.org/EIPS/eip-191\n string private constant EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA = \"\\x19\\x01\";\n\n // solhint-disable var-name-mixedcase\n bytes32 private immutable _DOMAIN_SEPARATOR;\n uint256 private immutable DOMAIN_SEPARATOR_CHAIN_ID; \n\n /// @dev Calculate the DOMAIN_SEPARATOR\n function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) {\n return keccak256(\n abi.encode(\n DOMAIN_SEPARATOR_SIGNATURE_HASH,\n chainId,\n address(this)\n )\n );\n }\n\n constructor() public {\n uint256 chainId; assembly {chainId := chainid()}\n _DOMAIN_SEPARATOR = _calculateDomainSeparator(DOMAIN_SEPARATOR_CHAIN_ID = chainId);\n }\n\n /// @dev Return the DOMAIN_SEPARATOR\n // It's named internal to allow making it public from the contract that uses it by creating a simple view function\n // with the desired public name, such as DOMAIN_SEPARATOR or domainSeparator.\n // solhint-disable-next-line func-name-mixedcase\n function _domainSeparator() internal view returns (bytes32) {\n uint256 chainId; assembly {chainId := chainid()}\n return chainId == DOMAIN_SEPARATOR_CHAIN_ID ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(chainId);\n }\n\n function _getDigest(bytes32 dataHash) internal view returns (bytes32 digest) {\n digest =\n keccak256(\n abi.encodePacked(\n EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA,\n _domainSeparator(),\n dataHash\n )\n );\n }\n}" + }, + "contracts/sSpell.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/Domain.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/ERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringBatchable.sol\";\n\n\n// Staking in sSpell inspired by Chef Nomi's SushiBar - MIT license (originally WTFPL)\n// modified by BoringCrypto for DictatorDAO\n\ncontract sSpell is IERC20, Domain {\n using BoringMath for uint256;\n using BoringMath128 for uint128;\n using BoringERC20 for IERC20;\n\n string public constant symbol = \"sSPELL\";\n string public constant name = \"Staked Spell Tokens\";\n uint8 public constant decimals = 18;\n uint256 public override totalSupply;\n uint256 private constant LOCK_TIME = 24 hours;\n\n IERC20 public immutable token;\n\n constructor(IERC20 _token) public {\n token = _token;\n }\n\n struct User {\n uint128 balance;\n uint128 lockedUntil;\n }\n\n /// @notice owner > balance mapping.\n mapping(address => User) public users;\n /// @notice owner > spender > allowance mapping.\n mapping(address => mapping(address => uint256)) public override allowance;\n /// @notice owner > nonce mapping. Used in `permit`.\n mapping(address => uint256) public nonces;\n\n event Transfer(address indexed _from, address indexed _to, uint256 _value);\n event Approval(address indexed _owner, address indexed _spender, uint256 _value);\n\n function balanceOf(address user) public view override returns (uint256 balance) {\n return users[user].balance;\n }\n\n function _transfer(\n address from,\n address to,\n uint256 shares\n ) internal {\n User memory fromUser = users[from];\n require(block.timestamp >= fromUser.lockedUntil, \"Locked\");\n if (shares != 0) {\n require(fromUser.balance >= shares, \"Low balance\");\n if (from != to) {\n require(to != address(0), \"Zero address\"); // Moved down so other failed calls safe some gas\n User memory toUser = users[to];\n users[from].balance = fromUser.balance - shares.to128(); // Underflow is checked\n users[to].balance = toUser.balance + shares.to128(); // Can't overflow because totalSupply would be greater than 2^128-1;\n }\n }\n emit Transfer(from, to, shares);\n }\n\n function _useAllowance(address from, uint256 shares) internal {\n if (msg.sender == from) {\n return;\n }\n uint256 spenderAllowance = allowance[from][msg.sender];\n // If allowance is infinite, don't decrease it to save on gas (breaks with EIP-20).\n if (spenderAllowance != type(uint256).max) {\n require(spenderAllowance >= shares, \"Low allowance\");\n allowance[from][msg.sender] = spenderAllowance - shares; // Underflow is checked\n }\n }\n\n /// @notice Transfers `shares` tokens from `msg.sender` to `to`.\n /// @param to The address to move the tokens.\n /// @param shares of the tokens to move.\n /// @return (bool) Returns True if succeeded.\n function transfer(address to, uint256 shares) public returns (bool) {\n _transfer(msg.sender, to, shares);\n return true;\n }\n\n /// @notice Transfers `shares` tokens from `from` to `to`. Caller needs approval for `from`.\n /// @param from Address to draw tokens from.\n /// @param to The address to move the tokens.\n /// @param shares The token shares to move.\n /// @return (bool) Returns True if succeeded.\n function transferFrom(\n address from,\n address to,\n uint256 shares\n ) public returns (bool) {\n _useAllowance(from, shares);\n _transfer(from, to, shares);\n return true;\n }\n\n /// @notice Approves `amount` from sender to be spend by `spender`.\n /// @param spender Address of the party that can draw from msg.sender's account.\n /// @param amount The maximum collective amount that `spender` can draw.\n /// @return (bool) Returns True if approved.\n function approve(address spender, uint256 amount) public override returns (bool) {\n allowance[msg.sender][spender] = amount;\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32) {\n return _domainSeparator();\n }\n\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 private constant PERMIT_SIGNATURE_HASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n\n /// @notice Approves `value` from `owner_` to be spend by `spender`.\n /// @param owner_ Address of the owner.\n /// @param spender The address of the spender that gets approved to draw from `owner_`.\n /// @param value The maximum collective amount that `spender` can draw.\n /// @param deadline This permit must be redeemed before this deadline (UTC timestamp in seconds).\n function permit(\n address owner_,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external override {\n require(owner_ != address(0), \"Zero owner\");\n require(block.timestamp < deadline, \"Expired\");\n require(\n ecrecover(_getDigest(keccak256(abi.encode(PERMIT_SIGNATURE_HASH, owner_, spender, value, nonces[owner_]++, deadline))), v, r, s) ==\n owner_,\n \"Invalid Sig\"\n );\n allowance[owner_][spender] = value;\n emit Approval(owner_, spender, value);\n }\n\n /// math is ok, because amount, totalSupply and shares is always 0 <= amount <= 100.000.000 * 10^18\n /// theoretically you can grow the amount/share ratio, but it's not practical and useless\n function mint(uint256 amount) public returns (bool) {\n require(msg.sender != address(0), \"Zero address\");\n User memory user = users[msg.sender];\n\n uint256 totalTokens = token.balanceOf(address(this));\n uint256 shares = totalSupply == 0 ? amount : (amount * totalSupply) / totalTokens;\n user.balance += shares.to128();\n user.lockedUntil = (block.timestamp + LOCK_TIME).to128();\n users[msg.sender] = user;\n totalSupply += shares;\n\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n emit Transfer(address(0), msg.sender, shares);\n return true;\n }\n\n function _burn(\n address from,\n address to,\n uint256 shares\n ) internal {\n require(to != address(0), \"Zero address\");\n User memory user = users[from];\n require(block.timestamp >= user.lockedUntil, \"Locked\");\n uint256 amount = (shares * token.balanceOf(address(this))) / totalSupply;\n users[from].balance = user.balance.sub(shares.to128()); // Must check underflow\n totalSupply -= shares;\n\n token.safeTransfer(to, amount);\n\n emit Transfer(from, address(0), shares);\n }\n\n function burn(address to, uint256 shares) public returns (bool) {\n _burn(msg.sender, to, shares);\n return true;\n }\n\n function burnFrom(\n address from,\n address to,\n uint256 shares\n ) public returns (bool) {\n _useAllowance(from, shares);\n _burn(from, to, shares);\n return true;\n }\n}" + }, + "@boringcrypto/boring-solidity/contracts/BoringBatchable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\n// solhint-disable avoid-low-level-calls\n// solhint-disable no-inline-assembly\n\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n\nimport \"./interfaces/IERC20.sol\";\n\ncontract BaseBoringBatchable {\n /// @dev Helper function to extract a useful revert message from a failed call.\n /// If the returned data is malformed or not correctly abi encoded then this call can fail itself.\n function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_returnData.length < 68) return \"Transaction reverted silently\";\n\n assembly {\n // Slice the sighash.\n _returnData := add(_returnData, 0x04)\n }\n return abi.decode(_returnData, (string)); // All that remains is the revert string\n }\n\n /// @notice Allows batched call to self (this contract).\n /// @param calls An array of inputs for each call.\n /// @param revertOnFail If True then reverts after a failed call and stops doing further calls.\n // F1: External is ok here because this is the batch function, adding it to a batch makes no sense\n // F2: Calls in the batch may be payable, delegatecall operates in the same context, so each call in the batch has access to msg.value\n // C3: The length of the loop is fully under user control, so can't be exploited\n // C7: Delegatecall is only used on the same contract, so it's safe\n function batch(bytes[] calldata calls, bool revertOnFail) external payable {\n for (uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory result) = address(this).delegatecall(calls[i]);\n if (!success && revertOnFail) {\n revert(_getRevertMsg(result));\n }\n }\n }\n}\n\ncontract BoringBatchable is BaseBoringBatchable {\n /// @notice Call wrapper that performs `ERC20.permit` on `token`.\n /// Lookup `IERC20.permit`.\n // F6: Parameters can be used front-run the permit and the user's permit will fail (due to nonce or other revert)\n // if part of a batch this could be used to grief once as the second call would not need the permit\n function permitToken(\n IERC20 token,\n address from,\n address to,\n uint256 amount,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public {\n token.permit(from, to, amount, deadline, v, r, s);\n }\n}\n" + }, + "contracts/swappers/Liquidations/YVUSDTSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract YVUSDTSwapper is ISwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n YearnVault public constant TETHER_VAULT = YearnVault(0x7Da96a3891Add058AdA2E826306D812C638D87a7);\n\n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n uint256 amountFrom =TETHER_VAULT.withdraw();\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountFrom, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (1,1);\n }\n}\n" + }, + "contracts/swappers/Liquidations/YVUSDCSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n}\n\ncontract YVUSDCSwapper is ISwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IERC20 public constant TETHER = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n YearnVault public constant USDC_VAULT = YearnVault(0x5f18C75AbDAe578b483E5F43f12a39cF75b973a9);\n IERC20 public constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n\n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n USDC.approve(address(MIM3POOL), type(uint256).max);\n }\n\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n uint256 amountFrom = USDC_VAULT.withdraw();\n\n uint256 amountTo = MIM3POOL.exchange_underlying(2, 0, amountFrom, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (1,1);\n }\n}\n" + }, + "contracts/swappers/Leverage/YVUSDTLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract YVUSDTLevSwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n YearnVault public constant USDT_VAULT = YearnVault(0x7Da96a3891Add058AdA2E826306D812C638D87a7);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(USDT_VAULT), type(uint256).max);\n }\n\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(this));\n\n uint256 amountTo = USDT_VAULT.deposit(type(uint256).max, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(IERC20(address(USDT_VAULT)), address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/YVUSDCLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\n\ncontract YVUSDCLeverageSwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n YearnVault public constant USDC_VAULT = YearnVault(0x5f18C75AbDAe578b483E5F43f12a39cF75b973a9);\n IERC20 public constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n MIM.approve(address(MIM3POOL), type(uint256).max);\n USDC.approve(address(USDC_VAULT), type(uint256).max);\n }\n\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountIntermediate = MIM3POOL.exchange_underlying(0, 2, amountFrom, 0, address(this));\n\n uint256 amountTo = USDC_VAULT.deposit(type(uint256).max, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(IERC20(address(USDC_VAULT)), address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/YVIBLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function add_liquidity(uint256[3] memory amounts, uint256 _min_mint_amount, bool _use_underlying) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract YVIBLevSwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool constant public IronBank = CurvePool(0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF);\n YearnVault constant public YVIB = YearnVault(0x27b7b1ad7288079A66d12350c828D3C00A6F07d7);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant CurveToken = IERC20(0x5282a4eF67D9C33135340fB3289cc1711c13638C);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(IronBank), type(uint256).max);\n CurveToken.approve(address(YVIB), type(uint256).max);\n }\n\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountIntermediate = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(this));\n\n uint256[3] memory amountsAdded = [0,0, amountIntermediate];\n\n IronBank.add_liquidity(amountsAdded, 0, true);\n\n uint256 amountTo = YVIB.deposit(type(uint256).max, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(IERC20(address(YVIB)), address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/YVCrvStETHLevSwapper2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function add_liquidity(uint256[3] memory amounts, uint256 _min_mint_amount, bool _use_underlying) external returns (uint256);\n function add_liquidity(uint256[2] memory amounts, uint256 _min_mint_amount) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\ninterface IWETH is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n function deposit() external payable;\n function withdraw(uint wad) external;\n}\ninterface IThreeCrypto is CurvePool {\n function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;\n}\ncontract YVCrvStETHLevSwapper2 {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public constant degenBox = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool constant public STETH = CurvePool(0x828b154032950C8ff7CF8085D841723Db2696056);\n YearnVault constant public YVSTETH = YearnVault(0x5faF6a2D186448Dfa667c51CB3D695c7A6E52d8E);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant CurveToken = IERC20(0x828b154032950C8ff7CF8085D841723Db2696056);\n IWETH public constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n IThreeCrypto constant public threecrypto = IThreeCrypto(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(threecrypto), type(uint256).max);\n WETH.approve(address(STETH), type(uint256).max);\n CurveToken.approve(address(YVSTETH), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n receive() external payable {}\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = degenBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n uint256 amountThird;\n {\n uint256 amountSecond = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(this));\n \n threecrypto.exchange(0, 2, amountSecond, 0);\n\n amountThird = WETH.balanceOf(address(this));\n }\n \n uint256[2] memory amountsAdded = [amountThird,0];\n\n STETH.add_liquidity(amountsAdded, 0);\n\n uint256 amountTo = YVSTETH.deposit(type(uint256).max, address(degenBox));\n\n (, shareReturned) = degenBox.deposit(IERC20(address(YVSTETH)), address(degenBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/YVCrvStETHLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function add_liquidity(uint256[3] memory amounts, uint256 _min_mint_amount, bool _use_underlying) external returns (uint256);\n function add_liquidity(uint256[2] memory amounts, uint256 _min_mint_amount) external payable returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\ninterface IWETH is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n function deposit() external payable;\n function withdraw(uint wad) external;\n}\n\ncontract YVCrvStETHLevSwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool constant public STETH = CurvePool(0xDC24316b9AE028F1497c275EB9192a3Ea0f67022);\n YearnVault constant public YVSTETH = YearnVault(0xdCD90C7f6324cfa40d7169ef80b12031770B4325);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant CurveToken = IERC20(0x06325440D014e39736583c165C2963BA99fAf14E);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n IWETH public constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(STETH), type(uint256).max);\n CurveToken.approve(address(YVSTETH), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n receive() external payable {}\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n uint256 amountThird;\n {\n uint256 amountSecond = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(pair));\n \n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n amountThird = getAmountOut(amountSecond, reserve1, reserve0);\n pair.swap(amountThird, 0, address(this), new bytes(0));\n }\n\n WETH.withdraw(amountThird);\n \n uint256[2] memory amountsAdded = [amountThird,0];\n\n STETH.add_liquidity{value: amountThird}(amountsAdded, 0);\n\n uint256 amountTo = YVSTETH.deposit(type(uint256).max, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(IERC20(address(YVSTETH)), address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/WethLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function add_liquidity(uint256[2] memory amounts, uint256 _min_mint_amount) external;\n}\n\ninterface IThreeCrypto is CurvePool {\n function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract WethLevSwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public constant degenBox = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IThreeCrypto constant public threecrypto = IThreeCrypto(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(threecrypto), type(uint256).max);\n WETH.approve(address(degenBox), type(uint256).max);\n }\n\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = degenBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountOne = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(this));\n\n threecrypto.exchange(0, 2, amountOne, 0);\n\n uint256 amountTo = WETH.balanceOf(address(this));\n\n (, shareReturned) = degenBox.deposit(WETH, address(this), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}" + }, + "contracts/swappers/Leverage/WbtcLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function add_liquidity(uint256[2] memory amounts, uint256 _min_mint_amount) external;\n}\n\ninterface IThreeCrypto is CurvePool {\n function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract WbtcLevSwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public constant degenBox = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IThreeCrypto constant public threecrypto = IThreeCrypto(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant WBTC = IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(threecrypto), type(uint256).max);\n WBTC.approve(address(degenBox), type(uint256).max);\n }\n\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = degenBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountOne = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(this));\n\n threecrypto.exchange(0, 1, amountOne, 0);\n\n uint256 amountTo = WBTC.balanceOf(address(this));\n\n (, shareReturned) = degenBox.deposit(WBTC, address(this), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}" + }, + "contracts/swappers/Leverage/ThreeCryptoLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function add_liquidity(uint256[3] memory amounts, uint256 _min_mint_amount) external;\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ninterface IConvex is IERC20{\n function withdrawAndUnwrap(uint256 _amount) external;\n //deposit a curve token\n function deposit(uint256 _amount, address _to) external;\n}\n\ncontract ThreeCryptoLevSwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool constant public threecrypto = CurvePool(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n IConvex public constant cvx3Crypto = IConvex(0x5958A8DB7dfE0CC49382209069b00F54e17929C2);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant CurveToken = IERC20(0xc4AD29ba4B3c580e6D59105FFf484999997675Ff);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(threecrypto), type(uint256).max);\n CurveToken.approve(address(cvx3Crypto), type(uint256).max);\n }\n\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountIntermediate = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(this));\n\n uint256[3] memory amountsAdded = [amountIntermediate, 0, 0];\n\n threecrypto.add_liquidity(amountsAdded, 0);\n\n uint256 amountTo = CurveToken.balanceOf(address(this));\n\n cvx3Crypto.deposit(amountTo, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(cvx3Crypto, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}" + }, + "contracts/swappers/Leverage/RenCrvLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function add_liquidity(uint256[2] memory amounts, uint256 _min_mint_amount) external;\n}\n\ninterface IThreeCrypto is CurvePool {\n function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ninterface IConvex is IERC20{\n function withdrawAndUnwrap(uint256 _amount) external;\n //deposit a curve token\n function deposit(uint256 _amount, address _to) external;\n}\n\ncontract RenCrvLevSwapper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool constant public renCrv = CurvePool(0x93054188d876f558f4a66B2EF1d97d16eDf0895B);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IThreeCrypto constant public threecrypto = IThreeCrypto(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n IConvex public constant cvxRen = IConvex(0xB65eDE134521F0EFD4E943c835F450137dC6E83e);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant CurveToken = IERC20(0x49849C98ae39Fff122806C06791Fa73784FB3675);\n IERC20 public constant WBTC = IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(threecrypto), type(uint256).max);\n WBTC.approve(address(renCrv), type(uint256).max);\n CurveToken.approve(address(cvxRen), type(uint256).max);\n }\n\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountOne = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(this));\n\n threecrypto.exchange(0, 1, amountOne, 0);\n\n uint256 amountIntermediate = WBTC.balanceOf(address(this));\n\n uint256[2] memory amountsAdded = [0, amountIntermediate];\n\n renCrv.add_liquidity(amountsAdded, 0);\n\n uint256 amountTo = CurveToken.balanceOf(address(this));\n\n cvxRen.deposit(amountTo, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(cvxRen, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}" + }, + "contracts/oracles/xSUSHIOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"../interfaces/IOracle.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\n/// @title xSUSHIOracle\n/// @author BoringCrypto\n/// @notice Oracle used for getting the price of xSUSHI based on Chainlink\n/// @dev\ncontract xSUSHIOracle is IOracle {\n using BoringMath for uint256; // Keep everything in uint256\n\n IERC20 public immutable sushi;\n IERC20 public immutable bar;\n IAggregator public immutable sushiOracle;\n\n constructor(\n IERC20 sushi_,\n IERC20 bar_,\n IAggregator sushiOracle_\n ) public {\n sushi = sushi_;\n bar = bar_;\n sushiOracle = sushiOracle_;\n }\n\n // Calculates the lastest exchange rate\n // Uses sushi rate and xSUSHI conversion and divide for any conversion other than from SUSHI to ETH\n function _get(address divide, uint256 decimals) internal view returns (uint256) {\n uint256 price = uint256(1e36);\n price = (price.mul(uint256(sushiOracle.latestAnswer())) / bar.totalSupply()).mul(sushi.balanceOf(address(bar)));\n\n if (divide != address(0)) {\n price = price / uint256(IAggregator(divide).latestAnswer());\n }\n\n return price / decimals;\n }\n\n function getDataParameter(address divide, uint256 decimals) public pure returns (bytes memory) {\n return abi.encode(divide, decimals);\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata data) public override returns (bool, uint256) {\n (address divide, uint256 decimals) = abi.decode(data, (address, uint256));\n return (true, _get(divide, decimals));\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata data) public view override returns (bool, uint256) {\n (address divide, uint256 decimals) = abi.decode(data, (address, uint256));\n return (true, _get(divide, decimals));\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"xSUSHI Chainlink\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"xSUSHI-LINK\";\n }\n}\n" + }, + "contracts/interfaces/IOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface IOracle {\n /// @notice Get the latest exchange rate.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return success if no valid (recent) rate is available, return false else true.\n /// @return rate The rate of the requested asset / pair / pool.\n function get(bytes calldata data) external returns (bool success, uint256 rate);\n\n /// @notice Check the last exchange rate without any state changes.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return success if no valid (recent) rate is available, return false else true.\n /// @return rate The rate of the requested asset / pair / pool.\n function peek(bytes calldata data) external view returns (bool success, uint256 rate);\n\n /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return rate The rate of the requested asset / pair / pool.\n function peekSpot(bytes calldata data) external view returns (uint256 rate);\n\n /// @notice Returns a human readable (short) name about this oracle.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return (string) A human readable symbol name about this oracle.\n function symbol(bytes calldata data) external view returns (string memory);\n\n /// @notice Returns a human readable name about this oracle.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return (string) A human readable name about this oracle.\n function name(bytes calldata data) external view returns (string memory);\n}\n" + }, + "contracts/oracles/xBooOracle.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n// Using the same Copyleft License as in the original Repository\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"../interfaces/IOracle.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../libraries/FixedPoint.sol\";\n\nimport \"hardhat/console.sol\";\n\n// solhint-disable not-rely-on-time\n\n// adapted from https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/examples/ExampleSlidingWindowOracle.sol\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ncontract xBooOracle is IOracle {\n using FixedPoint for *;\n using BoringMath for uint256;\n uint256 public constant PERIOD = 10 minutes;\n IAggregator public constant FTM_USD = IAggregator(0xf4766552D15AE4d256Ad41B6cf2933482B0680dc);\n IUniswapV2Pair public constant BOO_FTM = IUniswapV2Pair(0xEc7178F4C41f346b2721907F5cF7628E388A7a58);\n IERC20 public constant BOO = IERC20(0x841FAD6EAe12c286d1Fd18d1d525DFfA75C7EFFE);\n IERC20 public constant XBOO = IERC20(0xa48d959AE2E88f1dAA7D5F611E01908106dE7598);\n\n struct PairInfo {\n uint256 priceCumulativeLast;\n uint32 blockTimestampLast;\n uint144 priceAverage;\n }\n\n PairInfo public pairInfo;\n function _get(uint32 blockTimestamp) public view returns (uint256) {\n uint256 priceCumulative = BOO_FTM.price1CumulativeLast();\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(BOO_FTM).getReserves();\n priceCumulative += uint256(FixedPoint.fraction(reserve0, reserve1)._x) * (blockTimestamp - blockTimestampLast); // overflows ok\n\n // overflow is desired, casting never truncates\n // cumulative price is in (uq112x112 price * seconds) units so we simply wrap it after division by time elapsed\n return priceCumulative;\n }\n\n function toXBOO(uint256 amount) internal view returns (uint256) {\n return amount.mul(BOO.balanceOf(address(XBOO))) / XBOO.totalSupply();\n }\n\n // Get the latest exchange rate, if no valid (recent) rate is available, return false\n /// @inheritdoc IOracle\n function get(bytes calldata) external override returns (bool, uint256) {\n uint32 blockTimestamp = uint32(block.timestamp);\n if (pairInfo.blockTimestampLast == 0) {\n pairInfo.blockTimestampLast = blockTimestamp;\n pairInfo.priceCumulativeLast = _get(blockTimestamp);\n return (false, 0);\n }\n uint32 timeElapsed = blockTimestamp - pairInfo.blockTimestampLast; // overflow is desired\n console.log(timeElapsed);\n if (timeElapsed < PERIOD) {\n return (true, pairInfo.priceAverage);\n }\n\n uint256 priceCumulative = _get(blockTimestamp);\n pairInfo.priceAverage = uint144(1e44 / toXBOO(uint256(FixedPoint\n .uq112x112(uint224((priceCumulative - pairInfo.priceCumulativeLast) / timeElapsed))\n .mul(1e18)\n .decode144())).mul(uint256(FTM_USD.latestAnswer())));\n pairInfo.blockTimestampLast = blockTimestamp;\n pairInfo.priceCumulativeLast = priceCumulative;\n\n return (true, pairInfo.priceAverage);\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n uint32 blockTimestamp = uint32(block.timestamp);\n if (pairInfo.blockTimestampLast == 0) {\n return (false, 0);\n }\n uint32 timeElapsed = blockTimestamp - pairInfo.blockTimestampLast; // overflow is desired\n if (timeElapsed < PERIOD) {\n return (true, pairInfo.priceAverage);\n }\n\n uint256 priceCumulative = _get(blockTimestamp);\n uint144 priceAverage = uint144(1e44 / toXBOO(uint256(FixedPoint\n .uq112x112(uint224((priceCumulative - pairInfo.priceCumulativeLast) / timeElapsed))\n .mul(1e18)\n .decode144())).mul(uint256(FTM_USD.latestAnswer())));\n\n return (true, priceAverage);\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata) external view override returns (uint256 rate) {\n (uint256 reserve0, uint256 reserve1, ) = BOO_FTM.getReserves();\n rate = 1e44 / toXBOO(reserve0.mul(1e18) / reserve1).mul(uint256(FTM_USD.latestAnswer()));\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"xBOO TWAP\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"xBOO\";\n }\n}\n" + }, + "contracts/libraries/FixedPoint.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.6.12;\nimport \"./FullMath_v06_12.sol\";\n\n// solhint-disable\n\n// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))\nlibrary FixedPoint {\n // range: [0, 2**112 - 1]\n // resolution: 1 / 2**112\n struct uq112x112 {\n uint224 _x;\n }\n\n // range: [0, 2**144 - 1]\n // resolution: 1 / 2**112\n struct uq144x112 {\n uint256 _x;\n }\n\n uint8 private constant RESOLUTION = 112;\n uint256 private constant Q112 = 0x10000000000000000000000000000;\n uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000;\n uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits)\n\n // decode a UQ144x112 into a uint144 by truncating after the radix point\n function decode144(uq144x112 memory self) internal pure returns (uint144) {\n return uint144(self._x >> RESOLUTION);\n }\n\n // multiply a UQ112x112 by a uint256, returning a UQ144x112\n // reverts on overflow\n function mul(uq112x112 memory self, uint256 y) internal pure returns (uq144x112 memory) {\n uint256 z = 0;\n require(y == 0 || (z = self._x * y) / y == self._x, \"FixedPoint::mul: overflow\");\n return uq144x112(z);\n }\n\n // returns a UQ112x112 which represents the ratio of the numerator to the denominator\n // lossy if either numerator or denominator is greater than 112 bits\n function fraction(uint256 numerator, uint256 denominator) internal pure returns (uq112x112 memory) {\n require(denominator > 0, \"FixedPoint::fraction: div by 0\");\n if (numerator == 0) return FixedPoint.uq112x112(0);\n\n if (numerator <= uint144(-1)) {\n uint256 result = (numerator << RESOLUTION) / denominator;\n require(result <= uint224(-1), \"FixedPoint::fraction: overflow\");\n return uq112x112(uint224(result));\n } else {\n uint256 result = FullMath.mulDiv(numerator, Q112, denominator);\n require(result <= uint224(-1), \"FixedPoint::fraction: overflow\");\n return uq112x112(uint224(result));\n }\n }\n}\n" + }, + "hardhat/console.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >= 0.4.22 <0.9.0;\n\nlibrary console {\n\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n\tfunction _sendLogPayload(bytes memory payload) private view {\n\t\tuint256 payloadLength = payload.length;\n\t\taddress consoleAddress = CONSOLE_ADDRESS;\n\t\tassembly {\n\t\t\tlet payloadStart := add(payload, 32)\n\t\t\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n\t\t}\n\t}\n\n\tfunction log() internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log()\"));\n\t}\n\n\tfunction logInt(int p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n\t}\n\n\tfunction logUint(uint p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n\t}\n\n\tfunction logString(string memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n\t}\n\n\tfunction logBool(bool p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n\t}\n\n\tfunction logAddress(address p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n\t}\n\n\tfunction logBytes(bytes memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n\t}\n\n\tfunction logBytes1(bytes1 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n\t}\n\n\tfunction logBytes2(bytes2 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n\t}\n\n\tfunction logBytes3(bytes3 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n\t}\n\n\tfunction logBytes4(bytes4 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n\t}\n\n\tfunction logBytes5(bytes5 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n\t}\n\n\tfunction logBytes6(bytes6 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n\t}\n\n\tfunction logBytes7(bytes7 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n\t}\n\n\tfunction logBytes8(bytes8 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n\t}\n\n\tfunction logBytes9(bytes9 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n\t}\n\n\tfunction logBytes10(bytes10 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n\t}\n\n\tfunction logBytes11(bytes11 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n\t}\n\n\tfunction logBytes12(bytes12 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n\t}\n\n\tfunction logBytes13(bytes13 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n\t}\n\n\tfunction logBytes14(bytes14 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n\t}\n\n\tfunction logBytes15(bytes15 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n\t}\n\n\tfunction logBytes16(bytes16 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n\t}\n\n\tfunction logBytes17(bytes17 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n\t}\n\n\tfunction logBytes18(bytes18 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n\t}\n\n\tfunction logBytes19(bytes19 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n\t}\n\n\tfunction logBytes20(bytes20 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n\t}\n\n\tfunction logBytes21(bytes21 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n\t}\n\n\tfunction logBytes22(bytes22 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n\t}\n\n\tfunction logBytes23(bytes23 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n\t}\n\n\tfunction logBytes24(bytes24 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n\t}\n\n\tfunction logBytes25(bytes25 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n\t}\n\n\tfunction logBytes26(bytes26 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n\t}\n\n\tfunction logBytes27(bytes27 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n\t}\n\n\tfunction logBytes28(bytes28 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n\t}\n\n\tfunction logBytes29(bytes29 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n\t}\n\n\tfunction logBytes30(bytes30 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n\t}\n\n\tfunction logBytes31(bytes31 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n\t}\n\n\tfunction logBytes32(bytes32 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n\t}\n\n\tfunction log(uint p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n\t}\n\n\tfunction log(string memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n\t}\n\n\tfunction log(bool p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n\t}\n\n\tfunction log(address p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n\t}\n\n\tfunction log(uint p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n\t}\n\n\tfunction log(address p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n\t}\n\n\tfunction log(address p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n\t}\n\n\tfunction log(address p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n\t}\n\n\tfunction log(address p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n}\n" + }, + "contracts/libraries/FullMath_v06_12.sol": { + "content": "// SPDX-License-Identifier: CC-BY-4.0\npragma solidity 0.6.12;\n\n// solhint-disable\n\n// taken from https://medium.com/coinmonks/math-in-solidity-part-3-percents-and-proportions-4db014e080b1\n// license is CC-BY-4.0\nlibrary FullMath {\n function fullMul(uint256 x, uint256 y) private pure returns (uint256 l, uint256 h) {\n uint256 mm = mulmod(x, y, uint256(-1));\n l = x * y;\n h = mm - l;\n if (mm < l) h -= 1;\n }\n\n function fullDiv(\n uint256 l,\n uint256 h,\n uint256 d\n ) private pure returns (uint256) {\n uint256 pow2 = d & -d;\n d /= pow2;\n l /= pow2;\n l += h * ((-pow2) / pow2 + 1);\n uint256 r = 1;\n r *= 2 - d * r;\n r *= 2 - d * r;\n r *= 2 - d * r;\n r *= 2 - d * r;\n r *= 2 - d * r;\n r *= 2 - d * r;\n r *= 2 - d * r;\n r *= 2 - d * r;\n return l * r;\n }\n\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 d\n ) internal pure returns (uint256) {\n (uint256 l, uint256 h) = fullMul(x, y);\n uint256 mm = mulmod(x, y, d);\n if (mm > l) h -= 1;\n l -= mm;\n require(h < d, \"FullMath::mulDiv: overflow\");\n return fullDiv(l, h, d);\n }\n}\n" + }, + "contracts/oracles/ICEOracleFTM.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n// Using the same Copyleft License as in the original Repository\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"../interfaces/IOracle.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../libraries/FixedPoint.sol\";\n\nimport \"hardhat/console.sol\";\n\n// solhint-disable not-rely-on-time\n\n// adapted from https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/examples/ExampleSlidingWindowOracle.sol\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ncontract ICEOracleFTM is IOracle {\n using FixedPoint for *;\n using BoringMath for uint256;\n uint256 public constant PERIOD = 10 minutes;\n IAggregator public constant FTM_USD = IAggregator(0xf4766552D15AE4d256Ad41B6cf2933482B0680dc);\n IUniswapV2Pair public constant ICE_FTM = IUniswapV2Pair(0x84311ECC54D7553378c067282940b0fdfb913675);\n IERC20 public constant ICE = IERC20(0xf16e81dce15B08F326220742020379B855B87DF9);\n\n struct PairInfo {\n uint256 priceCumulativeLast;\n uint32 blockTimestampLast;\n uint144 priceAverage;\n }\n\n PairInfo public pairInfo;\n function _get(uint32 blockTimestamp) public view returns (uint256) {\n uint256 priceCumulative = ICE_FTM.price1CumulativeLast();\n\n // if time has elapsed since the last update on the pair, mock the accumulated price values\n (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(ICE_FTM).getReserves();\n priceCumulative += uint256(FixedPoint.fraction(reserve0, reserve1)._x) * (blockTimestamp - blockTimestampLast); // overflows ok\n\n // overflow is desired, casting never truncates\n // cumulative price is in (uq112x112 price * seconds) units so we simply wrap it after division by time elapsed\n return priceCumulative;\n }\n\n // Get the latest exchange rate, if no valid (recent) rate is available, return false\n /// @inheritdoc IOracle\n function get(bytes calldata) external override returns (bool, uint256) {\n uint32 blockTimestamp = uint32(block.timestamp);\n if (pairInfo.blockTimestampLast == 0) {\n pairInfo.blockTimestampLast = blockTimestamp;\n pairInfo.priceCumulativeLast = _get(blockTimestamp);\n return (false, 0);\n }\n uint32 timeElapsed = blockTimestamp - pairInfo.blockTimestampLast; // overflow is desired\n console.log(timeElapsed);\n if (timeElapsed < PERIOD) {\n return (true, pairInfo.priceAverage);\n }\n\n uint256 priceCumulative = _get(blockTimestamp);\n pairInfo.priceAverage = uint144(1e44 / uint256(FixedPoint\n .uq112x112(uint224((priceCumulative - pairInfo.priceCumulativeLast) / timeElapsed))\n .mul(1e18)\n .decode144()).mul(uint256(FTM_USD.latestAnswer())));\n pairInfo.blockTimestampLast = blockTimestamp;\n pairInfo.priceCumulativeLast = priceCumulative;\n\n return (true, pairInfo.priceAverage);\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n uint32 blockTimestamp = uint32(block.timestamp);\n if (pairInfo.blockTimestampLast == 0) {\n return (false, 0);\n }\n uint32 timeElapsed = blockTimestamp - pairInfo.blockTimestampLast; // overflow is desired\n if (timeElapsed < PERIOD) {\n return (true, pairInfo.priceAverage);\n }\n\n uint256 priceCumulative = _get(blockTimestamp);\n uint144 priceAverage = uint144(1e44 / uint256(FixedPoint\n .uq112x112(uint224((priceCumulative - pairInfo.priceCumulativeLast) / timeElapsed))\n .mul(1e18)\n .decode144()).mul(uint256(FTM_USD.latestAnswer())));\n\n return (true, priceAverage);\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata) external view override returns (uint256 rate) {\n (uint256 reserve0, uint256 reserve1, ) = ICE_FTM.getReserves();\n rate = 1e44 / (reserve0.mul(1e18) / reserve1).mul(uint256(FTM_USD.latestAnswer()));\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"ICE TWAP\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"ICE\";\n }\n}\n" + }, + "contracts/oracles/wOHMLinkOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../interfaces/IOracle.sol\";\n\n// Chainlink Aggregator\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ninterface IWOHM {\n function sOHMTowOHM(uint256 _amount) external view returns (uint256);\n}\n\ncontract wOHMOracle is IOracle {\n using BoringMath for uint256; // Keep everything in uint256\n\n IAggregator public constant ohmOracle = IAggregator(0x90c2098473852E2F07678Fe1B6d595b1bd9b16Ed);\n IAggregator public constant ethUSDOracle = IAggregator(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);\n IWOHM public constant WOHM = IWOHM(0xCa76543Cf381ebBB277bE79574059e32108e3E65);\n\n // Calculates the lastest exchange rate\n // Uses both divide and multiply only for tokens not supported directly by Chainlink, for example MKR/USD\n function _get() internal view returns (uint256) {\n return\n 1e44 / (uint256(1e18).mul(uint256(ohmOracle.latestAnswer()).mul(uint256(ethUSDOracle.latestAnswer()))) / WOHM.sOHMTowOHM(1e9));\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata) public override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"wOHM Chainlink\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"LINK/wOHM\";\n }\n}\n" + }, + "contracts/oracles/ProxyOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../interfaces/IOracle.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\n\n/// @title ProxyOracle\n/// @author 0xMerlin\n/// @notice Oracle used for getting the price of an oracle implementation\ncontract ProxyOracle is IOracle, BoringOwnable {\n IOracle public oracleImplementation;\n\n event LogOracleImplementationChange(IOracle indexed oldOracle, IOracle indexed newOracle);\n\n constructor() public {}\n\n function changeOracleImplementation(IOracle newOracle) external onlyOwner {\n IOracle oldOracle = oracleImplementation;\n oracleImplementation = newOracle;\n emit LogOracleImplementationChange(oldOracle, newOracle);\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata data) public override returns (bool, uint256) {\n return oracleImplementation.get(data);\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata data) public view override returns (bool, uint256) {\n return oracleImplementation.peek(data);\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n return oracleImplementation.peekSpot(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"Proxy Oracle\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"Proxy\";\n }\n}\n" + }, + "contracts/oracles/PeggedOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"../interfaces/IOracle.sol\";\n\n/// @title PeggedOracle\n/// @author BoringCrypto\n/// @notice Oracle used for pegged prices that don't change\n/// @dev\ncontract PeggedOracle is IOracle {\n /// @notice\n /// @dev\n /// @param rate (uint256) The fixed exchange rate\n /// @return (bytes)\n function getDataParameter(uint256 rate) public pure returns (bytes memory) {\n return abi.encode(rate);\n }\n\n // Get the exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata data) public override returns (bool, uint256) {\n uint256 rate = abi.decode(data, (uint256));\n return (rate != 0, rate);\n }\n\n // Check the exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata data) public view override returns (bool, uint256) {\n uint256 rate = abi.decode(data, (uint256));\n return (rate != 0, rate);\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"Pegged\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"PEG\";\n }\n}\n" + }, + "contracts/oracles/dQuickOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"../interfaces/IOracle.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\n/// @title xSUSHIOracle\n/// @author BoringCrypto\n/// @notice Oracle used for getting the price of xSUSHI based on Chainlink\n/// @dev\ncontract xSUSHIOracle is IOracle {\n using BoringMath for uint256; // Keep everything in uint256\n\n IERC20 public immutable sushi;\n IERC20 public immutable bar;\n IAggregator public immutable sushiOracle;\n\n constructor(\n IERC20 sushi_,\n IERC20 bar_,\n IAggregator sushiOracle_\n ) public {\n sushi = sushi_;\n bar = bar_;\n sushiOracle = sushiOracle_;\n }\n\n // Calculates the lastest exchange rate\n // Uses sushi rate and xSUSHI conversion and divide for any conversion other than from SUSHI to ETH\n function _get(address divide, uint256 decimals) internal view returns (uint256) {\n uint256 price = uint256(1e36);\n price = (price.mul(uint256(sushiOracle.latestAnswer())) / bar.totalSupply()).mul(sushi.balanceOf(address(bar)));\n\n if (divide != address(0)) {\n price = price / uint256(IAggregator(divide).latestAnswer());\n }\n\n return price / decimals;\n }\n\n function getDataParameter(address divide, uint256 decimals) public pure returns (bytes memory) {\n return abi.encode(divide, decimals);\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata data) public override returns (bool, uint256) {\n (address divide, uint256 decimals) = abi.decode(data, (address, uint256));\n return (true, _get(divide, decimals));\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata data) public view override returns (bool, uint256) {\n (address divide, uint256 decimals) = abi.decode(data, (address, uint256));\n return (true, _get(divide, decimals));\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"xSUSHI Chainlink\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"xSUSHI-LINK\";\n }\n}\n" + }, + "contracts/oracles/CompoundOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../interfaces/IOracle.sol\";\n\ninterface IUniswapAnchoredView {\n function price(string memory symbol) external view returns (uint256);\n}\n\ncontract CompoundOracle is IOracle {\n using BoringMath for uint256;\n\n IUniswapAnchoredView private constant ORACLE = IUniswapAnchoredView(0x922018674c12a7F0D394ebEEf9B58F186CdE13c1);\n\n struct PriceInfo {\n uint128 price;\n uint128 blockNumber;\n }\n\n mapping(string => PriceInfo) public prices;\n\n function _peekPrice(string memory symbol) internal view returns (uint256) {\n if (bytes(symbol).length == 0) {\n return 1000000;\n } // To allow only using collateralSymbol or assetSymbol if paired against USDx\n PriceInfo memory info = prices[symbol];\n if (block.number > info.blockNumber + 8) {\n return uint128(ORACLE.price(symbol)); // Prices are denominated with 6 decimals, so will fit in uint128\n }\n return info.price;\n }\n\n function _getPrice(string memory symbol) internal returns (uint256) {\n if (bytes(symbol).length == 0) {\n return 1000000;\n } // To allow only using collateralSymbol or assetSymbol if paired against USDx\n PriceInfo memory info = prices[symbol];\n if (block.number > info.blockNumber + 8) {\n info.price = uint128(ORACLE.price(symbol)); // Prices are denominated with 6 decimals, so will fit in uint128\n info.blockNumber = uint128(block.number); // Blocknumber will fit in uint128\n prices[symbol] = info;\n }\n return info.price;\n }\n\n function getDataParameter(\n string memory collateralSymbol,\n string memory assetSymbol,\n uint256 division\n ) public pure returns (bytes memory) {\n return abi.encode(collateralSymbol, assetSymbol, division);\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata data) public override returns (bool, uint256) {\n (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n return (true, uint256(1e36).mul(_getPrice(assetSymbol)) / _getPrice(collateralSymbol) / division);\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata data) public view override returns (bool, uint256) {\n (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n return (true, uint256(1e36).mul(_peekPrice(assetSymbol)) / _peekPrice(collateralSymbol) / division);\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"Compound\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"COMP\";\n }\n}\n" + }, + "contracts/oracles/CompositeOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\n// Using the same Copyleft License as in the original Repository\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../interfaces/IOracle.sol\";\n\ncontract CompositeOracle is IOracle {\n using BoringMath for uint256;\n\n function getDataParameter(\n IOracle oracle1,\n IOracle oracle2,\n bytes memory data1,\n bytes memory data2\n ) public pure returns (bytes memory) {\n return abi.encode(oracle1, oracle2, data1, data2);\n }\n\n // Get the latest exchange rate, if no valid (recent) rate is available, return false\n /// @inheritdoc IOracle\n function get(bytes calldata data) external override returns (bool, uint256) {\n (IOracle oracle1, IOracle oracle2, bytes memory data1, bytes memory data2) = abi.decode(data, (IOracle, IOracle, bytes, bytes));\n (bool success1, uint256 price1) = oracle1.get(data1);\n (bool success2, uint256 price2) = oracle2.get(data2);\n return (success1 && success2, price1.mul(price2) / 10**18);\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata data) public view override returns (bool, uint256) {\n (IOracle oracle1, IOracle oracle2, bytes memory data1, bytes memory data2) = abi.decode(data, (IOracle, IOracle, bytes, bytes));\n (bool success1, uint256 price1) = oracle1.peek(data1);\n (bool success2, uint256 price2) = oracle2.peek(data2);\n return (success1 && success2, price1.mul(price2) / 10**18);\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (IOracle oracle1, IOracle oracle2, bytes memory data1, bytes memory data2) = abi.decode(data, (IOracle, IOracle, bytes, bytes));\n uint256 price1 = oracle1.peekSpot(data1);\n uint256 price2 = oracle2.peekSpot(data2);\n return price1.mul(price2) / 10**18;\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata data) public view override returns (string memory) {\n (IOracle oracle1, IOracle oracle2, bytes memory data1, bytes memory data2) = abi.decode(data, (IOracle, IOracle, bytes, bytes));\n return string(abi.encodePacked(oracle1.name(data1), \"+\", oracle2.name(data2)));\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata data) public view override returns (string memory) {\n (IOracle oracle1, IOracle oracle2, bytes memory data1, bytes memory data2) = abi.decode(data, (IOracle, IOracle, bytes, bytes));\n return string(abi.encodePacked(oracle1.symbol(data1), \"+\", oracle2.symbol(data2)));\n }\n}\n" + }, + "contracts/oracles/ChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../interfaces/IOracle.sol\";\n\n// Chainlink Aggregator\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ncontract ChainlinkOracle is IOracle {\n using BoringMath for uint256; // Keep everything in uint256\n\n // Calculates the lastest exchange rate\n // Uses both divide and multiply only for tokens not supported directly by Chainlink, for example MKR/USD\n function _get(\n address multiply,\n address divide,\n uint256 decimals\n ) internal view returns (uint256) {\n uint256 price = uint256(1e36);\n if (multiply != address(0)) {\n price = price.mul(uint256(IAggregator(multiply).latestAnswer()));\n } else {\n price = price.mul(1e18);\n }\n\n if (divide != address(0)) {\n price = price / uint256(IAggregator(divide).latestAnswer());\n }\n\n return price / decimals;\n }\n\n function getDataParameter(\n address multiply,\n address divide,\n uint256 decimals\n ) public pure returns (bytes memory) {\n return abi.encode(multiply, divide, decimals);\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata data) public override returns (bool, uint256) {\n (address multiply, address divide, uint256 decimals) = abi.decode(data, (address, address, uint256));\n return (true, _get(multiply, divide, decimals));\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata data) public view override returns (bool, uint256) {\n (address multiply, address divide, uint256 decimals) = abi.decode(data, (address, address, uint256));\n return (true, _get(multiply, divide, decimals));\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"Chainlink\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"LINK\";\n }\n}\n" + }, + "contracts/oracles/BandOracleFTM.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma experimental ABIEncoderV2;\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../interfaces/IOracle.sol\";\n\n// Band\n\ninterface IStdReference {\n /// A structure returned whenever someone requests for standard reference data.\n struct ReferenceData {\n uint256 rate; // base/quote exchange rate, multiplied by 1e18.\n uint256 lastUpdatedBase; // UNIX epoch of the last time when base price gets updated.\n uint256 lastUpdatedQuote; // UNIX epoch of the last time when quote price gets updated.\n }\n\n /// Returns the price data for the given base/quote pair. Revert if not available.\n function getReferenceData(string memory _base, string memory _quote) external view returns (ReferenceData memory);\n\n /// Similar to getReferenceData, but with multiple base/quote pairs at once.\n function getReferenceDataBulk(string[] memory _bases, string[] memory _quotes) external view returns (ReferenceData[] memory);\n}\n\ncontract BandOracleFTMV1 is IOracle {\n using BoringMath for uint256; // Keep everything in uint256\n\n IStdReference constant ftmOracle = IStdReference(0x56E2898E0ceFF0D1222827759B56B28Ad812f92F);\n\n // Calculates the lastest exchange rate\n function _get() internal view returns (uint256 rate) {\n IStdReference.ReferenceData memory referenceData = ftmOracle.getReferenceData(\"USD\", \"FTM\");\n return referenceData.rate;\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata) public override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"BAND FTM/USD\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"BAND\";\n }\n}\n" + }, + "contracts/oracles/AVAXOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../interfaces/IOracle.sol\";\n\n// Chainlink Aggregator\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ncontract AVAXOracle is IOracle {\n using BoringMath for uint256; // Keep everything in uint256\n\n IAggregator public constant avaxOracle = IAggregator(0x0A77230d17318075983913bC2145DB16C7366156);\n\n // Calculates the lastest exchange rate\n // Uses both divide and multiply only for tokens not supported directly by Chainlink, for example MKR/USD\n function _get() internal view returns (uint256) {\n return 1e26 / uint256(avaxOracle.latestAnswer());\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata) public override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"AVAX Chainlink\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"LINK/AVAX\";\n }\n}\n" + }, + "contracts/oracles/ALCXOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../interfaces/IOracle.sol\";\n\n// Chainlink Aggregator\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ncontract ALCXOracle is IOracle {\n using BoringMath for uint256; // Keep everything in uint256\n\n IAggregator public constant alcxOracle = IAggregator(0x194a9AaF2e0b67c35915cD01101585A33Fe25CAa);\n IAggregator public constant ethUSDOracle = IAggregator(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);\n\n // Calculates the lastest exchange rate\n // Uses both divide and multiply only for tokens not supported directly by Chainlink, for example MKR/USD\n function _get() internal view returns (uint256) {\n return 1e44 / uint256(alcxOracle.latestAnswer()).mul(uint256(ethUSDOracle.latestAnswer()));\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata) public override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return \"ALCX Chainlink\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"LINK/ALCX\";\n }\n}\n" + }, + "contracts/mocks/OracleMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../interfaces/IOracle.sol\";\n\n// WARNING: This oracle is only for testing, please use PeggedOracle for a fixed value oracle\ncontract OracleMock is IOracle {\n using BoringMath for uint256;\n\n uint256 public rate;\n bool public success;\n\n constructor() public {\n success = true;\n }\n\n function set(uint256 rate_) public {\n // The rate can be updated.\n rate = rate_;\n }\n\n function setSuccess(bool val) public {\n success = val;\n }\n\n function getDataParameter() public pure returns (bytes memory) {\n return abi.encode(\"0x0\");\n }\n\n // Get the latest exchange rate\n function get(bytes calldata) public override returns (bool, uint256) {\n return (success, rate);\n }\n\n // Check the last exchange rate without any state changes\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (success, rate);\n }\n\n function peekSpot(bytes calldata) public view override returns (uint256) {\n return rate;\n }\n\n function name(bytes calldata) public view override returns (string memory) {\n return \"Test\";\n }\n\n function symbol(bytes calldata) public view override returns (string memory) {\n return \"TEST\";\n }\n}\n" + }, + "contracts/interfaces/IKashiPair.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"./IOracle.sol\";\nimport \"./ISwapper.sol\";\n\ninterface IKashiPair {\n event Approval(address indexed _owner, address indexed _spender, uint256 _value);\n event LogAccrue(uint256 accruedAmount, uint256 feeFraction, uint64 rate, uint256 utilization);\n event LogAddAsset(address indexed from, address indexed to, uint256 share, uint256 fraction);\n event LogAddCollateral(address indexed from, address indexed to, uint256 share);\n event LogBorrow(address indexed from, address indexed to, uint256 amount, uint256 part);\n event LogExchangeRate(uint256 rate);\n event LogFeeTo(address indexed newFeeTo);\n event LogRemoveAsset(address indexed from, address indexed to, uint256 share, uint256 fraction);\n event LogRemoveCollateral(address indexed from, address indexed to, uint256 share);\n event LogRepay(address indexed from, address indexed to, uint256 amount, uint256 part);\n event LogWithdrawFees(address indexed feeTo, uint256 feesEarnedFraction);\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n event Transfer(address indexed _from, address indexed _to, uint256 _value);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n function accrue() external;\n\n function accrueInfo()\n external\n view\n returns (\n uint64 interestPerBlock,\n uint64 lastBlockAccrued,\n uint128 feesEarnedFraction\n );\n\n function addAsset(\n address to,\n bool skim,\n uint256 share\n ) external returns (uint256 fraction);\n\n function addCollateral(\n address to,\n bool skim,\n uint256 share\n ) external;\n\n function allowance(address, address) external view returns (uint256);\n\n function approve(address spender, uint256 amount) external returns (bool);\n\n function asset() external view returns (IERC20);\n\n function balanceOf(address) external view returns (uint256);\n\n function bentoBox() external view returns (IBentoBoxV1);\n\n function borrow(address to, uint256 amount) external returns (uint256 part, uint256 share);\n\n function claimOwnership() external;\n\n function collateral() external view returns (IERC20);\n\n function cook(\n uint8[] calldata actions,\n uint256[] calldata values,\n bytes[] calldata datas\n ) external payable returns (uint256 value1, uint256 value2);\n\n function decimals() external view returns (uint8);\n\n function exchangeRate() external view returns (uint256);\n\n function feeTo() external view returns (address);\n\n function getInitData(\n IERC20 collateral_,\n IERC20 asset_,\n IOracle oracle_,\n bytes calldata oracleData_\n ) external pure returns (bytes memory data);\n\n function init(bytes calldata data) external payable;\n\n function isSolvent(address user, bool open) external view returns (bool);\n\n function liquidate(\n address[] calldata users,\n uint256[] calldata borrowParts,\n address to,\n ISwapper swapper,\n bool open\n ) external;\n\n function masterContract() external view returns (address);\n\n function name() external view returns (string memory);\n\n function nonces(address) external view returns (uint256);\n\n function oracle() external view returns (IOracle);\n\n function oracleData() external view returns (bytes memory);\n\n function owner() external view returns (address);\n\n function pendingOwner() external view returns (address);\n\n function permit(\n address owner_,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function removeAsset(address to, uint256 fraction) external returns (uint256 share);\n\n function removeCollateral(address to, uint256 share) external;\n\n function repay(\n address to,\n bool skim,\n uint256 part\n ) external returns (uint256 amount);\n\n function setFeeTo(address newFeeTo) external;\n\n function setSwapper(ISwapper swapper, bool enable) external;\n\n function swappers(ISwapper) external view returns (bool);\n\n function symbol() external view returns (string memory);\n\n function totalAsset() external view returns (uint128 elastic, uint128 base);\n\n function totalBorrow() external view returns (uint128 elastic, uint128 base);\n\n function totalCollateralShare() external view returns (uint256);\n\n function totalSupply() external view returns (uint256);\n\n function transfer(address to, uint256 amount) external returns (bool);\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n\n function transferOwnership(\n address newOwner,\n bool direct,\n bool renounce\n ) external;\n\n function updateExchangeRate() external returns (bool updated, uint256 rate);\n\n function userBorrowPart(address) external view returns (uint256);\n\n function userCollateralShare(address) external view returns (uint256);\n\n function withdrawFees() external;\n}\n" + }, + "contracts/mocks/SimpleStrategyMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@sushiswap/bentobox-sdk/contracts/IStrategy.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\n\n// solhint-disable not-rely-on-time\n\ncontract SimpleStrategyMock is IStrategy {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n IERC20 private immutable token;\n address private immutable bentoBox;\n\n modifier onlyBentoBox() {\n require(msg.sender == bentoBox, \"Ownable: caller is not the owner\");\n _;\n }\n\n constructor(address bentoBox_, IERC20 token_) public {\n bentoBox = bentoBox_;\n token = token_;\n }\n\n // Send the assets to the Strategy and call skim to invest them\n function skim(uint256) external override onlyBentoBox {\n // Leave the tokens on the contract\n return;\n }\n\n // Harvest any profits made converted to the asset and pass them to the caller\n function harvest(uint256 balance, address) external override onlyBentoBox returns (int256 amountAdded) {\n amountAdded = int256(token.balanceOf(address(this)).sub(balance));\n token.safeTransfer(bentoBox, uint256(amountAdded)); // Add as profit\n }\n\n // Withdraw assets. The returned amount can differ from the requested amount due to rounding or if the request was more than there is.\n function withdraw(uint256 amount) external override onlyBentoBox returns (uint256 actualAmount) {\n token.safeTransfer(bentoBox, uint256(amount)); // Add as profit\n actualAmount = amount;\n }\n\n // Withdraw all assets in the safest way possible. This shouldn't fail.\n function exit(uint256 balance) external override onlyBentoBox returns (int256 amountAdded) {\n amountAdded = 0;\n token.safeTransfer(bentoBox, balance);\n }\n}\n" + }, + "contracts/helpers/YearnLiquidityMigrationHelper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface IYearnVault {\n function deposit(uint256 amount, address recipient) external returns (uint256 shares);\n}\n\ncontract YearnLiquidityMigrationHelper {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n\n constructor(IBentoBoxV1 bentoBox_) public {\n bentoBox = bentoBox_;\n }\n\n function migrate(\n IERC20 token,\n IYearnVault vault,\n uint256 amount,\n address recipient\n ) external {\n token.approve(address(vault), amount);\n uint256 shares = vault.deposit(amount, address(bentoBox));\n bentoBox.deposit(token, address(bentoBox), recipient, shares, 0);\n }\n}\n" + }, + "contracts/mocks/ERC20Mock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/ERC20.sol\";\n\ncontract ERC20Mock is ERC20 {\n uint256 public override totalSupply;\n string public symbol;\n string public name;\n uint8 public decimals;\n\n constructor(uint256 _initialAmount) public {\n // Give the creator all initial tokens\n balanceOf[msg.sender] = _initialAmount;\n // Update total supply\n totalSupply = _initialAmount;\n }\n}\n" + }, + "contracts/MagicInternetGold.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// Magic Internet Money\n\n// ███╗ ███╗██╗ ██████╗ \n// ████╗ ████║██║██╔════╝ \n// ██╔████╔██║██║██║ ███╗\n// ██║╚██╔╝██║██║██║ ██║\n// ██║ ╚═╝ ██║██║╚██████╔╝\n// ╚═╝ ╚═╝╚═╝ ╚═════╝ \n \n\n// BoringCrypto, 0xMerlin\n\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/ERC20.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\n\n/// @title Magic Internet Gold\ncontract MagicInternetGold is ERC20, BoringOwnable {\n using BoringMath for uint256;\n // ERC20 'variables'\n string public constant symbol = \"MIG\";\n string public constant name = \"Magic Internet Gold\";\n uint8 public constant decimals = 18;\n uint256 public override totalSupply;\n\n struct Minting {\n uint128 time;\n uint128 amount;\n }\n\n Minting public lastMint;\n uint256 private constant MINTING_PERIOD = 24 hours;\n uint256 private constant MINTING_INCREASE = 15000;\n uint256 private constant MINTING_PRECISION = 1e5;\n\n // @notice mint MIG to an address\n // @param to - the recipient\n // @param amount - the amount minted\n function mint(address to, uint256 amount) public onlyOwner {\n require(to != address(0), \"MIG: no mint to zero address\");\n\n // Limits the amount minted per period to a convergence function, with the period duration restarting on every mint\n uint256 totalMintedAmount = uint256(lastMint.time < block.timestamp - MINTING_PERIOD ? 0 : lastMint.amount).add(amount);\n require(totalSupply == 0 || totalSupply.mul(MINTING_INCREASE) / MINTING_PRECISION >= totalMintedAmount);\n\n lastMint.time = block.timestamp.to128();\n lastMint.amount = totalMintedAmount.to128();\n\n totalSupply = totalSupply + amount;\n balanceOf[to] += amount;\n emit Transfer(address(0), to, amount);\n }\n\n // @notice mint MIG to a recipient on BentoBox\n // @param clone - the recipient clone contract\n // @param amount - the amount minted\n // @param bentoBox - the address of the BentoBox / DegenBox selected\n function mintToBentoBox(address clone, uint256 amount, IBentoBoxV1 bentoBox) public onlyOwner {\n mint(address(bentoBox), amount);\n bentoBox.deposit(IERC20(address(this)), address(bentoBox), clone, amount, 0);\n }\n\n // @notice burn MIG from caller\n // @param amount - the amount burnt\n function burn(uint256 amount) public {\n require(amount <= balanceOf[msg.sender], \"MIM: not enough\");\n\n balanceOf[msg.sender] -= amount;\n totalSupply -= amount;\n emit Transfer(msg.sender, address(0), amount);\n }\n}\n" + }, + "contracts/MagicInternetMoney.sol": { + "content": "// SPDX-License-Identifier: MIT\r\n\r\n// Magic Internet Money\r\n\r\n// ███╗ ███╗██╗███╗ ███╗\r\n// ████╗ ████║██║████╗ ████║\r\n// ██╔████╔██║██║██╔████╔██║\r\n// ██║╚██╔╝██║██║██║╚██╔╝██║\r\n// ██║ ╚═╝ ██║██║██║ ╚═╝ ██║\r\n// ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝\r\n\r\n// BoringCrypto, 0xMerlin\r\n\r\npragma solidity 0.6.12;\r\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\r\nimport \"@boringcrypto/boring-solidity/contracts/ERC20.sol\";\r\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\r\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\r\n\r\n/// @title Cauldron\r\n/// @dev This contract allows contract calls to any contract (except BentoBox)\r\n/// from arbitrary callers thus, don't trust calls from this contract in any circumstances.\r\ncontract MagicInternetMoney is ERC20, BoringOwnable {\r\n using BoringMath for uint256;\r\n // ERC20 'variables'\r\n string public constant symbol = \"MIM\";\r\n string public constant name = \"Magic Internet Money\";\r\n uint8 public constant decimals = 18;\r\n uint256 public override totalSupply;\r\n\r\n struct Minting {\r\n uint128 time;\r\n uint128 amount;\r\n }\r\n\r\n Minting public lastMint;\r\n uint256 private constant MINTING_PERIOD = 24 hours;\r\n uint256 private constant MINTING_INCREASE = 15000;\r\n uint256 private constant MINTING_PRECISION = 1e5;\r\n\r\n function mint(address to, uint256 amount) public onlyOwner {\r\n require(to != address(0), \"MIM: no mint to zero address\");\r\n\r\n // Limits the amount minted per period to a convergence function, with the period duration restarting on every mint\r\n uint256 totalMintedAmount = uint256(lastMint.time < block.timestamp - MINTING_PERIOD ? 0 : lastMint.amount).add(amount);\r\n require(totalSupply == 0 || totalSupply.mul(MINTING_INCREASE) / MINTING_PRECISION >= totalMintedAmount);\r\n\r\n lastMint.time = block.timestamp.to128();\r\n lastMint.amount = totalMintedAmount.to128();\r\n\r\n totalSupply = totalSupply + amount;\r\n balanceOf[to] += amount;\r\n emit Transfer(address(0), to, amount);\r\n }\r\n\r\n function mintToBentoBox(address clone, uint256 amount, IBentoBoxV1 bentoBox) public onlyOwner {\r\n mint(address(bentoBox), amount);\r\n bentoBox.deposit(IERC20(address(this)), address(bentoBox), clone, amount, 0);\r\n }\r\n\r\n function burn(uint256 amount) public {\r\n require(amount <= balanceOf[msg.sender], \"MIM: not enough\");\r\n\r\n balanceOf[msg.sender] -= amount;\r\n totalSupply -= amount;\r\n emit Transfer(msg.sender, address(0), amount);\r\n }\r\n}\r\n" + }, + "contracts/MinimalTimeLock.sol": { + "content": "//SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\n\n// Modified from https://etherscan.io/address/0x6d903f6003cca6255d85cca4d3b5e5146dc33925#code and https://github.com/boringcrypto/dictator-dao/blob/main/contracts/DictatorDAO.sol#L225\ncontract MinimalTimeLock is BoringOwnable { \n event QueueTransaction(bytes32 indexed txHash, address indexed target, uint256 value, bytes data, uint256 eta);\n event CancelTransaction(bytes32 indexed txHash, address indexed target, uint256 value, bytes data);\n event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint256 value, bytes data);\n\n uint256 public constant GRACE_PERIOD = 14 days;\n uint256 public constant DELAY = 2 days;\n mapping(bytes32 => uint256) public queuedTransactions;\n\n function queueTransaction(\n address target,\n uint256 value,\n bytes memory data\n ) public onlyOwner returns (bytes32) {\n\n bytes32 txHash = keccak256(abi.encode(target, value, data));\n uint256 eta = block.timestamp + DELAY;\n queuedTransactions[txHash] = eta;\n\n emit QueueTransaction(txHash, target, value, data, eta);\n return txHash;\n }\n\n function cancelTransaction(\n address target,\n uint256 value,\n bytes memory data\n ) public onlyOwner {\n\n bytes32 txHash = keccak256(abi.encode(target, value, data));\n queuedTransactions[txHash] = 0;\n\n emit CancelTransaction(txHash, target, value, data);\n }\n\n function executeTransaction(\n address target,\n uint256 value,\n bytes memory data\n ) public onlyOwner payable returns (bytes memory) {\n\n bytes32 txHash = keccak256(abi.encode(target, value, data));\n uint256 eta = queuedTransactions[txHash];\n require(block.timestamp >= eta, \"Too early\");\n require(block.timestamp <= eta + GRACE_PERIOD, \"Tx stale\");\n\n queuedTransactions[txHash] = 0;\n\n // solium-disable-next-line security/no-call-value\n (bool success, bytes memory returnData) = target.call{value: value}(data);\n require(success, \"Tx reverted :(\");\n\n emit ExecuteTransaction(txHash, target, value, data);\n\n return returnData;\n }\n}" + }, + "contracts/swappers/Liquidations/xBooSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\ninterface IxBOO {\n function leave(uint256 share) external;\n}\n\ninterface IBoo is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\ninterface ICurvePool {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ncontract xBooSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0x74A0BcA2eeEdf8883cb91E37e9ff49430f20a616);\n IUniswapV2Pair constant USDC_WFTM = IUniswapV2Pair(0x2b4C76d0dc16BE1C31D4C1DC53bF9B45987Fc75c);\n IERC20 constant WFTM = IERC20(0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83);\n IERC20 constant USDC = IERC20(0x04068DA6C83AFCFA0e13ba15A6696662335D5B75);\n IxBOO constant xBOO = IxBOO(0xa48d959AE2E88f1dAA7D5F611E01908106dE7598);\n IBoo constant BOO = IBoo(0x841FAD6EAe12c286d1Fd18d1d525DFfA75C7EFFE);\n IUniswapV2Pair constant BOO_FTM = IUniswapV2Pair(0xEc7178F4C41f346b2721907F5cF7628E388A7a58);\n IERC20 public constant MIM = IERC20(0x82f0B8B456c1A451378467398982d4834b6829c1);\n ICurvePool public constant ThreeCrypto = ICurvePool(0x2dd7C9371965472E5A5fD28fbE165007c61439E1);\n\n constructor() public {\n USDC.approve(address(ThreeCrypto), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n {\n (uint256 amountXbooFrom,) = bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n xBOO.leave(amountXbooFrom);\n }\n \n uint256 amountFirst;\n\n {\n uint256 amountFrom = BOO.balanceOf(address(this));\n\n BOO.transfer(address(BOO_FTM), amountFrom);\n \n (address token0, ) = UniswapV2Library.sortTokens(address(BOO), address(WFTM));\n\n (uint256 reserve0, uint256 reserve1, ) = BOO_FTM.getReserves();\n\n (reserve0, reserve1) = address(BOO) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountFirst = getAmountOut(amountFrom, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(BOO) == token0\n ? (uint256(0), amountFirst)\n : (amountFirst, uint256(0));\n\n BOO_FTM.swap(amount0Out, amount1Out, address(USDC_WFTM), new bytes(0));\n\n }\n\n uint256 amountIntermediate;\n\n {\n (address token0, ) = UniswapV2Library.sortTokens(address(WFTM), address(USDC));\n\n (uint256 reserve0, uint256 reserve1, ) = USDC_WFTM.getReserves();\n\n (reserve0, reserve1) = address(WFTM) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountIntermediate = getAmountOut(amountFirst, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(WFTM) == token0\n ? (uint256(0), amountIntermediate)\n : (amountIntermediate, uint256(0));\n\n USDC_WFTM.swap(amount0Out, amount1Out, address(this), new bytes(0));\n }\n\n uint256 amountTo = ThreeCrypto.exchange(2, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/wMEMOSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface IWMEMO is IERC20 {\n function wrap( uint _amount ) external returns ( uint );\n function unwrap( uint _amount ) external returns ( uint );\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\ninterface ITIME is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\ninterface IStakingManager {\n function unstake( uint _amount, bool _trigger ) external;\n function stake( uint _amount, address _recipient ) external returns ( bool );\n}\n\ncontract wMEMOSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xf4F46382C2bE1603Dc817551Ff9A7b333Ed1D18f);\n IUniswapV2Pair constant WMEMO_MIM = IUniswapV2Pair(0x4d308C46EA9f234ea515cC51F16fba776451cac8);\n IERC20 public constant MIM = IERC20(0x130966628846BFd36ff31a822705796e8cb8C18D);\n IERC20 public constant MEMO = IERC20(0x136Acd46C134E8269052c62A67042D6bDeDde3C9);\n IWMEMO public constant WMEMO = IWMEMO(0x0da67235dD5787D67955420C84ca1cEcd4E5Bb3b);\n IStakingManager public constant STAKING_MANAGER = IStakingManager(0x4456B87Af11e87E329AB7d7C7A246ed1aC2168B9);\n ITIME public constant TIME = ITIME(0xb54f16fB19478766A268F172C9480f8da1a7c9C3);\n address private constant WAVAX = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n\n constructor(\n ) public {\n MEMO.approve(address(STAKING_MANAGER), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an outpxut amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n \n (uint256 amountFrom, ) = bentoBox.withdraw(fromToken, address(this), address(WMEMO_MIM), 0, shareFrom);\n\n (address token0, ) = UniswapV2Library.sortTokens(address(WMEMO), address(WMEMO_MIM));\n\n (uint256 reserve0, uint256 reserve1, ) = WMEMO_MIM.getReserves();\n\n (reserve0, reserve1) = address(WMEMO) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n uint256 amountTo = getAmountOut(amountFrom, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(WMEMO) == token0\n ? (uint256(0), amountTo)\n : (amountTo, uint256(0));\n\n WMEMO_MIM.swap(amount0Out, amount1Out, address(bentoBox), new bytes(0));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}" + }, + "contracts/swappers/Liquidations/ICESwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\n\ninterface CurvePool {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ncontract ICESwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n\n IERC20 public constant WFTM = IERC20(0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83);\n IUniswapV2Pair public constant ICE_FTM = IUniswapV2Pair(0x84311ECC54D7553378c067282940b0fdfb913675);\n IUniswapV2Pair public constant USDC_FTM = IUniswapV2Pair(0x2b4C76d0dc16BE1C31D4C1DC53bF9B45987Fc75c);\n IERC20 public constant ICE = IERC20(0xf16e81dce15B08F326220742020379B855B87DF9);\n IERC20 public constant USDC = IERC20(0x04068DA6C83AFCFA0e13ba15A6696662335D5B75);\n IERC20 public constant MIM = IERC20(0x82f0B8B456c1A451378467398982d4834b6829c1);\n CurvePool public constant threePool = CurvePool(0x2dd7C9371965472E5A5fD28fbE165007c61439E1);\n\n uint8 private constant USDC_COIN = 2;\n uint8 private constant MIM_COIN = 0;\n\n constructor(\n ) public {\n USDC.approve(address(threePool), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n \n\n (uint256 amountFrom, ) = bentoBox.withdraw(ICE, address(this), address(ICE_FTM), 0, shareFrom);\n\n uint256 amountIntermediate;\n\n {\n\n (address token0, ) = UniswapV2Library.sortTokens(address(ICE), address(WFTM));\n\n (uint256 reserve0, uint256 reserve1, ) = ICE_FTM.getReserves();\n\n (reserve0, reserve1) = address(ICE) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountIntermediate = getAmountOut(amountFrom, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(ICE) == token0\n ? (uint256(0), amountIntermediate)\n : (amountIntermediate, uint256(0));\n\n ICE_FTM.swap(amount0Out, amount1Out, address(USDC_FTM), new bytes(0));\n }\n\n uint256 amountIntermediate2;\n\n {\n\n (address token0, ) = UniswapV2Library.sortTokens(address(USDC), address(WFTM));\n\n (uint256 reserve0, uint256 reserve1, ) = USDC_FTM.getReserves();\n\n (reserve0, reserve1) = address(WFTM) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountIntermediate2 = getAmountOut(amountIntermediate, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(WFTM) == token0\n ? (uint256(0), amountIntermediate2)\n : (amountIntermediate2, uint256(0));\n\n USDC_FTM.swap(amount0Out, amount1Out, address(this), new bytes(0));\n }\n\n uint256 amountTo = threePool.exchange(USDC_COIN, MIM_COIN, amountIntermediate2, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(MIM, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}" + }, + "contracts/swappers/Liquidations/FTMDegenSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\ninterface ICurvePool {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ncontract FTMDegenSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0x74A0BcA2eeEdf8883cb91E37e9ff49430f20a616);\n IUniswapV2Pair constant USDC_WFTM = IUniswapV2Pair(0x2b4C76d0dc16BE1C31D4C1DC53bF9B45987Fc75c);\n IERC20 constant WFTM = IERC20(0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83);\n IERC20 constant USDC = IERC20(0x04068DA6C83AFCFA0e13ba15A6696662335D5B75);\n IERC20 public constant MIM = IERC20(0x82f0B8B456c1A451378467398982d4834b6829c1);\n ICurvePool public constant ThreeCrypto = ICurvePool(0x2dd7C9371965472E5A5fD28fbE165007c61439E1);\n\n constructor() public {\n USDC.approve(address(ThreeCrypto), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom,) = bentoBox.withdraw(fromToken, address(this), address(USDC_WFTM), 0, shareFrom);\n\n uint256 amountFirst;\n\n {\n (address token0, ) = UniswapV2Library.sortTokens(address(WFTM), address(USDC));\n\n (uint256 reserve0, uint256 reserve1, ) = USDC_WFTM.getReserves();\n\n (reserve0, reserve1) = address(WFTM) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountFirst = getAmountOut(amountFrom, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(WFTM) == token0\n ? (uint256(0), amountFirst)\n : (amountFirst, uint256(0));\n\n USDC_WFTM.swap(amount0Out, amount1Out, address(this), new bytes(0));\n }\n\n uint256 amountTo = ThreeCrypto.exchange(2, 0, amountFirst, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/ArbEthSwapper.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\n\ncontract ArbEthSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0x74c764D41B77DBbb4fe771daB1939B00b146894A);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0xb6DD51D5425861C808Fd60827Ab6CFBfFE604959);\n IERC20 constant WETH = IERC20(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1);\n IERC20 public constant MIM = IERC20(0xFEa7a6a0B346362BF88A9e4A88416B77a57D6c2A);\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom,) = bentoBox.withdraw(fromToken, address(this), address(pair), 0, shareFrom);\n\n (address token0, ) = UniswapV2Library.sortTokens(address(MIM), address(WETH));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n\n (reserve0, reserve1) = address(WETH) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n uint256 amountTo = getAmountOut(amountFrom, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(WETH) == token0\n ? (uint256(0), amountTo)\n : (amountTo, uint256(0));\n\n pair.swap(amount0Out, amount1Out, address(bentoBox), new bytes(0));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Leverage/xBooLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\ninterface ICurvePool {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface IxBOO is IERC20 {\n function leave(uint256 share) external;\n function enter(uint256 amount) external;\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\ncontract xBooLevSwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0x74A0BcA2eeEdf8883cb91E37e9ff49430f20a616);\n IUniswapV2Pair constant USDC_WFTM = IUniswapV2Pair(0x2b4C76d0dc16BE1C31D4C1DC53bF9B45987Fc75c);\n IERC20 constant WFTM = IERC20(0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83);\n IERC20 constant USDC = IERC20(0x04068DA6C83AFCFA0e13ba15A6696662335D5B75);\n IxBOO constant xBOO = IxBOO(0xa48d959AE2E88f1dAA7D5F611E01908106dE7598);\n IERC20 constant BOO = IERC20(0x841FAD6EAe12c286d1Fd18d1d525DFfA75C7EFFE);\n IUniswapV2Pair constant BOO_FTM = IUniswapV2Pair(0xEc7178F4C41f346b2721907F5cF7628E388A7a58);\n IERC20 public constant MIM = IERC20(0x82f0B8B456c1A451378467398982d4834b6829c1);\n ICurvePool public constant ThreeCrypto = ICurvePool(0x2dd7C9371965472E5A5fD28fbE165007c61439E1);\n\n constructor() public {\n MIM.approve(address(ThreeCrypto), type(uint256).max);\n BOO.approve(address(xBOO), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n \n uint256 amountIntermediate;\n\n {\n uint256 amountFirst = ThreeCrypto.exchange(0, 2, amountFrom, 0, address(USDC_WFTM));\n\n (address token0, ) = UniswapV2Library.sortTokens(address(USDC), address(WFTM));\n\n (uint256 reserve0, uint256 reserve1, ) = USDC_WFTM.getReserves();\n\n (reserve0, reserve1) = address(USDC) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountIntermediate = getAmountOut(amountFirst, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(USDC) == token0\n ? (uint256(0), amountIntermediate)\n : (amountIntermediate, uint256(0));\n\n USDC_WFTM.swap(amount0Out, amount1Out, address(BOO_FTM), new bytes(0));\n }\n uint256 amountIntermediate2;\n\n {\n (address token0, ) = UniswapV2Library.sortTokens(address(BOO), address(WFTM));\n\n (uint256 reserve0, uint256 reserve1, ) = BOO_FTM.getReserves();\n\n (reserve0, reserve1) = address(WFTM) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountIntermediate2 = getAmountOut(amountIntermediate, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(WFTM) == token0\n ? (uint256(0), amountIntermediate2)\n : (amountIntermediate2, uint256(0));\n\n BOO_FTM.swap(amount0Out, amount1Out, address(this), new bytes(0));\n }\n\n xBOO.enter(amountIntermediate2);\n uint256 amountTo = xBOO.balanceOf(address(this));\n xBOO.transfer(address(bentoBox), amountTo);\n\n (, shareReturned) = bentoBox.deposit(xBOO, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/wMemoLevSwapper.sol": { + "content": "\n// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\ninterface IWMEMO is IERC20 {\n function wrap( uint _amount ) external returns ( uint );\n function unwrap( uint _amount ) external returns ( uint );\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\ninterface IStakingManager {\n function unstake( uint _amount, bool _trigger ) external;\n function stake( uint _amount, address _recipient ) external returns ( bool );\n function claim ( address _recipient ) external;\n}\n\ncontract wMEMOLevSwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xf4F46382C2bE1603Dc817551Ff9A7b333Ed1D18f);\n IUniswapV2Pair constant WMEMO_MIM = IUniswapV2Pair(0x4d308C46EA9f234ea515cC51F16fba776451cac8);\n IERC20 public constant MIM = IERC20(0x130966628846BFd36ff31a822705796e8cb8C18D);\n IERC20 public constant MEMO = IERC20(0x136Acd46C134E8269052c62A67042D6bDeDde3C9);\n IWMEMO public constant WMEMO = IWMEMO(0x0da67235dD5787D67955420C84ca1cEcd4E5Bb3b);\n IStakingManager public constant STAKING_MANAGER = IStakingManager(0x4456B87Af11e87E329AB7d7C7A246ed1aC2168B9);\n IERC20 public constant TIME = IERC20(0xb54f16fB19478766A268F172C9480f8da1a7c9C3);\n address private constant WAVAX = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;\n constructor(\n ) public {\n TIME.approve(address(STAKING_MANAGER), type(uint256).max);\n MEMO.approve(address(WMEMO), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountMIMFrom, ) = bentoBox.withdraw(MIM, address(this), address(WMEMO_MIM), 0, shareFrom);\n\n (address token0, ) = UniswapV2Library.sortTokens(address(WMEMO), address(MIM));\n\n (uint256 reserve0, uint256 reserve1, ) = WMEMO_MIM.getReserves();\n\n (reserve0, reserve1) = address(MIM) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n uint256 amountTo = getAmountOut(amountMIMFrom, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(MIM) == token0\n ? (uint256(0), amountTo)\n : (amountTo, uint256(0));\n\n WMEMO_MIM.swap(amount0Out, amount1Out, address(bentoBox), new bytes(0));\n\n (, shareReturned) = bentoBox.deposit(WMEMO, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n}" + }, + "contracts/swappers/Leverage/ICELevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\ninterface CurvePool {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ncontract ICELevSwapper {\n using BoringMath for uint256;\n \n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n\n IERC20 public constant WFTM = IERC20(0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83);\n IUniswapV2Pair public constant ICE_FTM = IUniswapV2Pair(0x84311ECC54D7553378c067282940b0fdfb913675);\n IUniswapV2Pair public constant USDC_FTM = IUniswapV2Pair(0x2b4C76d0dc16BE1C31D4C1DC53bF9B45987Fc75c);\n IERC20 public constant ICE = IERC20(0xf16e81dce15B08F326220742020379B855B87DF9);\n IERC20 public constant USDC = IERC20(0x04068DA6C83AFCFA0e13ba15A6696662335D5B75);\n IERC20 public constant MIM = IERC20(0x82f0B8B456c1A451378467398982d4834b6829c1);\n CurvePool public constant threePool = CurvePool(0x2dd7C9371965472E5A5fD28fbE165007c61439E1);\n\n uint8 private constant USDC_COIN = 2;\n uint8 private constant MIM_COIN = 0;\n\n constructor(\n ) public {\n MIM.approve(address(threePool), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountIntermediate = threePool.exchange(MIM_COIN, USDC_COIN, amountFrom, 0, address(USDC_FTM));\n\n uint256 amountIntermediate2;\n\n {\n\n (address token0, ) = UniswapV2Library.sortTokens(address(USDC), address(WFTM));\n\n (uint256 reserve0, uint256 reserve1, ) = USDC_FTM.getReserves();\n\n (reserve0, reserve1) = address(USDC) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountIntermediate2 = getAmountOut(amountIntermediate, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(USDC) == token0\n ? (uint256(0), amountIntermediate2)\n : (amountIntermediate2, uint256(0));\n\n USDC_FTM.swap(amount0Out, amount1Out, address(ICE_FTM), new bytes(0));\n }\n\n uint256 amountTo;\n\n {\n\n (address token0, ) = UniswapV2Library.sortTokens(address(ICE), address(WFTM));\n\n (uint256 reserve0, uint256 reserve1, ) = ICE_FTM.getReserves();\n\n (reserve0, reserve1) = address(WFTM) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountTo = getAmountOut(amountIntermediate2, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(WFTM) == token0\n ? (uint256(0), amountTo)\n : (amountTo, uint256(0));\n\n ICE_FTM.swap(amount0Out, amount1Out, address(bentoBox), new bytes(0));\n }\n\n (, shareReturned) = bentoBox.deposit(ICE, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/FTMLevDegenSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\ninterface ICurvePool {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ncontract FTMLevDegenSwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0x74A0BcA2eeEdf8883cb91E37e9ff49430f20a616);\n IUniswapV2Pair constant USDC_WFTM = IUniswapV2Pair(0x2b4C76d0dc16BE1C31D4C1DC53bF9B45987Fc75c);\n IERC20 constant WFTM = IERC20(0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83);\n IERC20 constant USDC = IERC20(0x04068DA6C83AFCFA0e13ba15A6696662335D5B75);\n IERC20 public constant MIM = IERC20(0x82f0B8B456c1A451378467398982d4834b6829c1);\n ICurvePool public constant ThreeCrypto = ICurvePool(0x2dd7C9371965472E5A5fD28fbE165007c61439E1);\n\n constructor() public {\n MIM.approve(address(ThreeCrypto), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n uint256 amountFirst;\n {\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n amountFirst = ThreeCrypto.exchange(0, 2, amountFrom, 0, address(USDC_WFTM));\n }\n\n uint256 amountTo;\n\n {\n (address token0, ) = UniswapV2Library.sortTokens(address(USDC), address(WFTM));\n\n (uint256 reserve0, uint256 reserve1, ) = USDC_WFTM.getReserves();\n\n (reserve0, reserve1) = address(USDC) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n amountTo = getAmountOut(amountFirst, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(USDC) == token0\n ? (uint256(0), amountTo)\n : (amountTo, uint256(0));\n\n USDC_WFTM.swap(amount0Out, amount1Out, address(bentoBox), new bytes(0));\n }\n\n \n\n (, shareReturned) = bentoBox.deposit(WFTM, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/ArbEthLevSwapper.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../libraries/UniswapV2Library.sol\";\n\ncontract ArbEthLevSwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0x74c764D41B77DBbb4fe771daB1939B00b146894A);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0xb6DD51D5425861C808Fd60827Ab6CFBfFE604959);\n IERC20 constant WETH = IERC20(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1);\n IERC20 public constant MIM = IERC20(0xFEa7a6a0B346362BF88A9e4A88416B77a57D6c2A);\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(pair), 0, shareFrom);\n\n (address token0, ) = UniswapV2Library.sortTokens(address(MIM), address(WETH));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n\n (reserve0, reserve1) = address(MIM) == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n \n uint256 amountTo = getAmountOut(amountFrom, reserve0, reserve1);\n\n (uint256 amount0Out, uint256 amount1Out) = address(MIM) == token0\n ? (uint256(0), amountTo)\n : (amountTo, uint256(0));\n\n pair.swap(amount0Out, amount1Out, address(bentoBox), new bytes(0));\n\n (, shareReturned) = bentoBox.deposit(WETH, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/UniswapV2ERC20.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity =0.6.12;\n\nimport './libraries/SafeMath.sol';\n\ncontract UniswapV2ERC20 {\n using SafeMathUniswap for uint;\n\n string public constant name = 'SushiSwap LP Token';\n string public constant symbol = 'SLP';\n uint8 public constant decimals = 18;\n uint public totalSupply;\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bytes32 public DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint) public nonces;\n\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n constructor() public {\n uint chainId;\n assembly {\n chainId := chainid()\n }\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),\n keccak256(bytes(name)),\n keccak256(bytes('1')),\n chainId,\n address(this)\n )\n );\n }\n\n function _mint(address to, uint value) internal {\n totalSupply = totalSupply.add(value);\n balanceOf[to] = balanceOf[to].add(value);\n emit Transfer(address(0), to, value);\n }\n\n function _burn(address from, uint value) internal {\n balanceOf[from] = balanceOf[from].sub(value);\n totalSupply = totalSupply.sub(value);\n emit Transfer(from, address(0), value);\n }\n\n function _approve(address owner, address spender, uint value) private {\n allowance[owner][spender] = value;\n emit Approval(owner, spender, value);\n }\n\n function _transfer(address from, address to, uint value) private {\n balanceOf[from] = balanceOf[from].sub(value);\n balanceOf[to] = balanceOf[to].add(value);\n emit Transfer(from, to, value);\n }\n\n function approve(address spender, uint value) external returns (bool) {\n _approve(msg.sender, spender, value);\n return true;\n }\n\n function transfer(address to, uint value) external returns (bool) {\n _transfer(msg.sender, to, value);\n return true;\n }\n\n function transferFrom(address from, address to, uint value) external returns (bool) {\n if (allowance[from][msg.sender] != uint(-1)) {\n allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);\n }\n _transfer(from, to, value);\n return true;\n }\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {\n require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');\n bytes32 digest = keccak256(\n abi.encodePacked(\n '\\x19\\x01',\n DOMAIN_SEPARATOR,\n keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');\n _approve(owner, spender, value);\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/UniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity =0.6.12;\n\nimport './UniswapV2ERC20.sol';\nimport './libraries/Math.sol';\nimport './libraries/UQ112x112.sol';\nimport './interfaces/IERC20.sol';\nimport './interfaces/IUniswapV2Factory.sol';\nimport './interfaces/IUniswapV2Callee.sol';\n\ninterface IMigrator {\n // Return the desired amount of liquidity token that the migrator wants.\n function desiredLiquidity() external view returns (uint256);\n}\n\ncontract UniswapV2Pair is UniswapV2ERC20 {\n using SafeMathUniswap for uint;\n using UQ112x112 for uint224;\n\n uint public constant MINIMUM_LIQUIDITY = 10**3;\n bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));\n\n address public factory;\n address public token0;\n address public token1;\n\n uint112 private reserve0; // uses single storage slot, accessible via getReserves\n uint112 private reserve1; // uses single storage slot, accessible via getReserves\n uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves\n\n uint public price0CumulativeLast;\n uint public price1CumulativeLast;\n uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event\n\n uint private unlocked = 1;\n modifier lock() {\n require(unlocked == 1, 'UniswapV2: LOCKED');\n unlocked = 0;\n _;\n unlocked = 1;\n }\n\n function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {\n _reserve0 = reserve0;\n _reserve1 = reserve1;\n _blockTimestampLast = blockTimestampLast;\n }\n\n function _safeTransfer(address token, address to, uint value) private {\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED');\n }\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n constructor() public {\n factory = msg.sender;\n }\n\n // called once by the factory at time of deployment\n function initialize(address _token0, address _token1) external {\n require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check\n token0 = _token0;\n token1 = _token1;\n }\n\n // update reserves and, on the first call per block, price accumulators\n function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {\n require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW');\n uint32 blockTimestamp = uint32(block.timestamp % 2**32);\n uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired\n if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {\n // * never overflows, and + overflow is desired\n price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;\n price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;\n }\n reserve0 = uint112(balance0);\n reserve1 = uint112(balance1);\n blockTimestampLast = blockTimestamp;\n emit Sync(reserve0, reserve1);\n }\n\n // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)\n function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) {\n address feeTo = IUniswapV2Factory(factory).feeTo();\n feeOn = feeTo != address(0);\n uint _kLast = kLast; // gas savings\n if (feeOn) {\n if (_kLast != 0) {\n uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1));\n uint rootKLast = Math.sqrt(_kLast);\n if (rootK > rootKLast) {\n uint numerator = totalSupply.mul(rootK.sub(rootKLast));\n uint denominator = rootK.mul(5).add(rootKLast);\n uint liquidity = numerator / denominator;\n if (liquidity > 0) _mint(feeTo, liquidity);\n }\n }\n } else if (_kLast != 0) {\n kLast = 0;\n }\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function mint(address to) external lock returns (uint liquidity) {\n (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings\n uint balance0 = IERC20Uniswap(token0).balanceOf(address(this));\n uint balance1 = IERC20Uniswap(token1).balanceOf(address(this));\n uint amount0 = balance0.sub(_reserve0);\n uint amount1 = balance1.sub(_reserve1);\n\n bool feeOn = _mintFee(_reserve0, _reserve1);\n uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n if (_totalSupply == 0) {\n address migrator = IUniswapV2Factory(factory).migrator();\n if (msg.sender == migrator) {\n liquidity = IMigrator(migrator).desiredLiquidity();\n require(liquidity > 0 && liquidity != uint256(-1), \"Bad desired liquidity\");\n } else {\n require(migrator == address(0), \"Must not have migrator\");\n liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);\n _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens\n }\n } else {\n liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);\n }\n require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED');\n _mint(to, liquidity);\n\n _update(balance0, balance1, _reserve0, _reserve1);\n if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date\n emit Mint(msg.sender, amount0, amount1);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function burn(address to) external lock returns (uint amount0, uint amount1) {\n (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings\n address _token0 = token0; // gas savings\n address _token1 = token1; // gas savings\n uint balance0 = IERC20Uniswap(_token0).balanceOf(address(this));\n uint balance1 = IERC20Uniswap(_token1).balanceOf(address(this));\n uint liquidity = balanceOf[address(this)];\n\n bool feeOn = _mintFee(_reserve0, _reserve1);\n uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee\n amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution\n amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution\n require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED');\n _burn(address(this), liquidity);\n _safeTransfer(_token0, to, amount0);\n _safeTransfer(_token1, to, amount1);\n balance0 = IERC20Uniswap(_token0).balanceOf(address(this));\n balance1 = IERC20Uniswap(_token1).balanceOf(address(this));\n\n _update(balance0, balance1, _reserve0, _reserve1);\n if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date\n emit Burn(msg.sender, amount0, amount1, to);\n }\n\n // this low-level function should be called from a contract which performs important safety checks\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {\n require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');\n (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings\n require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');\n\n uint balance0;\n uint balance1;\n { // scope for _token{0,1}, avoids stack too deep errors\n address _token0 = token0;\n address _token1 = token1;\n require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');\n if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens\n if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens\n if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);\n balance0 = IERC20Uniswap(_token0).balanceOf(address(this));\n balance1 = IERC20Uniswap(_token1).balanceOf(address(this));\n }\n uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;\n uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;\n require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');\n { // scope for reserve{0,1}Adjusted, avoids stack too deep errors\n uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));\n uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));\n require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');\n }\n\n _update(balance0, balance1, _reserve0, _reserve1);\n emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);\n }\n\n // force balances to match reserves\n function skim(address to) external lock {\n address _token0 = token0; // gas savings\n address _token1 = token1; // gas savings\n _safeTransfer(_token0, to, IERC20Uniswap(_token0).balanceOf(address(this)).sub(reserve0));\n _safeTransfer(_token1, to, IERC20Uniswap(_token1).balanceOf(address(this)).sub(reserve1));\n }\n\n // force reserves to match balances\n function sync() external lock {\n _update(IERC20Uniswap(token0).balanceOf(address(this)), IERC20Uniswap(token1).balanceOf(address(this)), reserve0, reserve1);\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/libraries/Math.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity =0.6.12;\n\n// a library for performing various math operations\n\nlibrary Math {\n function min(uint x, uint y) internal pure returns (uint z) {\n z = x < y ? x : y;\n }\n\n // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)\n function sqrt(uint y) internal pure returns (uint z) {\n if (y > 3) {\n z = y;\n uint x = y / 2 + 1;\n while (x < z) {\n z = x;\n x = (y / x + x) / 2;\n }\n } else if (y != 0) {\n z = 1;\n }\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/libraries/UQ112x112.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity =0.6.12;\n\n// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))\n\n// range: [0, 2**112 - 1]\n// resolution: 1 / 2**112\n\nlibrary UQ112x112 {\n uint224 constant Q112 = 2**112;\n\n // encode a uint112 as a UQ112x112\n function encode(uint112 y) internal pure returns (uint224 z) {\n z = uint224(y) * Q112; // never overflows\n }\n\n // divide a UQ112x112 by a uint112, returning a UQ112x112\n function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {\n z = x / uint224(y);\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/interfaces/IERC20.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IERC20Uniswap {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external view returns (string memory);\n function symbol() external view returns (string memory);\n function decimals() external view returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Callee.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Callee {\n function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "contracts/mocks/SushiSwapPairMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@sushiswap/core/contracts/uniswapv2/UniswapV2Pair.sol\";\n\ncontract SushiSwapPairMock is UniswapV2Pair {\n constructor() public UniswapV2Pair() {\n return;\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/UniswapV2Factory.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity =0.6.12;\n\nimport './interfaces/IUniswapV2Factory.sol';\nimport './UniswapV2Pair.sol';\n\ncontract UniswapV2Factory is IUniswapV2Factory {\n address public override feeTo;\n address public override feeToSetter;\n address public override migrator;\n\n mapping(address => mapping(address => address)) public override getPair;\n address[] public override allPairs;\n\n event PairCreated(address indexed token0, address indexed token1, address pair, uint);\n\n constructor(address _feeToSetter) public {\n feeToSetter = _feeToSetter;\n }\n\n function allPairsLength() external override view returns (uint) {\n return allPairs.length;\n }\n\n function pairCodeHash() external pure returns (bytes32) {\n return keccak256(type(UniswapV2Pair).creationCode);\n }\n\n function createPair(address tokenA, address tokenB) external override returns (address pair) {\n require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');\n (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS');\n require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient\n bytes memory bytecode = type(UniswapV2Pair).creationCode;\n bytes32 salt = keccak256(abi.encodePacked(token0, token1));\n assembly {\n pair := create2(0, add(bytecode, 32), mload(bytecode), salt)\n }\n UniswapV2Pair(pair).initialize(token0, token1);\n getPair[token0][token1] = pair;\n getPair[token1][token0] = pair; // populate mapping in the reverse direction\n allPairs.push(pair);\n emit PairCreated(token0, token1, pair, allPairs.length);\n }\n\n function setFeeTo(address _feeTo) external override {\n require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');\n feeTo = _feeTo;\n }\n\n function setMigrator(address _migrator) external override {\n require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');\n migrator = _migrator;\n }\n\n function setFeeToSetter(address _feeToSetter) external override {\n require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');\n feeToSetter = _feeToSetter;\n }\n\n}\n" + }, + "contracts/mocks/SushiSwapFactoryMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/UniswapV2Factory.sol\";\n\ncontract SushiSwapFactoryMock is UniswapV2Factory {\n constructor() public UniswapV2Factory(msg.sender) {\n return;\n }\n}\n" + }, + "contracts/swappers/Liquidations/YVWETHSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw(uint256 maxShares, address recipient) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\ncontract YVWETHSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n YearnVault public constant WETH_VAULT = YearnVault(0xa258C4606Ca8206D8aA700cE2143D7db854D168c);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n\n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n uint256 amountFrom = WETH_VAULT.withdraw(type(uint256).max, address(pair));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n uint256 amountIntermediate = getAmountOut(amountFrom, reserve0, reserve1);\n pair.swap(0, amountIntermediate, address(this), new bytes(0));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/YVIBSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function remove_liquidity_one_coin(uint256 tokenAmount, int128 i, uint256 min_amount, bool use_underlying) external returns(uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n function balanceOf(address user) external view returns (uint256);\n}\n\ncontract YVIBSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n \n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool constant public IronBank = CurvePool(0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF);\n YearnVault constant public YVIB = YearnVault(0x27b7b1ad7288079A66d12350c828D3C00A6F07d7);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n uint256 amountFrom = YVIB.withdraw();\n\n IronBank.remove_liquidity_one_coin(amountFrom, 2, 0, true);\n\n uint256 amountIntermediate = TETHER.balanceOf(address(this));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/YVCrvStETHSwapper2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function remove_liquidity_one_coin(uint256 tokenAmount, int128 i, uint256 min_amount) external returns(uint256);\n}\n\ninterface IThreeCrypto is CurvePool {\n function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n function balanceOf(address user) external view returns (uint256);\n}\n\ninterface IWETH is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n function deposit() external payable;\n}\n\ncontract YVCrvStETHSwapper2 is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant degenBox = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n IWETH public constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool constant public STETH = CurvePool(0x828b154032950C8ff7CF8085D841723Db2696056);\n YearnVault constant public YVSTETH = YearnVault(0x5faF6a2D186448Dfa667c51CB3D695c7A6E52d8E);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IThreeCrypto constant public threecrypto = IThreeCrypto(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n WETH.approve(address(threecrypto), type(uint256).max);\n }\n\n receive() external payable {}\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n degenBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n uint256 wethBalance;\n\n {\n\n uint256 amountFrom = YVSTETH.withdraw();\n\n wethBalance = STETH.remove_liquidity_one_coin(amountFrom, 0, 0);\n\n }\n\n threecrypto.exchange(2, 0, wethBalance, 0);\n\n uint256 amountIntermediate = TETHER.balanceOf(address(this));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(degenBox));\n\n (, shareReturned) = degenBox.deposit(toToken, address(degenBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/YVCrvStETHSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function remove_liquidity_one_coin(uint256 tokenAmount, int128 i, uint256 min_amount) external returns(uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n function balanceOf(address user) external view returns (uint256);\n}\n\ninterface IWETH is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n function deposit() external payable;\n}\n\ncontract YVCrvStETHSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n IWETH public constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool constant public STETH = CurvePool(0xDC24316b9AE028F1497c275EB9192a3Ea0f67022);\n YearnVault constant public YVSTETH = YearnVault(0xdCD90C7f6324cfa40d7169ef80b12031770B4325);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n receive() external payable {}\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n {\n\n uint256 amountFrom = YVSTETH.withdraw();\n\n STETH.remove_liquidity_one_coin(amountFrom, 0, 0);\n\n }\n\n uint256 amountSecond = address(this).balance;\n\n WETH.deposit{value: amountSecond}();\n WETH.transfer(address(pair), amountSecond);\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n uint256 amountIntermediate = getAmountOut(amountSecond, reserve0, reserve1);\n pair.swap(0, amountIntermediate, address(this), new bytes(0));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/XSushiSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface SushiBar {\n function leave(uint256 share) external;\n}\n\ninterface Sushi is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract YVXSushiSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n SushiBar public constant xSushi = SushiBar(0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272);\n Sushi public constant SUSHI = Sushi(0x6B3595068778DD592e39A122f4f5a5cF09C90fE2);\n IUniswapV2Pair constant SUSHI_WETH = IUniswapV2Pair(0x795065dCc9f64b5614C407a6EFDC400DA6221FB0);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n\n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n {\n\n (uint256 amountXSushiFrom, ) = bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n xSushi.leave(amountXSushiFrom);\n\n }\n uint256 amountFirst;\n\n {\n\n uint256 amountFrom = SUSHI.balanceOf(address(this));\n\n SUSHI.transfer(address(SUSHI_WETH), amountFrom);\n\n (uint256 reserve0, uint256 reserve1, ) = SUSHI_WETH.getReserves();\n \n amountFirst = getAmountOut(amountFrom, reserve0, reserve1);\n \n }\n\n SUSHI_WETH.swap(0, amountFirst, address(pair), new bytes(0));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n uint256 amountIntermediate = getAmountOut(amountFirst, reserve0, reserve1);\n pair.swap(0, amountIntermediate, address(this), new bytes(0));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/wOHMSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface IWOHM {\n function wrap( uint _amount ) external returns ( uint );\n function unwrap( uint _amount ) external returns ( uint );\n}\n\ninterface IOHM is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\ninterface IStakingManager {\n function unstake( uint _amount, bool _trigger ) external;\n function stake( uint _amount, address _recipient ) external returns ( bool );\n}\n\ncontract wOHMSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IERC20 public constant DAI = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); \n IUniswapV2Pair constant OHM_DAI = IUniswapV2Pair(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant SOHM = IERC20(0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F);\n IWOHM public constant WOHM = IWOHM(0xCa76543Cf381ebBB277bE79574059e32108e3E65);\n IStakingManager public constant STAKING_MANAGER = IStakingManager(0xFd31c7d00Ca47653c6Ce64Af53c1571f9C36566a);\n IOHM public constant OHM = IOHM(0x383518188C0C6d7730D91b2c03a03C837814a899);\n\n constructor(\n ) public {\n DAI.approve(address(MIM3POOL), type(uint256).max);\n SOHM.approve(address(STAKING_MANAGER), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n \n uint256 amountFirst;\n\n {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n amountFirst = WOHM.unwrap(amountFrom);\n\n }\n\n STAKING_MANAGER.unstake(amountFirst, false);\n\n OHM.transfer(address(OHM_DAI), amountFirst);\n\n (uint256 reserve0, uint256 reserve1, ) = OHM_DAI.getReserves();\n \n uint256 amountDAI = getAmountOut(amountFirst, reserve0, reserve1);\n\n OHM_DAI.swap(0, amountDAI, address(this), new bytes(0));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(1, 0, amountDAI, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/WethSwapper.sol": { + "content": "pragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function remove_liquidity_one_coin(uint256 tokenAmount, int128 i, uint256 min_amount) external;\n}\n\ninterface IThreeCrypto is CurvePool {\n function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;\n}\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n function balanceOf(address user) external view returns (uint256);\n}\n\ninterface IConvex is IERC20{\n function withdrawAndUnwrap(uint256 _amount) external;\n}\n\ncontract WethSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant degenBox = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IThreeCrypto constant public threecrypto = IThreeCrypto(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n WETH.approve(address(threecrypto), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = degenBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n threecrypto.exchange(2, 0, amountFrom, 0);\n\n uint256 amountIntermediate = TETHER.balanceOf(address(this));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(degenBox));\n\n (, shareReturned) = degenBox.deposit(toToken, address(degenBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}" + }, + "contracts/swappers/Liquidations/WbtcSwapper.sol": { + "content": "pragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function remove_liquidity_one_coin(uint256 tokenAmount, int128 i, uint256 min_amount) external;\n}\n\ninterface IThreeCrypto is CurvePool {\n function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;\n}\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n function balanceOf(address user) external view returns (uint256);\n}\n\ninterface IConvex is IERC20{\n function withdrawAndUnwrap(uint256 _amount) external;\n}\n\ncontract WbtcSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant degenBox = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IThreeCrypto constant public threecrypto = IThreeCrypto(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant WBTC = IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n WBTC.approve(address(threecrypto), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = degenBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n threecrypto.exchange(1, 0, amountFrom, 0);\n\n uint256 amountIntermediate = TETHER.balanceOf(address(this));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(degenBox));\n\n (, shareReturned) = degenBox.deposit(toToken, address(degenBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}" + }, + "contracts/swappers/Liquidations/ThreeCryptoSwapper.sol": { + "content": "pragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function remove_liquidity_one_coin(uint256 tokenAmount, uint256 i, uint256 min_amount) external;\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n function balanceOf(address user) external view returns (uint256);\n}\n\ninterface IConvex is IERC20{\n function withdrawAndUnwrap(uint256 _amount) external;\n}\n\ncontract ThreeCryptoSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n \n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool constant public threecrypto = CurvePool(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n IConvex public constant cvx3Crypto = IConvex(0x5958A8DB7dfE0CC49382209069b00F54e17929C2);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n cvx3Crypto.withdrawAndUnwrap(amountFrom);\n\n threecrypto.remove_liquidity_one_coin(amountFrom, 0, 0);\n\n uint256 amountIntermediate = TETHER.balanceOf(address(this));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}" + }, + "contracts/swappers/Liquidations/StkFrax3CrvSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\nimport \"../../interfaces/ISwapper.sol\";\n\ninterface CurvePool {\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address receiver\n ) external returns (uint256);\n\n function approve(address _spender, uint256 _value) external returns (bool);\n\n function remove_liquidity_one_coin(\n address pool,\n uint256 tokenAmount,\n int128 i,\n uint256 min_amount\n ) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n\n function balanceOf(address user) external view returns (uint256);\n}\n\ninterface IConvex is IERC20 {\n function withdrawAndUnwrap(uint256 _amount) external;\n}\n\ncontract StkFrax3CrvSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n address public constant FRAX3CRVPOOL = 0xd632f22692FaC7611d2AA1C0D552930D43CAEd3B;\n CurvePool public constant threePool = CurvePool(0xA79828DF1850E8a3A3064576f380D90aECDD3359);\n\n IConvex public immutable stkFrax3Crv;\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant FRAX3CRV = IERC20(0xd632f22692FaC7611d2AA1C0D552930D43CAEd3B);\n\n constructor(IConvex _stkFrax3Crv) public {\n stkFrax3Crv = _stkFrax3Crv;\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n FRAX3CRV.approve(address(threePool), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amountFrom, ) = bentoBox.withdraw(IERC20(stkFrax3Crv), address(this), address(this), 0, shareFrom);\n\n stkFrax3Crv.withdrawAndUnwrap(amountFrom);\n\n // Pool token order is FRAX, DAI, USDC, USDT\n uint256 amountUSDT = threePool.remove_liquidity_one_coin(FRAX3CRVPOOL, amountFrom, 3, 0);\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountUSDT, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(MIM, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/sSpellSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface IsSpell {\n function burn(address to, uint256 shares) external returns (bool);\n}\n\ninterface ISpell is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract SSpellSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IsSpell public constant sSpell = IsSpell(0x26FA3fFFB6EfE8c1E69103aCb4044C26B9A106a9);\n ISpell public constant SPELL = ISpell(0x090185f2135308BaD17527004364eBcC2D37e5F6);\n IUniswapV2Pair constant SPELL_ETH = IUniswapV2Pair(0xb5De0C3753b6E1B4dBA616Db82767F17513E6d4E);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n\n constructor(\n ) public {\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n {\n\n (uint256 amountSSpellFrom, ) = bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n sSpell.burn(address(this), amountSSpellFrom);\n\n }\n uint256 amountFirst;\n\n {\n\n uint256 amountFrom = SPELL.balanceOf(address(this));\n\n SPELL.transfer(address(SPELL_ETH), amountFrom);\n\n (uint256 reserve0, uint256 reserve1, ) = SPELL_ETH.getReserves();\n \n amountFirst = getAmountOut(amountFrom, reserve0, reserve1);\n \n }\n\n SPELL_ETH.swap(0, amountFirst, address(pair), new bytes(0));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n uint256 amountIntermediate = getAmountOut(amountFirst, reserve0, reserve1);\n pair.swap(0, amountIntermediate, address(this), new bytes(0));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}" + }, + "contracts/swappers/Liquidations/SpellSuperSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface IsSpell {\n function burn(address to, uint256 shares) external returns (bool);\n}\n\ninterface ISpell is IERC20 {\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract SpellSuperSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IsSpell public constant sSpell = IsSpell(0x26FA3fFFB6EfE8c1E69103aCb4044C26B9A106a9);\n ISpell public constant SPELL = ISpell(0x090185f2135308BaD17527004364eBcC2D37e5F6);\n IUniswapV2Pair constant SPELL_ETH = IUniswapV2Pair(0xb5De0C3753b6E1B4dBA616Db82767F17513E6d4E);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n\n constructor(\n ) public {\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(fromToken, address(this), address(SPELL_ETH), 0, shareFrom);\n\n uint256 amountFirst;\n\n {\n\n (uint256 reserve0, uint256 reserve1, ) = SPELL_ETH.getReserves();\n \n amountFirst = getAmountOut(amountFrom, reserve0, reserve1);\n \n }\n\n SPELL_ETH.swap(0, amountFirst, address(pair), new bytes(0));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n uint256 amountIntermediate = getAmountOut(amountFirst, reserve0, reserve1);\n pair.swap(0, amountIntermediate, address(this), new bytes(0));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}" + }, + "contracts/swappers/Liquidations/RenCrvSwapper.sol": { + "content": "pragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n function approve(address _spender, uint256 _value) external returns (bool);\n function remove_liquidity_one_coin(uint256 tokenAmount, int128 i, uint256 min_amount) external;\n}\n\ninterface IThreeCrypto is CurvePool {\n function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external;\n}\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n function balanceOf(address user) external view returns (uint256);\n}\n\ninterface IConvex is IERC20{\n function withdrawAndUnwrap(uint256 _amount) external;\n}\n\ncontract RenCrvSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool constant public renCrv = CurvePool(0x93054188d876f558f4a66B2EF1d97d16eDf0895B);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IThreeCrypto constant public threecrypto = IThreeCrypto(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n IConvex public constant cvxRen = IConvex(0xB65eDE134521F0EFD4E943c835F450137dC6E83e);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant CurveToken = IERC20(0x49849C98ae39Fff122806C06791Fa73784FB3675);\n IERC20 public constant WBTC = IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n WBTC.approve(address(threecrypto), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(fromToken, address(this), address(this), 0, shareFrom);\n\n cvxRen.withdrawAndUnwrap(amountFrom);\n\n renCrv.remove_liquidity_one_coin(amountFrom, 1, 0);\n\n uint256 amountOne = WBTC.balanceOf(address(this));\n\n threecrypto.exchange(1, 0, amountOne, 0);\n\n uint256 amountIntermediate = TETHER.balanceOf(address(this));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}" + }, + "contracts/swappers/Liquidations/FTMSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\n\ncontract FTMSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n \n IUniswapV2Pair constant pair = IUniswapV2Pair(0xB32b31DfAfbD53E310390F641C7119b5B9Ea0488);\n IERC20 constant WFTM = IERC20(0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83);\n IERC20 public constant MIM = IERC20(0x82f0B8B456c1A451378467398982d4834b6829c1);\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom,) = bentoBox.withdraw(fromToken, address(this), address(pair), 0, shareFrom);\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n uint256 amountTo = getAmountOut(amountFrom, reserve0, reserve1);\n pair.swap(0, amountTo, address(bentoBox), new bytes(0));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/ALCXSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapper.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract ALCXSwapper is ISwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant ALCX = IERC20(0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF);\n IUniswapV2Pair constant ALCX_WETH = IUniswapV2Pair(0xC3f279090a47e80990Fe3a9c30d24Cb117EF91a8);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n\n constructor() public {\n TETHER.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n// Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapper\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(fromToken, address(this), address(ALCX_WETH), 0, shareFrom);\n\n (uint256 reserve0, uint256 reserve1, ) = ALCX_WETH.getReserves();\n \n uint256 amountFirst = getAmountOut(amountFrom, reserve1, reserve0);\n\n ALCX_WETH.swap(amountFirst, 0, address(pair), new bytes(0));\n\n (reserve0, reserve1, ) = pair.getReserves();\n \n uint256 amountIntermediate = getAmountOut(amountFirst, reserve0, reserve1);\n pair.swap(0, amountIntermediate, address(this), new bytes(0));\n\n uint256 amountTo = MIM3POOL.exchange_underlying(3, 0, amountIntermediate, 0, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(toToken, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapper\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) public override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0,0);\n }\n}\n" + }, + "contracts/swappers/Leverage/YVYFILevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract YVYFILevSwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n YearnVault public constant YFI_VAULT = YearnVault(0xE14d13d8B3b85aF791b2AADD661cDBd5E6097Db1);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n IUniswapV2Pair constant YFI_WETH = IUniswapV2Pair(0x088ee5007C98a9677165D78dD2109AE4a3D04d0C);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n IERC20 constant YFI = IERC20(0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n MIM.approve(address(MIM3POOL), type(uint256).max);\n YFI.approve(address(YFI_VAULT), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n uint256 amountFirst;\n\n {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n amountFirst = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(pair));\n\n }\n\n uint256 amountIntermediate;\n \n {\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n amountIntermediate = getAmountOut(amountFirst, reserve1, reserve0);\n pair.swap(amountIntermediate, 0, address(YFI_WETH), new bytes(0));\n\n }\n\n (uint256 reserve0, uint256 reserve1, ) = YFI_WETH.getReserves();\n \n uint256 amountInt2 = getAmountOut(amountIntermediate, reserve1, reserve0);\n \n YFI_WETH.swap(amountInt2, 0, address(this), new bytes(0));\n\n uint256 amountTo = YFI_VAULT.deposit(type(uint256).max, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(IERC20(address(YFI_VAULT)), address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/YVXSushiLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface SushiBar is IERC20 {\n function leave(uint256 share) external;\n function enter(uint256 amount) external;\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract YVXSushiLevSwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n SushiBar public constant xSushi = SushiBar(0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272);\n IERC20 public constant SUSHI = IERC20(0x6B3595068778DD592e39A122f4f5a5cF09C90fE2);\n IUniswapV2Pair constant SUSHI_WETH = IUniswapV2Pair(0x795065dCc9f64b5614C407a6EFDC400DA6221FB0);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n SUSHI.approve(address(xSushi), type(uint256).max);\n MIM.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n uint256 amountFirst;\n uint256 amountIntermediate;\n\n {\n\n (uint256 amountMIMFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n amountFirst = MIM3POOL.exchange_underlying(0, 3, amountMIMFrom, 0, address(pair));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n amountIntermediate = getAmountOut(amountFirst, reserve1, reserve0);\n\n }\n\n uint256 amountThird;\n\n {\n \n pair.swap(amountIntermediate, 0, address(SUSHI_WETH), new bytes(0));\n\n (uint256 reserve0, uint256 reserve1, ) = SUSHI_WETH.getReserves();\n \n amountThird = getAmountOut(amountIntermediate, reserve1, reserve0);\n\n }\n\n SUSHI_WETH.swap(amountThird, 0, address(this), new bytes(0));\n\n xSushi.enter(amountThird);\n\n uint256 amountTo = xSushi.balanceOf(address(this));\n\n xSushi.transfer(address(bentoBox), amountTo);\n\n (, shareReturned) = bentoBox.deposit(xSushi, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n}\n" + }, + "contracts/swappers/Leverage/YVWETHLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface YearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\ncontract YVWETHLevSwapper{\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public immutable bentoBox;\n\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n YearnVault public constant WETH_VAULT = YearnVault(0xa258C4606Ca8206D8aA700cE2143D7db854D168c);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n IERC20 constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n constructor(\n IBentoBoxV1 bentoBox_\n ) public {\n bentoBox = bentoBox_;\n WETH.approve(address(WETH_VAULT), type(uint256).max);\n MIM.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountIntermediate = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(pair));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n uint256 amountInt2 = getAmountOut(amountIntermediate, reserve1, reserve0);\n pair.swap(amountInt2, 0, address(this), new bytes(0));\n\n uint256 amountTo = WETH_VAULT.deposit(type(uint256).max, address(bentoBox));\n\n (, shareReturned) = bentoBox.deposit(IERC20(address(WETH_VAULT)), address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/wOHMLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface IWOHM is IERC20 {\n function wrap( uint _amount ) external returns ( uint );\n function unwrap( uint _amount ) external returns ( uint );\n function transfer(address _to, uint256 _value) external returns (bool success);\n}\n\ninterface IStakingManager {\n function unstake( uint _amount, bool _trigger ) external;\n function stake( uint _amount, address _recipient ) external returns ( bool );\n function claim ( address _recipient ) external;\n}\n\ncontract wOHMLevSwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IUniswapV2Pair constant OHM_DAI = IUniswapV2Pair(0x34d7d7Aaf50AD4944B70B320aCB24C95fa2def7c);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant SOHM = IERC20(0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F);\n IWOHM public constant WOHM = IWOHM(0xCa76543Cf381ebBB277bE79574059e32108e3E65);\n IStakingManager public constant STAKING_MANAGER = IStakingManager(0xFd31c7d00Ca47653c6Ce64Af53c1571f9C36566a);\n IERC20 public constant OHM = IERC20(0x383518188C0C6d7730D91b2c03a03C837814a899);\n constructor(\n ) public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n OHM.approve(address(STAKING_MANAGER), type(uint256).max);\n SOHM.approve(address(WOHM), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n uint256 amountFirst;\n uint256 amountIntermediate;\n\n {\n\n (uint256 amountMIMFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n amountFirst = MIM3POOL.exchange_underlying(0, 1, amountMIMFrom, 0, address(OHM_DAI));\n\n (uint256 reserve0, uint256 reserve1, ) = OHM_DAI.getReserves();\n amountIntermediate = getAmountOut(amountFirst, reserve1, reserve0);\n }\n \n OHM_DAI.swap(amountIntermediate, 0, address(this), new bytes(0));\n\n STAKING_MANAGER.stake(amountIntermediate, address(this));\n\n STAKING_MANAGER.claim(address(this));\n\n uint256 amountTo = WOHM.wrap(amountIntermediate);\n\n WOHM.transfer(address(bentoBox), amountTo);\n\n (, shareReturned) = bentoBox.deposit(WOHM, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n\n}" + }, + "contracts/swappers/Leverage/SpellLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract SpellLevSwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant SPELL = IERC20(0x090185f2135308BaD17527004364eBcC2D37e5F6);\n IUniswapV2Pair constant SPELL_ETH = IUniswapV2Pair(0xb5De0C3753b6E1B4dBA616Db82767F17513E6d4E);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n uint256 amountFirst = MIM3POOL.exchange_underlying(0, 3, amountFrom, 0, address(pair));\n \n uint256 amountIntermediate;\n {\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n amountIntermediate = getAmountOut(amountFirst, reserve1, reserve0);\n pair.swap(amountIntermediate, 0, address(SPELL_ETH), new bytes(0));\n\n }\n\n uint256 amountTo;\n\n {\n\n (uint256 reserve0, uint256 reserve1, ) = SPELL_ETH.getReserves();\n \n amountTo = getAmountOut(amountIntermediate, reserve1, reserve0);\n \n }\n\n SPELL_ETH.swap(amountTo, 0, address(bentoBox), new bytes(0));\n\n (, shareReturned) = bentoBox.deposit(SPELL, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/FTMLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ncontract FTMLevSwapper{\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0xB32b31DfAfbD53E310390F641C7119b5B9Ea0488);\n IERC20 constant WFTM = IERC20(0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83);\n IERC20 public constant MIM = IERC20(0x82f0B8B456c1A451378467398982d4834b6829c1);\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n (uint256 amountFrom, ) = bentoBox.withdraw(MIM, address(this), address(pair), 0, shareFrom);\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n \n uint256 amountTo = getAmountOut(amountFrom, reserve1, reserve0);\n pair.swap(amountTo, 0, address(bentoBox), new bytes(0));\n\n (, shareReturned) = bentoBox.deposit(WFTM, address(bentoBox), recipient, amountTo, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/swappers/Leverage/ALCXLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol\";\n\ninterface CurvePool {\n function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy, address receiver) external returns (uint256);\n}\n\ninterface TetherToken {\n function approve(address _spender, uint256 _value) external;\n}\n\ncontract ALCXLevSwapper {\n using BoringMath for uint256;\n\n // Local variables\n IBentoBoxV1 public constant bentoBox = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n TetherToken public constant TETHER = TetherToken(0xdAC17F958D2ee523a2206206994597C13D831ec7); \n IERC20 public constant ALCX = IERC20(0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF);\n IUniswapV2Pair constant ALCX_WETH = IUniswapV2Pair(0xC3f279090a47e80990Fe3a9c30d24Cb117EF91a8);\n IUniswapV2Pair constant pair = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n constructor() public {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n // Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n\n uint256 amountFirst;\n uint256 amountIntermediate;\n\n {\n\n (uint256 amountMIMFrom, ) = bentoBox.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n amountFirst = MIM3POOL.exchange_underlying(0, 3, amountMIMFrom, 0, address(pair));\n\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n amountIntermediate = getAmountOut(amountFirst, reserve1, reserve0);\n\n }\n\n pair.swap(amountIntermediate, 0, address(ALCX_WETH), new bytes(0));\n\n (uint256 reserve0, uint256 reserve1, ) = ALCX_WETH.getReserves();\n \n uint256 amountThird = getAmountOut(amountIntermediate, reserve0, reserve1);\n\n ALCX_WETH.swap(0, amountThird, address(bentoBox), new bytes(0));\n\n (, shareReturned) = bentoBox.deposit(ALCX, address(bentoBox), recipient, amountThird, 0);\n extraShare = shareReturned.sub(shareToMin);\n }\n}\n" + }, + "contracts/mocks/ExternalFunctionMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\n\ncontract ExternalFunctionMock {\n using BoringMath for uint256;\n\n event Result(uint256 output);\n\n function sum(uint256 a, uint256 b) external returns (uint256 c) {\n c = a.add(b);\n emit Result(c);\n }\n}\n" + }, + "@boringcrypto/boring-solidity/contracts/interfaces/IMasterContract.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\ninterface IMasterContract {\n /// @notice Init function that gets called from `BoringFactory.deploy`.\n /// Also kown as the constructor for cloned contracts.\n /// Any ETH send to `BoringFactory.deploy` ends up here.\n /// @param data Can be abi encoded arguments or anything else.\n function init(bytes calldata data) external payable;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 690 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/mainnet/solcInputs/f3c6669b166894ac5cec2d9fe7c3a109.json b/deployments/mainnet/solcInputs/f3c6669b166894ac5cec2d9fe7c3a109.json new file mode 100644 index 00000000..4f8bf8f5 --- /dev/null +++ b/deployments/mainnet/solcInputs/f3c6669b166894ac5cec2d9fe7c3a109.json @@ -0,0 +1,320 @@ +{ + "language": "Solidity", + "sources": { + "contracts/interfaces/IWhitelister.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface IWhitelister {\n /// @notice Get whether user is allowed to borrow\n /// @param user address of the user\n /// @param newBorrowPart new borrow part of the user. \n /// @return success if user is allowed to borrow said new amount, returns true otherwise false\n function getBorrowStatus(address user, uint256 newBorrowPart) external view returns (bool success);\n\n /// @notice Function for the user to bring a merkle proof to set a new max borrow\n /// @param user address of the user\n /// @param maxBorrow new max borrowPart for the user. \n /// @param merkleProof merkle proof provided to user.\n /// @return success if the user is indeed allowed to borrow said new amount\n function setMaxBorrow(address user, uint256 maxBorrow, bytes32[] calldata merkleProof) external returns (bool success);\n}\n" + }, + "contracts/Whitelister.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.10;\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./interfaces/IWhitelister.sol\";\n\ncontract Whitelister is IWhitelister, Ownable {\n event LogSetMaxBorrow(address user, uint256 maxBorrowAmount);\n event LogSetMerkleRoot(bytes32 newRoot, string ipfsMerkleProofs);\n mapping (address => uint256) public amountAllowed;\n\n bytes32 public merkleRoot;\n string public ipfsMerkleProofs;\n\n constructor (\n bytes32 _merkleRoot,\n string memory _ipfsMerkleProofs\n ) {\n merkleRoot = _merkleRoot;\n ipfsMerkleProofs = _ipfsMerkleProofs;\n emit LogSetMerkleRoot(_merkleRoot, _ipfsMerkleProofs);\n }\n\n /// @inheritdoc IWhitelister\n function getBorrowStatus(address user, uint256 newBorrowAmount) external view override returns (bool success) {\n return amountAllowed[user] >= newBorrowAmount;\n }\n\n /// @inheritdoc IWhitelister\n function setMaxBorrow(address user, uint256 maxBorrow, bytes32[] calldata merkleProof) external returns (bool success) {\n // Verify the merkle proof.\n bytes32 node = keccak256(abi.encodePacked(user, maxBorrow));\n require(MerkleProof.verify(merkleProof, merkleRoot, node), \"Whitelister: Invalid proof.\");\n\n amountAllowed[user] = maxBorrow;\n\n emit LogSetMaxBorrow(user, maxBorrow);\n\n return true;\n }\n\n function changeMerkleRoot(bytes32 newRoot, string calldata ipfsMerkleProofs_) external onlyOwner {\n ipfsMerkleProofs = ipfsMerkleProofs_;\n merkleRoot = newRoot;\n emit LogSetMerkleRoot(newRoot, ipfsMerkleProofs_);\n }\n\n}" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = _efficientHash(computedHash, proofElement);\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = _efficientHash(proofElement, computedHash);\n }\n }\n return computedHash;\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\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 _transferOwnership(_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 _transferOwnership(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 _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/magic-crv/RewardHarvester.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable func-name-mixedcase\npragma solidity ^0.8.10;\n\nimport \"@rari-capital/solmate/src/tokens/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/Tether.sol\";\nimport \"../interfaces/curve/ICurveThreeCryptoPool.sol\";\nimport \"../interfaces/curve/ICurveThreePool.sol\";\nimport \"../interfaces/curve/ICurvePool.sol\";\n\ninterface ICurveVoter {\n function lock() external;\n\n function claimAll(address recipient) external returns (uint256 amount);\n\n function claim(address recipient) external returns (uint256 amount);\n}\n\ncontract RewardHarvester is Ownable {\n error InsufficientOutput();\n error NotAllowed();\n\n ERC20 public constant CRV = ERC20(0xD533a949740bb3306d119CC777fa900bA034cd52);\n ERC20 public constant CRV3 = ERC20(0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490);\n ERC20 public constant WETH = ERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n CurveThreePool public constant CRV3POOL = CurveThreePool(0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7);\n CurvePool public constant CRVETH = CurvePool(0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511);\n Tether public constant USDT = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n CurveThreeCryptoPool public constant TRICRYPTO = CurveThreeCryptoPool(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n ICurveVoter public immutable curveVoter;\n\n mapping(address => bool) public allowedHarvesters;\n\n modifier onlyAllowedHarvesters() {\n if (!allowedHarvesters[msg.sender] && msg.sender != owner()) {\n revert NotAllowed();\n }\n _;\n }\n\n constructor(ICurveVoter _curveVoter) {\n curveVoter = _curveVoter;\n USDT.approve(address(TRICRYPTO), type(uint256).max);\n WETH.approve(address(CRVETH), type(uint256).max);\n }\n\n function setAllowedHarvester(address account, bool allowed) external onlyOwner {\n allowedHarvesters[account] = allowed;\n }\n\n function harvest(uint256 minAmountOut) external onlyAllowedHarvesters returns (uint256 amountOut) {\n uint256 crvAmount = curveVoter.claim(address(this));\n\n if (crvAmount != 0) {\n amountOut = _harvest(crvAmount, minAmountOut);\n }\n }\n\n function harvestAll(uint256 minAmountOut) external onlyAllowedHarvesters returns (uint256 amountOut) {\n uint256 crvAmount = curveVoter.claimAll(address(this));\n\n if (crvAmount != 0) {\n amountOut = _harvest(crvAmount, minAmountOut);\n }\n }\n\n function _harvest(uint256 crvAmount, uint256 minAmountOut) private returns (uint256 amountOut) {\n // 3CRV -> USDT\n CRV3POOL.remove_liquidity_one_coin(crvAmount, 2, 0);\n\n // USDT -> WETH\n TRICRYPTO.exchange(0, 2, USDT.balanceOf(address(this)), 0);\n\n // WETH -> CRV\n amountOut = CRVETH.exchange(0, 1, WETH.balanceOf(address(this)), 0);\n\n if (amountOut < minAmountOut) {\n revert InsufficientOutput();\n }\n\n CRV.transfer(address(curveVoter), amountOut);\n curveVoter.lock();\n }\n}\n" + }, + "@rari-capital/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*///////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*///////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*///////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*///////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n bytes32 public constant PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*///////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*///////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*///////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\n )\n );\n\n address recoveredAddress = ecrecover(digest, v, r, s);\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*///////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "contracts/interfaces/Tether.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface Tether {\n function approve(address spender, uint256 value) external;\n\n function balanceOf(address user) external view returns (uint256);\n\n function transfer(address to, uint256 value) external;\n}\n" + }, + "contracts/interfaces/curve/ICurveThreeCryptoPool.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface CurveThreeCryptoPool {\n function exchange(\n uint256 i,\n uint256 j,\n uint256 dx,\n uint256 min_dy\n ) payable external;\n\n function get_dy(\n uint256 i,\n uint256 j,\n uint256 dx\n ) external view returns (uint256);\n\n function add_liquidity(uint256[3] memory amounts, uint256 _min_mint_amount) external;\n}\n" + }, + "contracts/interfaces/curve/ICurveThreePool.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface CurveThreePool {\n function exchange(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy\n ) external;\n\n function get_dy_underlying(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function get_dy(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function add_liquidity(uint256[3] memory amounts, uint256 _min_mint_amount) external;\n\n function remove_liquidity_one_coin(\n uint256 amount,\n int128 i,\n uint256 minAmount\n ) external;\n}\n" + }, + "contracts/interfaces/curve/ICurvePool.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable func-name-mixedcase, var-name-mixedcase\npragma solidity >=0.6.12;\n\ninterface CurvePool {\n function coins(uint256 i) external view returns (address);\n\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address receiver\n ) external returns (uint256);\n\n function exchange(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address receiver\n ) external returns (uint256);\n\n function exchange(\n uint256 i,\n uint256 j,\n uint256 dx,\n uint256 min_dy\n ) external returns (uint256);\n\n function get_dy_underlying(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function get_dy(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function approve(address _spender, uint256 _value) external returns (bool);\n\n function add_liquidity(uint256[2] memory amounts, uint256 _min_mint_amount) external;\n\n function add_liquidity(uint256[3] memory amounts, uint256 _min_mint_amount) external;\n\n function add_liquidity(uint256[4] memory amounts, uint256 _min_mint_amount) external;\n\n function remove_liquidity_one_coin(\n uint256 tokenAmount,\n int128 i,\n uint256 min_amount\n ) external returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 tokenAmount,\n uint256 i,\n uint256 min_amount\n ) external returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 tokenAmount,\n int128 i,\n uint256 min_amount,\n address receiver\n ) external returns (uint256);\n}\n" + }, + "contracts/interfaces/ISwapperGeneric.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >= 0.6.12;\n\nimport \"./IERC20.sol\";\n\ninterface ISwapperGeneric {\n /// @notice Withdraws 'amountFrom' of token 'from' from the BentoBox account for this swapper.\n /// Swaps it for at least 'amountToMin' of token 'to'.\n /// Transfers the swapped tokens of 'to' into the BentoBox using a plain ERC20 transfer.\n /// Returns the amount of tokens 'to' transferred to BentoBox.\n /// (The BentoBox skim function will be used by the caller to get the swapped funds).\n function swap(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) external returns (uint256 extraShare, uint256 shareReturned);\n\n /// @notice Calculates the amount of token 'from' needed to complete the swap (amountFrom),\n /// this should be less than or equal to amountFromMax.\n /// Withdraws 'amountFrom' of token 'from' from the BentoBox account for this swapper.\n /// Swaps it for exactly 'exactAmountTo' of token 'to'.\n /// Transfers the swapped tokens of 'to' into the BentoBox using a plain ERC20 transfer.\n /// Transfers allocated, but unused 'from' tokens within the BentoBox to 'refundTo' (amountFromMax - amountFrom).\n /// Returns the amount of 'from' tokens withdrawn from BentoBox (amountFrom).\n /// (The BentoBox skim function will be used by the caller to get the swapped funds).\n function swapExact(\n IERC20 fromToken,\n IERC20 toToken,\n address recipient,\n address refundTo,\n uint256 shareFromSupplied,\n uint256 shareToExact\n ) external returns (uint256 shareUsed, uint256 shareReturned);\n}\n" + }, + "contracts/interfaces/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address account) external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function approve(address spender, uint256 amount) external returns (bool);\n\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) external returns (bool);\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /// @notice EIP 2612\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "contracts/swappers/Liquidations/YVDAISwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable func-name-mixedcase, var-name-mixedcase\npragma solidity 0.8.10;\n\nimport \"../../interfaces/IBentoBoxV1.sol\";\nimport \"../../interfaces/curve/ICurvePool.sol\";\nimport \"../../interfaces/yearn/IYearnVault.sol\";\nimport \"../../interfaces/ISwapperGeneric.sol\";\n\ncontract YVDAISwapper is ISwapperGeneric {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IERC20 public constant DAI = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IYearnVault public constant DAI_VAULT = IYearnVault(0xdA816459F1AB5631232FE5e97a05BBBb94970c95);\n\n constructor() {\n DAI.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n DEGENBOX.withdraw(IERC20(address(DAI_VAULT)), address(this), address(this), 0, shareFrom);\n\n // yvDAI -> DAI\n uint256 amount = DAI_VAULT.withdraw();\n\n // DAI -> MIM\n amount = MIM3POOL.exchange_underlying(1, 0, amount, 0, address(DEGENBOX));\n\n (, shareReturned) = DEGENBOX.deposit(MIM, address(DEGENBOX), recipient, amount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure override returns (uint256 shareUsed, uint256 shareReturned) {\n return (1, 1);\n }\n}\n" + }, + "contracts/interfaces/IBentoBoxV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\nimport \"./IERC20.sol\";\n\ninterface IBentoBoxV1 {\n function toAmount(\n address _token,\n uint256 _share,\n bool _roundUp\n ) external view returns (uint256);\n\n function withdraw(\n IERC20 token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256, uint256);\n\n function deposit(\n IERC20 token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256, uint256);\n\n function deploy(\n address masterContract,\n bytes calldata data,\n bool useCreate2\n ) external payable returns (address cloneAddress);\n\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function balanceOf(IERC20, address) external view returns (uint256);\n\n function totals(IERC20) external view returns (uint128 elastic, uint128 base);\n\n function flashLoan(\n address borrower,\n address receiver,\n IERC20 token,\n uint256 amount,\n bytes calldata data\n ) external;\n\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n}\n" + }, + "contracts/interfaces/yearn/IYearnVault.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface IYearnVault {\n function withdraw() external returns (uint256);\n function deposit(uint256 amount, address recipient) external returns (uint256);\n}" + }, + "contracts/swappers/Liquidations/popsicle/PopsicleWETHUSDTSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../../interfaces/ISwapperGeneric.sol\";\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\nimport \"../../../interfaces/Tether.sol\";\n\n/// @notice WETH/USDT Popsicle Swapper for Ethereum\ncontract PopsicleWETHUSDTSwapper is ISwapperGeneric {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n\n IUniswapV2Pair public constant WETHUSDT = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n Tether public constant USDT = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n IPopsicle public immutable popsicle;\n\n constructor(IPopsicle _popsicle) {\n popsicle = _popsicle;\n USDT.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function _getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn * 997;\n uint256 numerator = amountInWithFee * reserveOut;\n uint256 denominator = (reserveIn * 1000) + amountInWithFee;\n amountOut = numerator / denominator;\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amountFrom, ) = DEGENBOX.withdraw(IERC20(address(popsicle)), address(this), address(this), 0, shareFrom);\n (uint256 wethAmount, uint256 usdtAmount) = popsicle.withdraw(amountFrom, address(this));\n\n // WETH -> USDT\n (uint256 reserve0, uint256 reserve1, ) = WETHUSDT.getReserves();\n uint256 usdtFromWeth = _getAmountOut(wethAmount, reserve0, reserve1);\n WETH.transfer(address(WETHUSDT), wethAmount);\n WETHUSDT.swap(0, usdtFromWeth, address(this), \"\");\n usdtAmount += usdtFromWeth;\n\n // USDT -> MIM\n uint256 mimFromUSDT = MIM3POOL.exchange_underlying(3, 0, usdtAmount, 0, address(DEGENBOX));\n\n (, shareReturned) = DEGENBOX.deposit(MIM, address(DEGENBOX), recipient, mimFromUSDT, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure virtual returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "contracts/interfaces/IPopsicle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface IPopsicle {\n function pool() external view returns (address);\n\n function token0() external view returns (address);\n\n function token1() external view returns (address);\n\n function strategy() external view returns (address);\n\n function usersAmounts() external view returns (uint256 amount0, uint256 amount1);\n\n function totalSupply() external view returns (uint256 amount);\n\n function balanceOf(address account) external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function approve(address spender, uint256 amount) external returns (bool);\n\n function withdraw(uint256 shares, address to) external returns (uint256 amount0, uint256 amount1);\n\n function tickLower() external view returns (int24);\n\n function tickUpper() external view returns (int24);\n\n function deposit(\n uint256 amount0Desired,\n uint256 amount1Desired,\n address to\n )\n external\n returns (\n uint256 shares,\n uint256 amount0,\n uint256 amount1\n );\n}\n" + }, + "contracts/swappers/Liquidations/UsdceAvaxSwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../interfaces/ISwapperGeneric.sol\";\nimport \"../../interfaces/IBentoBoxV1.sol\";\nimport \"../../interfaces/platypus/IPlatypusRouter01.sol\";\n\n/// @notice Joe USDCE.e/WAVAX swapper using Platypus for swapping USDCE.e to MIM\ncontract UsdceAvaxSwapperV2 is ISwapperGeneric {\n IBentoBoxV1 public immutable DEGENBOX;\n\n IUniswapV2Pair public constant USDCEAVAX = IUniswapV2Pair(0xA389f9430876455C36478DeEa9769B7Ca4E3DDB1);\n IUniswapV2Pair public constant MIMAVAX = IUniswapV2Pair(0x781655d802670bbA3c89aeBaaEa59D3182fD755D);\n IPlatypusRouter01 public constant PLATYPUS_ROUTER = IPlatypusRouter01(0x73256EC7575D999C360c1EeC118ECbEFd8DA7D12);\n\n IERC20 public constant WAVAX = IERC20(0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7);\n IERC20 public constant MIM = IERC20(0x130966628846BFd36ff31a822705796e8cb8C18D);\n IERC20 public constant USDC = IERC20(0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E);\n IERC20 public constant USDCE = IERC20(0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664);\n\n constructor(IBentoBoxV1 _DEGENBOX) {\n DEGENBOX = _DEGENBOX;\n USDCE.approve(address(PLATYPUS_ROUTER), type(uint256).max);\n MIM.approve(address(_DEGENBOX), type(uint256).max);\n }\n\n // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function _getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn * 997;\n uint256 numerator = amountInWithFee * reserveOut;\n uint256 denominator = (reserveIn * 1000) + amountInWithFee;\n amountOut = numerator / denominator;\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amountFrom, ) = DEGENBOX.withdraw(IERC20(address(USDCEAVAX)), address(this), address(this), 0, shareFrom);\n USDCEAVAX.transfer(address(USDCEAVAX), amountFrom);\n (uint256 usdceAmount, uint256 avaxAmount) = USDCEAVAX.burn(address(this));\n uint256 mimAmount;\n\n // USDC.e -> MIM\n {\n address[] memory tokenPath = new address[](3);\n tokenPath[0] = address(USDCE);\n tokenPath[1] = address(USDC);\n tokenPath[2] = address(MIM);\n address[] memory poolPath = new address[](2);\n poolPath[0] = address(0x66357dCaCe80431aee0A7507e2E361B7e2402370); // USDC -> MIM pool\n poolPath[1] = address(0x30C30d826be87Cd0A4b90855C2F38f7FcfE4eaA7); // USDC.e -> USDC pool\n\n (mimAmount, ) = PLATYPUS_ROUTER.swapTokensForTokens(tokenPath, poolPath, usdceAmount, 0, address(this), type(uint256).max);\n }\n\n // swap AVAX to MIM\n (uint256 reserve0, uint256 reserve1, ) = MIMAVAX.getReserves();\n uint256 mimFromAvax = _getAmountOut(avaxAmount, reserve1, reserve0);\n WAVAX.transfer(address(MIMAVAX), avaxAmount);\n MIMAVAX.swap(mimFromAvax, 0, address(this), new bytes(0));\n mimAmount += mimFromAvax;\n\n (, shareReturned) = DEGENBOX.deposit(MIM, address(this), recipient, mimAmount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "contracts/interfaces/platypus/IPlatypusRouter01.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.6.12;\n\ninterface IPlatypusRouter01 {\n function swapTokensForTokens(\n address[] calldata tokenPath,\n address[] calldata poolPath,\n uint256 fromAmount,\n uint256 minimumToAmount,\n address to,\n uint256 deadline\n ) external returns (uint256 amountOut, uint256 haircut);\n}\n" + }, + "contracts/swappers/Liquidations/StargatePlatypusSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\nimport \"../../interfaces/ISwapperGeneric.sol\";\nimport \"../../interfaces/IBentoBoxV1.sol\";\nimport \"../../interfaces/IERC20.sol\";\nimport \"../../interfaces/platypus/IPlatypusRouter01.sol\";\nimport \"../../interfaces/stargate/IStargateRouter.sol\";\nimport \"../../interfaces/stargate/IStargatePool.sol\";\n\n/// @notice Liquidation Swapper for Stargate LP using Platypus\ncontract StargatePlatypusSwapper is ISwapperGeneric {\n IBentoBoxV1 public immutable degenBox;\n IStargatePool public immutable pool;\n IStargateRouter public immutable stargateRouter;\n IPlatypusRouter01 public immutable platypusRouter;\n uint16 public immutable poolId;\n\n address[] public tokenPath;\n address[] public poolPath;\n\n /// @dev _tokenPath[0] must be Stargate Pool Underlying Token and last one MIM\n constructor(\n IBentoBoxV1 _degenBox,\n IStargatePool _pool,\n uint16 _poolId,\n IStargateRouter _stargateRouter,\n IPlatypusRouter01 _platypusRouter,\n address[] memory _tokenPath,\n address[] memory _poolPath\n ) {\n degenBox = _degenBox;\n pool = _pool;\n poolId = _poolId;\n stargateRouter = _stargateRouter;\n platypusRouter = _platypusRouter;\n\n for (uint256 i = 0; i < _tokenPath.length; i++) {\n tokenPath.push(_tokenPath[i]);\n }\n for (uint256 i = 0; i < _poolPath.length; i++) {\n poolPath.push(_poolPath[i]);\n }\n\n IERC20(_tokenPath[0]).approve(address(_platypusRouter), type(uint256).max);\n }\n\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n degenBox.withdraw(IERC20(address(pool)), address(this), address(this), 0, shareFrom);\n\n // use the full balance so it's easier to check if everything has been redeemed.\n uint256 amount = IERC20(address(pool)).balanceOf(address(this));\n\n // Stargate Pool LP -> Underlying Token\n stargateRouter.instantRedeemLocal(poolId, amount, address(this));\n require(IERC20(address(pool)).balanceOf(address(this)) == 0, \"Cannot fully redeem\");\n\n amount = IERC20(address(tokenPath[0])).balanceOf(address(this));\n\n // Stargate Pool Underlying Token -> MIM\n (amount, ) = platypusRouter.swapTokensForTokens(tokenPath, poolPath, amount, 0, address(degenBox), type(uint256).max);\n\n (, shareReturned) = degenBox.deposit(IERC20(tokenPath[tokenPath.length - 1]), address(degenBox), recipient, amount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "contracts/interfaces/stargate/IStargateRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n// solhint-disable contract-name-camelcase\n\npragma solidity >=0.7.6;\npragma abicoder v2;\n\ninterface IStargateRouter {\n struct lzTxObj {\n uint256 dstGasForCall;\n uint256 dstNativeAmount;\n bytes dstNativeAddr;\n }\n\n function addLiquidity(\n uint256 _poolId,\n uint256 _amountLD,\n address _to\n ) external;\n\n function swap(\n uint16 _dstChainId,\n uint256 _srcPoolId,\n uint256 _dstPoolId,\n address payable _refundAddress,\n uint256 _amountLD,\n uint256 _minAmountLD,\n lzTxObj memory _lzTxParams,\n bytes calldata _to,\n bytes calldata _payload\n ) external payable;\n\n function redeemRemote(\n uint16 _dstChainId,\n uint256 _srcPoolId,\n uint256 _dstPoolId,\n address payable _refundAddress,\n uint256 _amountLP,\n uint256 _minAmountLD,\n bytes calldata _to,\n lzTxObj memory _lzTxParams\n ) external payable;\n\n function instantRedeemLocal(\n uint16 _srcPoolId,\n uint256 _amountLP,\n address _to\n ) external returns (uint256);\n\n function redeemLocal(\n uint16 _dstChainId,\n uint256 _srcPoolId,\n uint256 _dstPoolId,\n address payable _refundAddress,\n uint256 _amountLP,\n bytes calldata _to,\n lzTxObj memory _lzTxParams\n ) external payable;\n\n function sendCredits(\n uint16 _dstChainId,\n uint256 _srcPoolId,\n uint256 _dstPoolId,\n address payable _refundAddress\n ) external payable;\n\n function quoteLayerZeroFee(\n uint16 _dstChainId,\n uint8 _functionType,\n bytes calldata _toAddress,\n bytes calldata _transferAndCallPayload,\n lzTxObj memory _lzTxParams\n ) external view returns (uint256, uint256);\n}\n" + }, + "contracts/interfaces/stargate/IStargatePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.6.12;\n\ninterface IStargatePool {\n function totalLiquidity() external view returns (uint256);\n\n function totalSupply() external view returns (uint256);\n\n function decimals() external view returns (uint256);\n\n function localDecimals() external view returns (uint256);\n\n function token() external view returns (address);\n}\n" + }, + "contracts/swappers/Liquidations/StargateCurveSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"../../interfaces/ISwapperGeneric.sol\";\nimport \"../../interfaces/IBentoBoxV1.sol\";\nimport \"../../interfaces/curve/ICurvePool.sol\";\nimport \"../../interfaces/stargate/IStargateRouter.sol\";\nimport \"../../interfaces/stargate/IStargatePool.sol\";\n\n/// @notice Liquidation Swapper for Stargate LP using Curve\ncontract StargateCurveSwapper is ISwapperGeneric {\n using Address for address;\n\n IBentoBoxV1 public immutable degenBox;\n IStargatePool public immutable pool;\n IStargateRouter public immutable stargateRouter;\n CurvePool public immutable curvePool;\n int128 public immutable curvePoolI;\n int128 public immutable curvePoolJ;\n uint16 public immutable poolId;\n IERC20 public immutable underlyingPoolToken;\n IERC20 public immutable mim;\n\n constructor(\n IBentoBoxV1 _degenBox,\n IStargatePool _pool,\n uint16 _poolId,\n IStargateRouter _stargateRouter,\n CurvePool _curvePool,\n int128 _curvePoolI,\n int128 _curvePoolJ\n ) {\n degenBox = _degenBox;\n pool = _pool;\n poolId = _poolId;\n stargateRouter = _stargateRouter;\n curvePool = _curvePool;\n curvePoolI = _curvePoolI;\n curvePoolJ = _curvePoolJ;\n mim = IERC20(_curvePool.coins(uint128(_curvePoolJ)));\n\n underlyingPoolToken = IERC20(_pool.token());\n\n // using safeApprove so that it works with USDT on mainnet not returning bool\n _safeApprove(underlyingPoolToken, address(_curvePool), type(uint256).max);\n }\n\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n degenBox.withdraw(IERC20(address(pool)), address(this), address(this), 0, shareFrom);\n\n // use the full balance so it's easier to check if everything has been redeemed.\n uint256 amount = IERC20(address(pool)).balanceOf(address(this));\n\n // Stargate Pool LP -> Underlying Token\n stargateRouter.instantRedeemLocal(poolId, amount, address(this));\n\n require(IERC20(address(pool)).balanceOf(address(this)) == 0, \"Cannot fully redeem\");\n\n amount = underlyingPoolToken.balanceOf(address(this));\n\n // Stargate Pool Underlying Token -> MIM\n amount = curvePool.exchange_underlying(curvePoolI, curvePoolJ, amount, 0, address(degenBox));\n\n (, shareReturned) = degenBox.deposit(mim, address(degenBox), recipient, amount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n\n /// @dev copied from @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol to avoid IERC20 naming conflict\n function _safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) private {\n // solhint-disable-next-line reason-string\n require((value == 0) || (token.allowance(address(this), spender) == 0), \"SafeERC20: approve from non-zero to non-zero allowance\");\n\n bytes memory returndata = address(token).functionCall(\n abi.encodeWithSelector(token.approve.selector, spender, value),\n \"SafeERC20: low-level call failed\"\n );\n if (returndata.length > 0) {\n // Return data is optional\n // solhint-disable-next-line reason-string\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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" + }, + "contracts/swappers/Leverage/StargatePlatypusLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\nimport \"../../interfaces/ILevSwapperGeneric.sol\";\nimport \"../../interfaces/IBentoBoxV1.sol\";\nimport \"../../interfaces/IERC20.sol\";\nimport \"../../interfaces/platypus/IPlatypusRouter01.sol\";\nimport \"../../interfaces/stargate/IStargateRouter.sol\";\nimport \"../../interfaces/stargate/IStargatePool.sol\";\n\n/// @notice Leverage Swapper for Stargate LP using Platypus\ncontract StargatePlatypusLevSwapper is ILevSwapperGeneric {\n IBentoBoxV1 public immutable degenBox;\n IStargatePool public immutable pool;\n IStargateRouter public immutable stargateRouter;\n IPlatypusRouter01 public immutable platypusRouter;\n uint256 public immutable poolId;\n address[] public tokenPath;\n address[] public poolPath;\n\n /// @dev _tokenPath[0] must be MIM and last one Stargate Pool Underlying Token\n constructor(\n IBentoBoxV1 _degenBox,\n IStargatePool _pool,\n uint256 _poolId,\n IStargateRouter _stargateRouter,\n IPlatypusRouter01 _platypusRouter,\n address[] memory _tokenPath,\n address[] memory _poolPath\n ) {\n degenBox = _degenBox;\n pool = _pool;\n poolId = _poolId;\n stargateRouter = _stargateRouter;\n platypusRouter = _platypusRouter;\n\n for (uint256 i = 0; i < _tokenPath.length; i++) {\n tokenPath.push(_tokenPath[i]);\n }\n for (uint256 i = 0; i < _poolPath.length; i++) {\n poolPath.push(_poolPath[i]);\n }\n\n IERC20(_tokenPath[0]).approve(address(_platypusRouter), type(uint256).max);\n IERC20(_tokenPath[_tokenPath.length - 1]).approve(address(_stargateRouter), type(uint256).max);\n IERC20(address(pool)).approve(address(_degenBox), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amount, ) = degenBox.withdraw(IERC20(tokenPath[0]), address(this), address(this), 0, shareFrom);\n\n // MIM -> Stargate Pool Underlying Token\n (amount, ) = platypusRouter.swapTokensForTokens(tokenPath, poolPath, amount, 0, address(this), type(uint256).max);\n\n // Underlying Token -> Stargate Pool LP\n stargateRouter.addLiquidity(poolId, amount, address(this));\n amount = IERC20(address(pool)).balanceOf(address(this));\n\n (, shareReturned) = degenBox.deposit(IERC20(address(pool)), address(this), recipient, amount, 0);\n extraShare = shareReturned - shareToMin;\n }\n}\n" + }, + "contracts/interfaces/ILevSwapperGeneric.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface ILevSwapperGeneric {\n /// @notice Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) external returns (uint256 extraShare, uint256 shareReturned);\n}\n" + }, + "contracts/swappers/Liquidations/MagicCRVSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"../../interfaces/IBentoBoxV1.sol\";\nimport \"../../interfaces/IERC20.sol\";\nimport \"../../interfaces/ISwapperGeneric.sol\";\n\ninterface IMagicCRV {\n function totalSupply() external view returns (uint256);\n\n function totalCRVTokens() external view returns (uint256);\n}\n\ninterface IMIMMagicCrvPool {\n function exchangeToMim(uint256 amountIn, address recipient) external returns (uint256 amountOut);\n}\n\ncontract MagicCRVSwapper is ISwapperGeneric {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public immutable magicCRV;\n\n constructor(\n IERC20 _magicCRV\n ) {\n magicCRV = _magicCRV;\n\n MIM.approve(address(DEGENBOX), type(uint256).max);\n }\n\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amount, ) = DEGENBOX.withdraw(magicCRV, address(this), address(this), 0, shareFrom);\n \n // TODO\n\n (, shareReturned) = DEGENBOX.deposit(MIM, address(DEGENBOX), recipient, amount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure override returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "contracts/swappers/Leverage/StargateCurveLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"../../interfaces/ILevSwapperGeneric.sol\";\nimport \"../../interfaces/IBentoBoxV1.sol\";\nimport \"../../interfaces/IERC20.sol\";\nimport \"../../interfaces/curve/ICurvePool.sol\";\nimport \"../../interfaces/stargate/IStargateRouter.sol\";\nimport \"../../interfaces/stargate/IStargatePool.sol\";\n\n/// @notice Leverage Swapper for Stargate LP using Curve\ncontract StargateCurveLevSwapper is ILevSwapperGeneric {\n using Address for address;\n\n IBentoBoxV1 public immutable degenBox;\n IStargatePool public immutable pool;\n IStargateRouter public immutable stargateRouter;\n CurvePool public immutable curvePool;\n int128 public immutable curvePoolI;\n int128 public immutable curvePoolJ;\n uint256 public immutable poolId;\n IERC20 public immutable underlyingPoolToken;\n IERC20 public immutable mim;\n\n constructor(\n IBentoBoxV1 _degenBox,\n IStargatePool _pool,\n uint16 _poolId,\n IStargateRouter _stargateRouter,\n CurvePool _curvePool,\n int128 _curvePoolI,\n int128 _curvePoolJ\n ) {\n degenBox = _degenBox;\n pool = _pool;\n poolId = _poolId;\n stargateRouter = _stargateRouter;\n curvePool = _curvePool;\n curvePoolI = _curvePoolI;\n curvePoolJ = _curvePoolJ;\n mim = IERC20(_curvePool.coins(uint128(_curvePoolI)));\n underlyingPoolToken = IERC20(_pool.token());\n\n mim.approve(address(_curvePool), type(uint256).max);\n _safeApprove(underlyingPoolToken, address(_stargateRouter), type(uint256).max);\n IERC20(address(pool)).approve(address(_degenBox), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amount, ) = degenBox.withdraw(mim, address(this), address(this), 0, shareFrom);\n\n // MIM -> Stargate Pool Underlying Token\n amount = curvePool.exchange_underlying(curvePoolI, curvePoolJ, amount, 0, address(this));\n\n // Underlying Token -> Stargate Pool LP\n stargateRouter.addLiquidity(poolId, amount, address(this));\n amount = IERC20(address(pool)).balanceOf(address(this));\n\n (, shareReturned) = degenBox.deposit(IERC20(address(pool)), address(this), recipient, amount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n /// @dev copied from @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol to avoid IERC20 naming conflict\n function _safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) private {\n // solhint-disable-next-line reason-string\n require((value == 0) || (token.allowance(address(this), spender) == 0), \"SafeERC20: approve from non-zero to non-zero allowance\");\n\n bytes memory returndata = address(token).functionCall(\n abi.encodeWithSelector(token.approve.selector, spender, value),\n \"SafeERC20: low-level call failed\"\n );\n if (returndata.length > 0) {\n // Return data is optional\n // solhint-disable-next-line reason-string\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "contracts/withdrawer/MultichainWithdrawer.sol": { + "content": "// SPDX-License-Identifier: MIXED\npragma solidity 0.8.10;\n\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\n\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\n// Edited by BoringCrypto\n\ncontract BoringOwnableData {\n address public owner;\n address public pendingOwner;\n}\n\ncontract BoringOwnable is BoringOwnableData {\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /// @notice `owner` defaults to msg.sender on construction.\n constructor() {\n owner = msg.sender;\n emit OwnershipTransferred(address(0), msg.sender);\n }\n\n /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.\n /// Can only be invoked by the current `owner`.\n /// @param newOwner Address of the new owner.\n /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\n /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\n function transferOwnership(\n address newOwner,\n bool direct,\n bool renounce\n ) public onlyOwner {\n if (direct) {\n // Checks\n require(newOwner != address(0) || renounce, \"Ownable: zero address\");\n\n // Effects\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n pendingOwner = address(0);\n } else {\n // Effects\n pendingOwner = newOwner;\n }\n }\n\n /// @notice Needs to be called by `pendingOwner` to claim ownership.\n function claimOwnership() public {\n address _pendingOwner = pendingOwner;\n\n // Checks\n require(msg.sender == _pendingOwner, \"Ownable: caller != pending owner\");\n\n // Effects\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = address(0);\n }\n\n /// @notice Only allows the `owner` to execute the function.\n modifier onlyOwner() {\n require(msg.sender == owner, \"Ownable: caller is not the owner\");\n _;\n }\n}\n\ninterface IERC20 {\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n function balanceOf(address account) external view returns (uint256);\n\n function approve(address spender, uint256 amount) external returns (bool);\n}\n\ninterface IBentoBoxV1 {\n function balanceOf(IERC20 token, address user) external view returns (uint256 share);\n\n function deposit(\n IERC20 token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n function toAmount(\n IERC20 token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n function toShare(\n IERC20 token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n function transfer(\n IERC20 token,\n address from,\n address to,\n uint256 share\n ) external;\n\n function withdraw(\n IERC20 token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n}\n\n// License-Identifier: MIT\n\ninterface Cauldron {\n function accrue() external;\n\n function withdrawFees() external;\n\n function accrueInfo()\n external\n view\n returns (\n uint64,\n uint128,\n uint64\n );\n\n function bentoBox() external returns (address);\n\n function setFeeTo(address newFeeTo) external;\n\n function feeTo() external returns (address);\n\n function masterContract() external returns (CauldronV1);\n}\n\ninterface CauldronV1 {\n function accrue() external;\n\n function withdrawFees() external;\n\n function accrueInfo() external view returns (uint64, uint128);\n\n function setFeeTo(address newFeeTo) external;\n\n function feeTo() external returns (address);\n\n function masterContract() external returns (CauldronV1);\n}\n\ninterface AnyswapRouter {\n function anySwapOut(\n address token,\n address to,\n uint256 amount,\n uint256 toChainID\n ) external;\n}\n\ncontract MultichainWithdrawer is BoringOwnable {\n event MimWithdrawn(uint256 amount);\n\n bytes4 private constant SIG_TRANSFER = 0xa9059cbb; // transfer(address,uint256)\n\n IBentoBoxV1 public immutable bentoBox;\n IBentoBoxV1 public immutable degenBox;\n IERC20 public immutable MIM;\n\n AnyswapRouter public immutable anyswapRouter;\n\n address public immutable mimProvider;\n address public immutable ethereumRecipient;\n\n CauldronV1[] public bentoBoxCauldronsV1;\n Cauldron[] public bentoBoxCauldronsV2;\n Cauldron[] public degenBoxCauldrons;\n\n constructor(\n IBentoBoxV1 bentoBox_,\n IBentoBoxV1 degenBox_,\n IERC20 mim,\n AnyswapRouter anyswapRouter_,\n address mimProvider_,\n address ethereumRecipient_,\n Cauldron[] memory bentoBoxCauldronsV2_,\n CauldronV1[] memory bentoBoxCauldronsV1_,\n Cauldron[] memory degenBoxCauldrons_\n ) {\n bentoBox = bentoBox_;\n degenBox = degenBox_;\n MIM = mim;\n anyswapRouter = anyswapRouter_;\n mimProvider = mimProvider_;\n ethereumRecipient = ethereumRecipient_;\n\n bentoBoxCauldronsV2 = bentoBoxCauldronsV2_;\n bentoBoxCauldronsV1 = bentoBoxCauldronsV1_;\n degenBoxCauldrons = degenBoxCauldrons_;\n\n MIM.approve(address(anyswapRouter), type(uint256).max);\n }\n\n function withdraw() public {\n uint256 length = bentoBoxCauldronsV2.length;\n for (uint256 i = 0; i < length; i++) {\n require(bentoBoxCauldronsV2[i].masterContract().feeTo() == address(this), \"wrong feeTo\");\n\n bentoBoxCauldronsV2[i].accrue();\n (, uint256 feesEarned, ) = bentoBoxCauldronsV2[i].accrueInfo();\n if (feesEarned > (bentoBox.toAmount(MIM, bentoBox.balanceOf(MIM, address(bentoBoxCauldronsV2[i])), false))) {\n MIM.transferFrom(mimProvider, address(bentoBox), feesEarned);\n bentoBox.deposit(MIM, address(bentoBox), address(bentoBoxCauldronsV2[i]), feesEarned, 0);\n }\n\n bentoBoxCauldronsV2[i].withdrawFees();\n }\n\n length = bentoBoxCauldronsV1.length;\n for (uint256 i = 0; i < length; i++) {\n require(bentoBoxCauldronsV1[i].masterContract().feeTo() == address(this), \"wrong feeTo\");\n\n bentoBoxCauldronsV1[i].accrue();\n (, uint256 feesEarned) = bentoBoxCauldronsV1[i].accrueInfo();\n if (feesEarned > (bentoBox.toAmount(MIM, bentoBox.balanceOf(MIM, address(bentoBoxCauldronsV1[i])), false))) {\n MIM.transferFrom(mimProvider, address(bentoBox), feesEarned);\n bentoBox.deposit(MIM, address(bentoBox), address(bentoBoxCauldronsV1[i]), feesEarned, 0);\n }\n bentoBoxCauldronsV1[i].withdrawFees();\n }\n\n length = degenBoxCauldrons.length;\n for (uint256 i = 0; i < length; i++) {\n require(degenBoxCauldrons[i].masterContract().feeTo() == address(this), \"wrong feeTo\");\n\n degenBoxCauldrons[i].accrue();\n (, uint256 feesEarned, ) = degenBoxCauldrons[i].accrueInfo();\n if (feesEarned > (degenBox.toAmount(MIM, degenBox.balanceOf(MIM, address(degenBoxCauldrons[i])), false))) {\n MIM.transferFrom(mimProvider, address(degenBox), feesEarned);\n degenBox.deposit(MIM, address(degenBox), address(degenBoxCauldrons[i]), feesEarned, 0);\n }\n degenBoxCauldrons[i].withdrawFees();\n }\n\n uint256 mimFromBentoBoxShare = address(bentoBox) != address(0) ? bentoBox.balanceOf(MIM, address(this)) : 0;\n uint256 mimFromDegenBoxShare = address(degenBox) != address(0) ? degenBox.balanceOf(MIM, address(this)) : 0;\n\n withdrawFromBentoBoxes(mimFromBentoBoxShare, mimFromDegenBoxShare);\n\n uint256 amountWithdrawn = MIM.balanceOf(address(this));\n bridgeMimToEthereum(amountWithdrawn);\n\n emit MimWithdrawn(amountWithdrawn);\n }\n\n function withdrawFromBentoBoxes(uint256 amountBentoboxShare, uint256 amountDegenBoxShare) public {\n if (amountBentoboxShare > 0) {\n bentoBox.withdraw(MIM, address(this), address(this), 0, amountBentoboxShare);\n }\n if (amountDegenBoxShare > 0) {\n degenBox.withdraw(MIM, address(this), address(this), 0, amountDegenBoxShare);\n }\n }\n\n function bridgeMimToEthereum(uint256 amount) public {\n // bridge all MIM to Ethereum, chainId 1\n anyswapRouter.anySwapOut(address(MIM), ethereumRecipient, amount, 1);\n }\n\n function rescueTokens(\n IERC20 token,\n address to,\n uint256 amount\n ) external onlyOwner {\n _safeTransfer(token, to, amount);\n }\n\n function addPool(Cauldron pool) external onlyOwner {\n _addPool(pool);\n }\n\n function addPoolV1(CauldronV1 pool) external onlyOwner {\n bentoBoxCauldronsV1.push(pool);\n }\n\n function addPools(Cauldron[] memory pools) external onlyOwner {\n for (uint256 i = 0; i < pools.length; i++) {\n _addPool(pools[i]);\n }\n }\n\n function _addPool(Cauldron pool) internal onlyOwner {\n require(address(pool) != address(0), \"invalid cauldron\");\n\n if (pool.bentoBox() == address(bentoBox)) {\n //do not allow doubles\n for (uint256 i = 0; i < bentoBoxCauldronsV2.length; i++) {\n require(bentoBoxCauldronsV2[i] != pool, \"already added\");\n }\n bentoBoxCauldronsV2.push(pool);\n } else if (pool.bentoBox() == address(degenBox)) {\n for (uint256 i = 0; i < degenBoxCauldrons.length; i++) {\n require(degenBoxCauldrons[i] != pool, \"already added\");\n }\n degenBoxCauldrons.push(pool);\n }\n }\n\n function _safeTransfer(\n IERC20 token,\n address to,\n uint256 amount\n ) internal {\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(SIG_TRANSFER, to, amount));\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"transfer failed\");\n }\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport './pool/IUniswapV3PoolImmutables.sol';\nimport './pool/IUniswapV3PoolState.sol';\nimport './pool/IUniswapV3PoolDerivedState.sol';\nimport './pool/IUniswapV3PoolActions.sol';\nimport './pool/IUniswapV3PoolOwnerActions.sol';\nimport './pool/IUniswapV3PoolEvents.sol';\n\n/// @title The interface for a Uniswap V3 Pool\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\n/// to the ERC20 specification\n/// @dev The pool interface is broken up into many smaller pieces\ninterface IUniswapV3Pool is\n IUniswapV3PoolImmutables,\n IUniswapV3PoolState,\n IUniswapV3PoolDerivedState,\n IUniswapV3PoolActions,\n IUniswapV3PoolOwnerActions,\n IUniswapV3PoolEvents\n{\n\n}\n" + }, + "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\npragma abicoder v2;\n\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\n\n/// @title Router token swapping functionality\n/// @notice Functions for swapping tokens via Uniswap V3\ninterface ISwapRouter is IUniswapV3SwapCallback {\n struct ExactInputSingleParams {\n address tokenIn;\n address tokenOut;\n uint24 fee;\n address recipient;\n uint256 deadline;\n uint256 amountIn;\n uint256 amountOutMinimum;\n uint160 sqrtPriceLimitX96;\n }\n\n /// @notice Swaps `amountIn` of one token for as much as possible of another token\n /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\n /// @return amountOut The amount of the received token\n function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\n\n struct ExactInputParams {\n bytes path;\n address recipient;\n uint256 deadline;\n uint256 amountIn;\n uint256 amountOutMinimum;\n }\n\n /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\n /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\n /// @return amountOut The amount of the received token\n function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\n\n struct ExactOutputSingleParams {\n address tokenIn;\n address tokenOut;\n uint24 fee;\n address recipient;\n uint256 deadline;\n uint256 amountOut;\n uint256 amountInMaximum;\n uint160 sqrtPriceLimitX96;\n }\n\n /// @notice Swaps as little as possible of one token for `amountOut` of another token\n /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\n /// @return amountIn The amount of the input token\n function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\n\n struct ExactOutputParams {\n bytes path;\n address recipient;\n uint256 deadline;\n uint256 amountOut;\n uint256 amountInMaximum;\n }\n\n /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\n /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\n /// @return amountIn The amount of the input token\n function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that never changes\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\ninterface IUniswapV3PoolImmutables {\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\n /// @return The contract address\n function factory() external view returns (address);\n\n /// @notice The first of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token0() external view returns (address);\n\n /// @notice The second of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token1() external view returns (address);\n\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\n /// @return The fee\n function fee() external view returns (uint24);\n\n /// @notice The pool tick spacing\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\n /// This value is an int24 to avoid casting even though it is always positive.\n /// @return The tick spacing\n function tickSpacing() external view returns (int24);\n\n /// @notice The maximum amount of position liquidity that can use any tick in the range\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\n /// @return The max amount of liquidity per tick\n function maxLiquidityPerTick() external view returns (uint128);\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that can change\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\n/// per transaction\ninterface IUniswapV3PoolState {\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\n /// when accessed externally.\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\n /// boundary.\n /// observationIndex The index of the last oracle observation that was written,\n /// observationCardinality The current maximum number of observations stored in the pool,\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\n /// feeProtocol The protocol fee for both tokens of the pool.\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\n /// unlocked Whether the pool is currently locked to reentrancy\n function slot0()\n external\n view\n returns (\n uint160 sqrtPriceX96,\n int24 tick,\n uint16 observationIndex,\n uint16 observationCardinality,\n uint16 observationCardinalityNext,\n uint8 feeProtocol,\n bool unlocked\n );\n\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\n /// @dev This value can overflow the uint256\n function feeGrowthGlobal0X128() external view returns (uint256);\n\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\n /// @dev This value can overflow the uint256\n function feeGrowthGlobal1X128() external view returns (uint256);\n\n /// @notice The amounts of token0 and token1 that are owed to the protocol\n /// @dev Protocol fees will never exceed uint128 max in either token\n function protocolFees() external view returns (uint128 token0, uint128 token1);\n\n /// @notice The currently in range liquidity available to the pool\n /// @dev This value has no relationship to the total liquidity across all ticks\n function liquidity() external view returns (uint128);\n\n /// @notice Look up information about a specific tick in the pool\n /// @param tick The tick to look up\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\n /// tick upper,\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\n /// a specific position.\n function ticks(int24 tick)\n external\n view\n returns (\n uint128 liquidityGross,\n int128 liquidityNet,\n uint256 feeGrowthOutside0X128,\n uint256 feeGrowthOutside1X128,\n int56 tickCumulativeOutside,\n uint160 secondsPerLiquidityOutsideX128,\n uint32 secondsOutside,\n bool initialized\n );\n\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\n function tickBitmap(int16 wordPosition) external view returns (uint256);\n\n /// @notice Returns the information about a position by the position's key\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\n /// @return _liquidity The amount of liquidity in the position,\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\n function positions(bytes32 key)\n external\n view\n returns (\n uint128 _liquidity,\n uint256 feeGrowthInside0LastX128,\n uint256 feeGrowthInside1LastX128,\n uint128 tokensOwed0,\n uint128 tokensOwed1\n );\n\n /// @notice Returns data about a specific observation index\n /// @param index The element of the observations array to fetch\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\n /// ago, rather than at a specific index in the array.\n /// @return blockTimestamp The timestamp of the observation,\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\n /// Returns initialized whether the observation has been initialized and the values are safe to use\n function observations(uint256 index)\n external\n view\n returns (\n uint32 blockTimestamp,\n int56 tickCumulative,\n uint160 secondsPerLiquidityCumulativeX128,\n bool initialized\n );\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that is not stored\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\n/// blockchain. The functions here may have variable gas costs.\ninterface IUniswapV3PoolDerivedState {\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\n /// you must call it with secondsAgos = [3600, 0].\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\n /// timestamp\n function observe(uint32[] calldata secondsAgos)\n external\n view\n returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\n\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\n /// snapshot is taken and the second snapshot is taken.\n /// @param tickLower The lower tick of the range\n /// @param tickUpper The upper tick of the range\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\n /// @return secondsInside The snapshot of seconds per liquidity for the range\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\n external\n view\n returns (\n int56 tickCumulativeInside,\n uint160 secondsPerLiquidityInsideX128,\n uint32 secondsInside\n );\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissionless pool actions\n/// @notice Contains pool methods that can be called by anyone\ninterface IUniswapV3PoolActions {\n /// @notice Sets the initial price for the pool\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\n function initialize(uint160 sqrtPriceX96) external;\n\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\n /// @param recipient The address for which the liquidity will be created\n /// @param tickLower The lower tick of the position in which to add liquidity\n /// @param tickUpper The upper tick of the position in which to add liquidity\n /// @param amount The amount of liquidity to mint\n /// @param data Any data that should be passed through to the callback\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\n function mint(\n address recipient,\n int24 tickLower,\n int24 tickUpper,\n uint128 amount,\n bytes calldata data\n ) external returns (uint256 amount0, uint256 amount1);\n\n /// @notice Collects tokens owed to a position\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\n /// @param recipient The address which should receive the fees collected\n /// @param tickLower The lower tick of the position for which to collect fees\n /// @param tickUpper The upper tick of the position for which to collect fees\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\n /// @return amount0 The amount of fees collected in token0\n /// @return amount1 The amount of fees collected in token1\n function collect(\n address recipient,\n int24 tickLower,\n int24 tickUpper,\n uint128 amount0Requested,\n uint128 amount1Requested\n ) external returns (uint128 amount0, uint128 amount1);\n\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\n /// @dev Fees must be collected separately via a call to #collect\n /// @param tickLower The lower tick of the position for which to burn liquidity\n /// @param tickUpper The upper tick of the position for which to burn liquidity\n /// @param amount How much liquidity to burn\n /// @return amount0 The amount of token0 sent to the recipient\n /// @return amount1 The amount of token1 sent to the recipient\n function burn(\n int24 tickLower,\n int24 tickUpper,\n uint128 amount\n ) external returns (uint256 amount0, uint256 amount1);\n\n /// @notice Swap token0 for token1, or token1 for token0\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\n /// @param recipient The address to receive the output of the swap\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\n /// @param data Any data to be passed through to the callback\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\n /// @param recipient The address which will receive the token0 and token1 amounts\n /// @param amount0 The amount of token0 to send\n /// @param amount1 The amount of token1 to send\n /// @param data Any data to be passed through to the callback\n function flash(\n address recipient,\n uint256 amount0,\n uint256 amount1,\n bytes calldata data\n ) external;\n\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\n /// the input observationCardinalityNext.\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\n function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissioned pool actions\n/// @notice Contains pool methods that may only be called by the factory owner\ninterface IUniswapV3PoolOwnerActions {\n /// @notice Set the denominator of the protocol's % share of the fees\n /// @param feeProtocol0 new protocol fee for token0 of the pool\n /// @param feeProtocol1 new protocol fee for token1 of the pool\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\n\n /// @notice Collect the protocol fee accrued to the pool\n /// @param recipient The address to which collected protocol fees should be sent\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\n /// @return amount0 The protocol fee collected in token0\n /// @return amount1 The protocol fee collected in token1\n function collectProtocol(\n address recipient,\n uint128 amount0Requested,\n uint128 amount1Requested\n ) external returns (uint128 amount0, uint128 amount1);\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Events emitted by a pool\n/// @notice Contains all events emitted by the pool\ninterface IUniswapV3PoolEvents {\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\n event Initialize(uint160 sqrtPriceX96, int24 tick);\n\n /// @notice Emitted when liquidity is minted for a given position\n /// @param sender The address that minted the liquidity\n /// @param owner The owner of the position and recipient of any minted liquidity\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount The amount of liquidity minted to the position range\n /// @param amount0 How much token0 was required for the minted liquidity\n /// @param amount1 How much token1 was required for the minted liquidity\n event Mint(\n address sender,\n address indexed owner,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount,\n uint256 amount0,\n uint256 amount1\n );\n\n /// @notice Emitted when fees are collected by the owner of a position\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\n /// @param owner The owner of the position for which fees are collected\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount0 The amount of token0 fees collected\n /// @param amount1 The amount of token1 fees collected\n event Collect(\n address indexed owner,\n address recipient,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount0,\n uint128 amount1\n );\n\n /// @notice Emitted when a position's liquidity is removed\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\n /// @param owner The owner of the position for which liquidity is removed\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount The amount of liquidity to remove\n /// @param amount0 The amount of token0 withdrawn\n /// @param amount1 The amount of token1 withdrawn\n event Burn(\n address indexed owner,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount,\n uint256 amount0,\n uint256 amount1\n );\n\n /// @notice Emitted by the pool for any swaps between token0 and token1\n /// @param sender The address that initiated the swap call, and that received the callback\n /// @param recipient The address that received the output of the swap\n /// @param amount0 The delta of the token0 balance of the pool\n /// @param amount1 The delta of the token1 balance of the pool\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\n /// @param liquidity The liquidity of the pool after the swap\n /// @param tick The log base 1.0001 of price of the pool after the swap\n event Swap(\n address indexed sender,\n address indexed recipient,\n int256 amount0,\n int256 amount1,\n uint160 sqrtPriceX96,\n uint128 liquidity,\n int24 tick\n );\n\n /// @notice Emitted by the pool for any flashes of token0/token1\n /// @param sender The address that initiated the swap call, and that received the callback\n /// @param recipient The address that received the tokens from flash\n /// @param amount0 The amount of token0 that was flashed\n /// @param amount1 The amount of token1 that was flashed\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\n event Flash(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1,\n uint256 paid0,\n uint256 paid1\n );\n\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\n /// just before a mint/swap/burn.\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\n event IncreaseObservationCardinalityNext(\n uint16 observationCardinalityNextOld,\n uint16 observationCardinalityNextNew\n );\n\n /// @notice Emitted when the protocol fee is changed by the pool\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\n /// @param feeProtocol0New The updated value of the token0 protocol fee\n /// @param feeProtocol1New The updated value of the token1 protocol fee\n event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\n\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\n /// @param sender The address that collects the protocol fees\n /// @param recipient The address that receives the collected protocol fees\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\n event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\n}\n" + }, + "@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Callback for IUniswapV3PoolActions#swap\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\ninterface IUniswapV3SwapCallback {\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external;\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Factory {\n event PairCreated(address indexed token0, address indexed token1, address pair, uint);\n\n function feeTo() external view returns (address);\n function feeToSetter() external view returns (address);\n function migrator() external view returns (address);\n\n function getPair(address tokenA, address tokenB) external view returns (address pair);\n function allPairs(uint) external view returns (address pair);\n function allPairsLength() external view returns (uint);\n\n function createPair(address tokenA, address tokenB) external returns (address pair);\n\n function setFeeTo(address) external;\n function setFeeToSetter(address) external;\n function setMigrator(address) external;\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/libraries/TransferHelper.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.6.0;\n\n// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false\nlibrary TransferHelper {\n function safeApprove(address token, address to, uint value) internal {\n // bytes4(keccak256(bytes('approve(address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');\n }\n\n function safeTransfer(address token, address to, uint value) internal {\n // bytes4(keccak256(bytes('transfer(address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');\n }\n\n function safeTransferFrom(address token, address from, address to, uint value) internal {\n // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');\n }\n\n function safeTransferETH(address to, uint value) internal {\n (bool success,) = to.call{value:value}(new bytes(0));\n require(success, 'TransferHelper: ETH_TRANSFER_FAILED');\n }\n}\n" + }, + "@uniswap/v3-core/contracts/libraries/SafeCast.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Safe casting methods\n/// @notice Contains methods for safely casting between types\nlibrary SafeCast {\n /// @notice Cast a uint256 to a uint160, revert on overflow\n /// @param y The uint256 to be downcasted\n /// @return z The downcasted integer, now type uint160\n function toUint160(uint256 y) internal pure returns (uint160 z) {\n require((z = uint160(y)) == y);\n }\n\n /// @notice Cast a int256 to a int128, revert on overflow or underflow\n /// @param y The int256 to be downcasted\n /// @return z The downcasted integer, now type int128\n function toInt128(int256 y) internal pure returns (int128 z) {\n require((z = int128(y)) == y);\n }\n\n /// @notice Cast a uint256 to a int256, revert on overflow\n /// @param y The uint256 to be casted\n /// @return z The casted integer, now type int256\n function toInt256(uint256 y) internal pure returns (int256 z) {\n require(y < 2**255);\n z = int256(y);\n }\n}\n" + }, + "@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.0;\n\n/// @title Optimized overflow and underflow safe math operations\n/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost\nlibrary LowGasSafeMath {\n /// @notice Returns x + y, reverts if sum overflows uint256\n /// @param x The augend\n /// @param y The addend\n /// @return z The sum of x and y\n function add(uint256 x, uint256 y) internal pure returns (uint256 z) {\n require((z = x + y) >= x);\n }\n\n /// @notice Returns x - y, reverts if underflows\n /// @param x The minuend\n /// @param y The subtrahend\n /// @return z The difference of x and y\n function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n require((z = x - y) <= x);\n }\n\n /// @notice Returns x * y, reverts if overflows\n /// @param x The multiplicand\n /// @param y The multiplier\n /// @return z The product of x and y\n function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {\n require(x == 0 || (z = x * y) / x == y);\n }\n\n /// @notice Returns x + y, reverts if overflows or underflows\n /// @param x The augend\n /// @param y The addend\n /// @return z The sum of x and y\n function add(int256 x, int256 y) internal pure returns (int256 z) {\n require((z = x + y) >= x == (y >= 0));\n }\n\n /// @notice Returns x - y, reverts if overflows or underflows\n /// @param x The minuend\n /// @param y The subtrahend\n /// @return z The difference of x and y\n function sub(int256 x, int256 y) internal pure returns (int256 z) {\n require((z = x - y) <= x == (y >= 0));\n }\n}\n" + }, + "contracts/swappers/Leverage/popsicle/PopsicleWETHUSDTLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router01.sol\";\n\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\";\n\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../libraries/UniswapV3OneSidedUsingUniV2.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\nimport \"../../../interfaces/Tether.sol\";\n\n/// @notice WETH/USDT Popsicle Leverage Swapper for Ethereum\ncontract PopsicleWETHUSDTLevSwapper {\n using LowGasSafeMath for uint256;\n\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n IPopsicle public immutable popsicle;\n\n CurvePool private constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IERC20 private constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n IERC20 private constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n Tether private constant USDT = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n IUniswapV2Pair private constant WETHUSDT = IUniswapV2Pair(0x06da0fd433C1A5d7a4faa01111c044910A184553);\n\n uint256 private constant MIN_USDT_IMBALANCE = 1e6;\n uint256 private constant MIN_WETH_IMBALANCE = 0.0002 ether;\n\n IUniswapV3Pool private immutable pool;\n\n constructor(IPopsicle _popsicle) {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n USDT.approve(address(_popsicle), type(uint256).max);\n WETH.approve(address(_popsicle), type(uint256).max);\n pool = IUniswapV3Pool(_popsicle.pool());\n popsicle = _popsicle;\n }\n\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 mimAmount, ) = DEGENBOX.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n // MIM -> USDT on Curve MIM3POOL\n MIM3POOL.exchange_underlying(0, 3, mimAmount, 0, address(this));\n uint256 usdtAmount = USDT.balanceOf(address(this)); // account for some amounts left from previous leverages\n\n // Swap Amount USDT -> WETH to provide optimal 50/50 liquidity\n // Use UniswapV2 pair to avoid changing V3 liquidity balance\n {\n (uint256 reserve0, uint256 reserve1, ) = WETHUSDT.getReserves();\n (uint160 sqrtRatioX, , , , , , ) = pool.slot0();\n\n (uint256 balance0, uint256 balance1) = UniswapV3OneSidedUsingUniV2.getAmountsToDeposit(\n UniswapV3OneSidedUsingUniV2.GetAmountsToDepositParams({\n sqrtRatioX: sqrtRatioX,\n tickLower: popsicle.tickLower(),\n tickUpper: popsicle.tickUpper(),\n totalAmountIn: usdtAmount,\n reserve0: reserve0,\n reserve1: reserve1,\n minToken0Imbalance: MIN_WETH_IMBALANCE,\n minToken1Imbalance: MIN_USDT_IMBALANCE,\n amountInIsToken0: false\n })\n );\n\n USDT.transfer(address(WETHUSDT), usdtAmount.sub(balance1));\n WETHUSDT.swap(balance0, 0, address(this), new bytes(0));\n }\n (uint256 shares, , ) = popsicle.deposit(WETH.balanceOf(address(this)), USDT.balanceOf(address(this)), address(DEGENBOX));\n (, shareReturned) = DEGENBOX.deposit(IERC20(address(popsicle)), address(DEGENBOX), recipient, shares, 0);\n extraShare = shareReturned - shareToMin;\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router01.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.6.2;\n\ninterface IUniswapV2Router01 {\n function factory() external pure returns (address);\n function WETH() external pure returns (address);\n\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 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 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 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 function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n uint liquidity,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountA, uint amountB);\n function removeLiquidityETHWithPermit(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountToken, uint amountETH);\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 function swapTokensForExactTokens(\n uint amountOut,\n uint amountInMax,\n address[] calldata path,\n address to,\n uint deadline\n ) external returns (uint[] memory amounts);\n function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)\n external\n payable\n returns (uint[] memory amounts);\n function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)\n external\n returns (uint[] memory amounts);\n function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)\n external\n returns (uint[] memory amounts);\n function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)\n external\n payable\n returns (uint[] memory amounts);\n\n function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);\n function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);\n function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);\n function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);\n function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);\n}" + }, + "contracts/libraries/UniswapV3OneSidedUsingUniV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\";\n\nimport \"./FullMath.sol\";\nimport \"./TickMath.sol\";\nimport \"./LiquidityAmounts.sol\";\n\nlibrary UniswapV3OneSidedUsingUniV2 {\n using LowGasSafeMath for uint256;\n\n uint256 private constant SWAP_IMBALANCE_MAX_PASS = 10;\n uint256 constant MULTIPLIER = 1e18;\n\n struct Cache {\n uint160 sqrtRatioX;\n uint160 sqrtRatioAX;\n uint160 sqrtRatioBX;\n uint256 amountIn0;\n uint256 amountIn1;\n uint256 balance0Left;\n uint256 balance1Left;\n uint256 tokenIntermediate;\n uint128 liquidity;\n }\n\n struct GetAmountsToDepositParams {\n uint160 sqrtRatioX;\n int24 tickLower;\n int24 tickUpper;\n bool amountInIsToken0;\n uint256 totalAmountIn;\n uint256 reserve0;\n uint256 reserve1;\n uint256 minToken0Imbalance;\n uint256 minToken1Imbalance;\n }\n\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn.mul(997);\n uint256 numerator = amountInWithFee.mul(reserveOut);\n uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n amountOut = numerator / denominator;\n }\n\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n uint256 denominator = reserveOut.sub(amountOut).mul(997);\n amountIn = (numerator / denominator).add(1);\n }\n\n function getAmountsToDeposit(GetAmountsToDepositParams memory parameters) internal pure returns (uint256 balance0, uint256 balance1) {\n Cache memory cache;\n cache.sqrtRatioX = parameters.sqrtRatioX;\n cache.sqrtRatioAX = TickMath.getSqrtRatioAtTick(parameters.tickLower);\n cache.sqrtRatioBX = TickMath.getSqrtRatioAtTick(parameters.tickUpper);\n\n uint256 distance = cache.sqrtRatioBX - cache.sqrtRatioAX;\n\n // The ratio of each token in the range. share0 + share1 = 1\n uint256 share0 = FullMath.mulDiv(cache.sqrtRatioBX - parameters.sqrtRatioX, MULTIPLIER, distance);\n uint256 share1 = FullMath.mulDiv(parameters.sqrtRatioX - cache.sqrtRatioAX, MULTIPLIER, distance);\n\n if (parameters.amountInIsToken0) {\n cache.tokenIntermediate = FullMath.mulDiv(parameters.totalAmountIn, share1, MULTIPLIER);\n balance0 = parameters.totalAmountIn.sub(cache.tokenIntermediate);\n balance1 = getAmountOut(cache.tokenIntermediate, parameters.reserve0, parameters.reserve1);\n\n _updateBalanceLeft(cache, balance0, balance1);\n\n for (uint256 i = 0; i < SWAP_IMBALANCE_MAX_PASS; i++) {\n if (cache.balance0Left <= parameters.minToken0Imbalance && cache.balance1Left <= parameters.minToken1Imbalance) {\n break;\n }\n\n if (cache.balance0Left.mul(cache.amountIn1) > cache.balance1Left.mul(cache.amountIn0)) {\n cache.tokenIntermediate = FullMath.mulDiv(cache.balance0Left, share1, MULTIPLIER);\n balance0 = balance0.sub(cache.tokenIntermediate);\n balance1 = getAmountOut(parameters.totalAmountIn.sub(balance0), parameters.reserve0, parameters.reserve1);\n\n _updateBalanceLeft(cache, balance0, balance1);\n }\n if (cache.balance0Left.mul(cache.amountIn1) < cache.balance1Left.mul(cache.amountIn0)) {\n cache.tokenIntermediate = FullMath.mulDiv(cache.balance1Left, share0, MULTIPLIER);\n balance1 = balance1.sub(cache.tokenIntermediate);\n uint256 amountIn = getAmountIn(balance1, parameters.reserve1, parameters.reserve0);\n balance0 = parameters.totalAmountIn.sub(amountIn);\n\n _updateBalanceLeft(cache, balance0, balance1);\n }\n }\n } else {\n cache.tokenIntermediate = FullMath.mulDiv(parameters.totalAmountIn, share0, MULTIPLIER);\n balance0 = getAmountOut(cache.tokenIntermediate, parameters.reserve1, parameters.reserve0);\n balance1 = parameters.totalAmountIn.sub(cache.tokenIntermediate);\n\n _updateBalanceLeft(cache, balance0, balance1);\n\n for (uint256 i = 0; i < SWAP_IMBALANCE_MAX_PASS; i++) {\n if (cache.balance0Left <= parameters.minToken0Imbalance && cache.balance1Left <= parameters.minToken1Imbalance) {\n break;\n }\n\n if (cache.balance0Left.mul(cache.amountIn1) > cache.balance1Left.mul(cache.amountIn0)) {\n cache.tokenIntermediate = FullMath.mulDiv(cache.balance0Left, share1, MULTIPLIER);\n balance0 = balance0.sub(cache.tokenIntermediate);\n uint256 amountIn = getAmountIn(balance0, parameters.reserve1, parameters.reserve0);\n balance1 = parameters.totalAmountIn.sub(amountIn);\n\n _updateBalanceLeft(cache, balance0, balance1);\n }\n\n if (cache.balance0Left.mul(cache.amountIn1) < cache.balance1Left.mul(cache.amountIn0)) {\n cache.tokenIntermediate = FullMath.mulDiv(cache.balance1Left, share0, MULTIPLIER);\n balance1 = balance1.sub(cache.tokenIntermediate);\n balance0 = getAmountOut(parameters.totalAmountIn.sub(balance1), parameters.reserve1, parameters.reserve0);\n\n _updateBalanceLeft(cache, balance0, balance1);\n }\n }\n }\n }\n\n function _updateBalanceLeft(\n Cache memory cache,\n uint256 balance0,\n uint256 balance1\n ) private pure {\n cache.liquidity = LiquidityAmounts.getLiquidityForAmounts(\n cache.sqrtRatioX,\n cache.sqrtRatioAX,\n cache.sqrtRatioBX,\n balance0,\n balance1\n );\n (cache.amountIn0, cache.amountIn1) = LiquidityAmounts.getAmountsForLiquidity(\n cache.sqrtRatioX,\n cache.sqrtRatioAX,\n cache.sqrtRatioBX,\n cache.liquidity\n );\n\n cache.balance0Left = balance0.sub(cache.amountIn0);\n cache.balance1Left = balance1.sub(cache.amountIn1);\n }\n}\n" + }, + "contracts/libraries/FullMath.sol": { + "content": "// SPDX-License-Identifier: CC-BY-4.0\npragma solidity >=0.8.0;\n\nlibrary FullMath {\n /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n /// @param a The multiplicand\n /// @param b The multiplier\n /// @param denominator The divisor\n /// @return result The 256-bit result\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\n function mulDiv(\n uint256 a,\n uint256 b,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n // 512-bit multiply [prod1 prod0] = a * b\n // Compute the product mod 2**256 and mod 2**256 - 1\n // then use the Chinese Remainder Theorem to reconstruct\n // the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2**256 + prod0\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(a, b, not(0))\n prod0 := mul(a, b)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division\n if (prod1 == 0) {\n require(denominator > 0);\n assembly {\n result := div(prod0, denominator)\n }\n return result;\n }\n\n // Make sure the result is less than 2**256.\n // Also prevents denominator == 0\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0]\n // Compute remainder using mulmod\n uint256 remainder;\n assembly {\n remainder := mulmod(a, b, denominator)\n }\n // Subtract 256 bit number from 512 bit number\n assembly {\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator\n // Compute largest power of two divisor of denominator.\n // Always >= 1.\n unchecked {\n uint256 twos = (type(uint256).max - denominator + 1) & denominator;\n // Divide denominator by power of two\n assembly {\n denominator := div(denominator, twos)\n }\n\n // Divide [prod1 prod0] by the factors of two\n assembly {\n prod0 := div(prod0, twos)\n }\n // Shift in bits from prod1 into prod0. For this we need\n // to flip `twos` such that it is 2**256 / twos.\n // If twos is zero, then it becomes one\n assembly {\n twos := add(div(sub(0, twos), twos), 1)\n }\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2**256\n // Now that denominator is an odd number, it has an inverse\n // modulo 2**256 such that denominator * inv = 1 mod 2**256.\n // Compute the inverse by starting with a seed that is correct\n // correct for four bits. That is, denominator * inv = 1 mod 2**4\n uint256 inv = (3 * denominator) ^ 2;\n // Now use Newton-Raphson iteration to improve the precision.\n // Thanks to Hensel's lifting lemma, this also works in modular\n // arithmetic, doubling the correct bits in each step.\n inv *= 2 - denominator * inv; // inverse mod 2**8\n inv *= 2 - denominator * inv; // inverse mod 2**16\n inv *= 2 - denominator * inv; // inverse mod 2**32\n inv *= 2 - denominator * inv; // inverse mod 2**64\n inv *= 2 - denominator * inv; // inverse mod 2**128\n inv *= 2 - denominator * inv; // inverse mod 2**256\n\n // Because the division is now exact we can divide by multiplying\n // with the modular inverse of denominator. This will give us the\n // correct result modulo 2**256. Since the precoditions guarantee\n // that the outcome is less than 2**256, this is the final result.\n // We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inv;\n return result;\n }\n }\n}\n" + }, + "contracts/libraries/TickMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.8.0;\n\n/// @title Math library for computing sqrt prices from ticks and vice versa\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\n/// prices between 2**-128 and 2**128\nlibrary TickMath {\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\n int24 internal constant MIN_TICK = -887272;\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\n int24 internal constant MAX_TICK = -MIN_TICK;\n\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\n uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\n /// @dev Throws if |tick| > max tick\n /// @param tick The input tick for the above formula\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\n /// at the given tick\n function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\n uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\n require(absTick <= uint256(int256(MAX_TICK)), 'T');\n\n uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\n if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\n if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\n if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\n if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\n if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\n if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\n if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\n if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\n if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\n if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\n if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\n if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\n if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\n if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\n if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\n if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\n if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\n if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\n if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\n\n if (tick > 0) ratio = type(uint256).max / ratio;\n\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\n // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\n sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\n }\n\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\n /// ever return.\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\n function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\n // second inequality must be < because the price can never reach the price at the max tick\n require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');\n uint256 ratio = uint256(sqrtPriceX96) << 32;\n\n uint256 r = ratio;\n uint256 msb = 0;\n\n assembly {\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(5, gt(r, 0xFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(4, gt(r, 0xFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(3, gt(r, 0xFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(2, gt(r, 0xF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(1, gt(r, 0x3))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := gt(r, 0x1)\n msb := or(msb, f)\n }\n\n if (msb >= 128) r = ratio >> (msb - 127);\n else r = ratio << (127 - msb);\n\n int256 log_2 = (int256(msb) - 128) << 64;\n\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(63, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(62, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(61, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(60, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(59, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(58, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(57, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(56, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(55, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(54, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(53, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(52, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(51, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(50, f))\n }\n\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\n\n int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\n int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\n\n tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\n }\n}\n" + }, + "contracts/libraries/LiquidityAmounts.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.8.0;\n\nimport \"@uniswap/v3-core/contracts/libraries/FixedPoint96.sol\";\nimport \"./FullMath.sol\";\n\n/// @title Liquidity amount functions\n/// @notice Provides functions for computing liquidity amounts from token amounts and prices\nlibrary LiquidityAmounts {\n /// @notice Downcasts uint256 to uint128\n /// @param x The uint258 to be downcasted\n /// @return y The passed value, downcasted to uint128\n function toUint128(uint256 x) private pure returns (uint128 y) {\n require((y = uint128(x)) == x);\n }\n\n /// @notice Computes the amount of liquidity received for a given amount of token0 and price range\n /// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n /// @param amount0 The amount0 being sent in\n /// @return liquidity The amount of returned liquidity\n function getLiquidityForAmount0(\n uint160 sqrtRatioAX96,\n uint160 sqrtRatioBX96,\n uint256 amount0\n ) internal pure returns (uint128 liquidity) {\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n uint256 intermediate = FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);\n return toUint128(FullMath.mulDiv(amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96));\n }\n\n /// @notice Computes the amount of liquidity received for a given amount of token1 and price range\n /// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n /// @param amount1 The amount1 being sent in\n /// @return liquidity The amount of returned liquidity\n function getLiquidityForAmount1(\n uint160 sqrtRatioAX96,\n uint160 sqrtRatioBX96,\n uint256 amount1\n ) internal pure returns (uint128 liquidity) {\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n return toUint128(FullMath.mulDiv(amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96));\n }\n\n /// @notice Computes the maximum amount of liquidity received for a given amount of token0, token1, the current\n /// pool prices and the prices at the tick boundaries\n /// @param sqrtRatioX96 A sqrt price representing the current pool prices\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n /// @param amount0 The amount of token0 being sent in\n /// @param amount1 The amount of token1 being sent in\n /// @return liquidity The maximum amount of liquidity received\n function getLiquidityForAmounts(\n uint160 sqrtRatioX96,\n uint160 sqrtRatioAX96,\n uint160 sqrtRatioBX96,\n uint256 amount0,\n uint256 amount1\n ) internal pure returns (uint128 liquidity) {\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n if (sqrtRatioX96 <= sqrtRatioAX96) {\n liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);\n } else if (sqrtRatioX96 < sqrtRatioBX96) {\n uint128 liquidity0 = getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);\n uint128 liquidity1 = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);\n\n liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\n } else {\n liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);\n }\n }\n\n /// @notice Computes the amount of token0 for a given amount of liquidity and a price range\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n /// @param liquidity The liquidity being valued\n /// @return amount0 The amount of token0\n function getAmount0ForLiquidity(\n uint160 sqrtRatioAX96,\n uint160 sqrtRatioBX96,\n uint128 liquidity\n ) internal pure returns (uint256 amount0) {\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n return\n FullMath.mulDiv(\n uint256(liquidity) << FixedPoint96.RESOLUTION,\n sqrtRatioBX96 - sqrtRatioAX96,\n sqrtRatioBX96\n ) / sqrtRatioAX96;\n }\n\n /// @notice Computes the amount of token1 for a given amount of liquidity and a price range\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n /// @param liquidity The liquidity being valued\n /// @return amount1 The amount of token1\n function getAmount1ForLiquidity(\n uint160 sqrtRatioAX96,\n uint160 sqrtRatioBX96,\n uint128 liquidity\n ) internal pure returns (uint256 amount1) {\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n return FullMath.mulDiv(liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96);\n }\n\n /// @notice Computes the token0 and token1 value for a given amount of liquidity, the current\n /// pool prices and the prices at the tick boundaries\n /// @param sqrtRatioX96 A sqrt price representing the current pool prices\n /// @param sqrtRatioAX96 A sqrt price representing the first tick boundary\n /// @param sqrtRatioBX96 A sqrt price representing the second tick boundary\n /// @param liquidity The liquidity being valued\n /// @return amount0 The amount of token0\n /// @return amount1 The amount of token1\n function getAmountsForLiquidity(\n uint160 sqrtRatioX96,\n uint160 sqrtRatioAX96,\n uint160 sqrtRatioBX96,\n uint128 liquidity\n ) internal pure returns (uint256 amount0, uint256 amount1) {\n if (sqrtRatioAX96 > sqrtRatioBX96) (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);\n\n if (sqrtRatioX96 <= sqrtRatioAX96) {\n amount0 = getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\n } else if (sqrtRatioX96 < sqrtRatioBX96) {\n amount0 = getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);\n amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);\n } else {\n amount1 = getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);\n }\n }\n}\n" + }, + "@uniswap/v3-core/contracts/libraries/FixedPoint96.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.4.0;\n\n/// @title FixedPoint96\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\n/// @dev Used in SqrtPriceMath.sol\nlibrary FixedPoint96 {\n uint8 internal constant RESOLUTION = 96;\n uint256 internal constant Q96 = 0x1000000000000000000000000;\n}\n" + }, + "contracts/swappers/Leverage/popsicle/PopsicleUSDCWETHLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router01.sol\";\n\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport \"@uniswap/v3-core/contracts/libraries/LowGasSafeMath.sol\";\n\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../libraries/UniswapV3OneSidedUsingUniV2.sol\";\n\ninterface IERC20 {\n function balanceOf(address account) external view returns (uint256);\n\n function approve(address spender, uint256 amount) external returns (bool);\n\n function transfer(address recipient, uint256 amount) external returns (bool);\n}\n\ninterface IBentoBoxV1 {\n function withdraw(\n IERC20 token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256, uint256);\n\n function deposit(\n IERC20 token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256, uint256);\n}\n\ninterface CurvePool {\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address receiver\n ) external returns (uint256);\n}\n\n/// @notice USDC/WETH Popsicle Leverage Swapper for Ethereum\ncontract PopsicleUSDCWETHLevSwapper {\n using LowGasSafeMath for uint256;\n\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n IPopsicle public immutable popsicle;\n\n CurvePool private constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IERC20 private constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n IERC20 private constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n IERC20 private constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n IUniswapV2Pair private constant USDCWETH = IUniswapV2Pair(0x397FF1542f962076d0BFE58eA045FfA2d347ACa0);\n\n uint256 private constant MIN_USDC_IMBALANCE = 1e6;\n uint256 private constant MIN_WETH_IMBALANCE = 0.0002 ether;\n\n IUniswapV3Pool private immutable pool;\n\n constructor(IPopsicle _popsicle) {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n USDC.approve(address(_popsicle), type(uint256).max);\n WETH.approve(address(_popsicle), type(uint256).max);\n pool = IUniswapV3Pool(_popsicle.pool());\n popsicle = _popsicle;\n }\n\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 mimAmount, ) = DEGENBOX.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n // MIM -> USDC on Curve MIM3POOL\n MIM3POOL.exchange_underlying(0, 2, mimAmount, 0, address(this));\n uint256 usdcAmount = USDC.balanceOf(address(this)); // account for some amounts left from previous leverages\n\n // Swap Amount USDC -> WETH to provide optimal 50/50 liquidity\n // Use UniswapV2 pair to avoid changing V3 liquidity balance\n {\n (uint256 reserve0, uint256 reserve1, ) = USDCWETH.getReserves();\n (uint160 sqrtRatioX, , , , , , ) = pool.slot0();\n\n (uint256 balance0, uint256 balance1) = UniswapV3OneSidedUsingUniV2.getAmountsToDeposit(\n UniswapV3OneSidedUsingUniV2.GetAmountsToDepositParams({\n sqrtRatioX: sqrtRatioX,\n tickLower: popsicle.tickLower(),\n tickUpper: popsicle.tickUpper(),\n totalAmountIn: usdcAmount,\n reserve0: reserve0,\n reserve1: reserve1,\n minToken0Imbalance: MIN_USDC_IMBALANCE,\n minToken1Imbalance: MIN_WETH_IMBALANCE,\n amountInIsToken0: true\n })\n );\n USDC.transfer(address(USDCWETH), usdcAmount.sub(balance0));\n USDCWETH.swap(0, balance1, address(this), new bytes(0));\n }\n\n (uint256 shares, , ) = popsicle.deposit(USDC.balanceOf(address(this)), WETH.balanceOf(address(this)), address(DEGENBOX));\n\n (, shareReturned) = DEGENBOX.deposit(IERC20(address(popsicle)), address(DEGENBOX), recipient, shares, 0);\n extraShare = shareReturned - shareToMin;\n }\n}\n" + }, + "contracts/swappers/Liquidations/popsicle/PopsicleWBTCWETHSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@rari-capital/solmate/src/tokens/ERC20.sol\";\nimport \"@rari-capital/solmate/src/utils/SafeTransferLib.sol\";\n\nimport \"../../../interfaces/ISwapperGeneric.sol\";\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\nimport \"../../../interfaces/curve/ICurveThreeCryptoPool.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\n\n/// @notice WBTC/WETH Popsicle Swapper for Ethereum\ncontract PopsicleWBTCWETHSwapper is ISwapperGeneric {\n using SafeTransferLib for ERC20;\n\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurveThreeCryptoPool public constant THREECRYPTO = CurveThreeCryptoPool(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 private constant WBTC = IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);\n IERC20 public constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n ERC20 private constant USDT = ERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n IPopsicle public immutable popsicle;\n\n constructor(IPopsicle _popsicle) {\n popsicle = _popsicle;\n WBTC.approve(address(THREECRYPTO), type(uint256).max);\n WETH.approve(address(THREECRYPTO), type(uint256).max);\n USDT.safeApprove(address(MIM3POOL), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amountFrom, ) = DEGENBOX.withdraw(IERC20(address(popsicle)), address(this), address(this), 0, shareFrom);\n (uint256 wbtcAmount, uint256 wethAmount) = popsicle.withdraw(amountFrom, address(this));\n\n // WBTC -> USDT\n THREECRYPTO.exchange(1, 0, wbtcAmount, 0);\n\n // WETH -> USDT\n THREECRYPTO.exchange(2, 0, wethAmount, 0);\n\n // USDT -> MIM\n uint256 mimAmount = MIM3POOL.exchange_underlying(3, 0, USDT.balanceOf(address(this)), 0, address(DEGENBOX));\n\n (, shareReturned) = DEGENBOX.deposit(MIM, address(DEGENBOX), recipient, mimAmount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure virtual returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "@rari-capital/solmate/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @author Modified from Gnosis (https://github.com/gnosis/gp-v2-contracts/blob/main/src/contracts/libraries/GPv2SafeERC20.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\nlibrary SafeTransferLib {\n /*///////////////////////////////////////////////////////////////\n ETH OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferETH(address to, uint256 amount) internal {\n bool callStatus;\n\n assembly {\n // Transfer the ETH and store if it succeeded or not.\n callStatus := call(gas(), to, amount, 0, 0, 0, 0)\n }\n\n require(callStatus, \"ETH_TRANSFER_FAILED\");\n }\n\n /*///////////////////////////////////////////////////////////////\n ERC20 OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferFrom(\n ERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n bool callStatus;\n\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata to memory piece by piece:\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.\n mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the \"from\" argument.\n mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the \"to\" argument.\n mstore(add(freeMemoryPointer, 68), amount) // Finally append the \"amount\" argument. No mask as it's a full 32 byte value.\n\n // Call the token and store if it succeeded or not.\n // We use 100 because the calldata length is 4 + 32 * 3.\n callStatus := call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)\n }\n\n require(didLastOptionalReturnCallSucceed(callStatus), \"TRANSFER_FROM_FAILED\");\n }\n\n function safeTransfer(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool callStatus;\n\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata to memory piece by piece:\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.\n mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Finally append the \"amount\" argument. No mask as it's a full 32 byte value.\n\n // Call the token and store if it succeeded or not.\n // We use 68 because the calldata length is 4 + 32 * 2.\n callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)\n }\n\n require(didLastOptionalReturnCallSucceed(callStatus), \"TRANSFER_FAILED\");\n }\n\n function safeApprove(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool callStatus;\n\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata to memory piece by piece:\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) // Begin with the function selector.\n mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Finally append the \"amount\" argument. No mask as it's a full 32 byte value.\n\n // Call the token and store if it succeeded or not.\n // We use 68 because the calldata length is 4 + 32 * 2.\n callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)\n }\n\n require(didLastOptionalReturnCallSucceed(callStatus), \"APPROVE_FAILED\");\n }\n\n /*///////////////////////////////////////////////////////////////\n INTERNAL HELPER LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function didLastOptionalReturnCallSucceed(bool callStatus) private pure returns (bool success) {\n assembly {\n // Get how many bytes the call returned.\n let returnDataSize := returndatasize()\n\n // If the call reverted:\n if iszero(callStatus) {\n // Copy the revert message into memory.\n returndatacopy(0, 0, returnDataSize)\n\n // Revert with the same message.\n revert(0, returnDataSize)\n }\n\n switch returnDataSize\n case 32 {\n // Copy the return data into memory.\n returndatacopy(0, 0, returnDataSize)\n\n // Set success to whether it returned true.\n success := iszero(iszero(mload(0)))\n }\n case 0 {\n // There was no return data.\n success := 1\n }\n default {\n // It returned some malformed input.\n success := 0\n }\n }\n }\n}\n" + }, + "contracts/swappers/Leverage/popsicle/PopsicleWBTCWETHLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\n\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../libraries/UniswapV3OneSidedUsingCurve.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\nimport \"../../../interfaces/curve/ICurveThreeCryptoPool.sol\";\nimport \"../../../interfaces/Tether.sol\";\n\n/// @notice WBTC/WETH Popsicle Leverage Swapper for Ethereum\ncontract PopsicleWBTCWETHLevSwapper {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n IPopsicle public immutable popsicle;\n\n CurvePool private constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurveThreeCryptoPool public constant THREECRYPTO = CurveThreeCryptoPool(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n IERC20 private constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 private constant WBTC = IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);\n IERC20 public constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n Tether private constant USDT = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n uint256 private constant MIN_WBTC_IMBALANCE = 1e3; // 0.00001 wBTC\n uint256 private constant MIN_WETH_IMBALANCE = 0.0002 ether;\n\n IUniswapV3Pool private immutable pool;\n\n constructor(IPopsicle _popsicle) {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n WBTC.approve(address(_popsicle), type(uint256).max);\n WETH.approve(address(_popsicle), type(uint256).max);\n WBTC.approve(address(THREECRYPTO), type(uint256).max);\n USDT.approve(address(THREECRYPTO), type(uint256).max);\n pool = IUniswapV3Pool(_popsicle.pool());\n popsicle = _popsicle;\n }\n\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 mimAmount, ) = DEGENBOX.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n // MIM -> USDT\n MIM3POOL.exchange_underlying(0, 3, mimAmount, 0, address(this));\n\n // USDT -> WBTC\n THREECRYPTO.exchange(0, 1, USDT.balanceOf(address(this)), 0);\n uint256 wbtcAmount = WBTC.balanceOf(address(this));\n\n {\n (uint160 sqrtRatioX, , , , , , ) = pool.slot0();\n\n (uint256 balance0, ) = UniswapV3OneSidedUsingCurve.getAmountsToDeposit(\n UniswapV3OneSidedUsingCurve.GetAmountsToDepositParams({\n sqrtRatioX: sqrtRatioX,\n tickLower: popsicle.tickLower(),\n tickUpper: popsicle.tickUpper(),\n totalAmountIn: wbtcAmount,\n i: 1,\n j: 2,\n pool: address(THREECRYPTO),\n selector: CurveThreeCryptoPool.get_dy.selector,\n minToken0Imbalance: MIN_WBTC_IMBALANCE,\n minToken1Imbalance: MIN_WETH_IMBALANCE,\n amountInIsToken0: true\n })\n );\n\n THREECRYPTO.exchange(1, 2, wbtcAmount - balance0, 0);\n }\n\n (uint256 shares, , ) = popsicle.deposit(WBTC.balanceOf(address(this)), WETH.balanceOf(address(this)), address(DEGENBOX));\n (, shareReturned) = DEGENBOX.deposit(IERC20(address(popsicle)), address(DEGENBOX), recipient, shares, 0);\n extraShare = shareReturned - shareToMin;\n }\n}\n" + }, + "contracts/libraries/UniswapV3OneSidedUsingCurve.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"./FullMath.sol\";\nimport \"./TickMath.sol\";\nimport \"./LiquidityAmounts.sol\";\nimport \"../interfaces/curve/ICurvePool.sol\";\n\nlibrary UniswapV3OneSidedUsingCurve {\n uint256 private constant SWAP_IMBALANCE_MAX_PASS = 10;\n uint256 constant MULTIPLIER = 1e18;\n\n struct Cache {\n uint160 sqrtRatioX;\n uint160 sqrtRatioAX;\n uint160 sqrtRatioBX;\n uint256 amountIn0;\n uint256 amountIn1;\n uint256 balance0Left;\n uint256 balance1Left;\n uint256 tokenIntermediate;\n uint128 liquidity;\n }\n\n struct GetAmountsToDepositParams {\n uint160 sqrtRatioX;\n int24 tickLower;\n int24 tickUpper;\n bool amountInIsToken0;\n int8 i;\n int8 j;\n address pool;\n bytes4 selector; // curve pool function selector for get_dy/get_dy_underlying.\n uint256 totalAmountIn;\n uint256 minToken0Imbalance;\n uint256 minToken1Imbalance;\n }\n\n function get_dy(\n address pool,\n bytes4 selector,\n int8 i,\n int8 j,\n uint256 dx\n ) internal view returns (uint256) {\n (bool success, bytes memory data) = pool.staticcall(abi.encodeWithSelector(selector, i, j, dx));\n require(success, \"call failed\");\n return (abi.decode(data, (uint256)));\n }\n\n function getAmountsToDeposit(GetAmountsToDepositParams memory parameters) internal view returns (uint256 balance0, uint256 balance1) {\n Cache memory cache;\n cache.sqrtRatioX = parameters.sqrtRatioX;\n cache.sqrtRatioAX = TickMath.getSqrtRatioAtTick(parameters.tickLower);\n cache.sqrtRatioBX = TickMath.getSqrtRatioAtTick(parameters.tickUpper);\n\n uint256 distance = cache.sqrtRatioBX - cache.sqrtRatioAX;\n\n // The ratio of each token in the range. share0 + share1 = 1\n uint256 share0 = FullMath.mulDiv(cache.sqrtRatioBX - parameters.sqrtRatioX, MULTIPLIER, distance);\n uint256 share1 = FullMath.mulDiv(parameters.sqrtRatioX - cache.sqrtRatioAX, MULTIPLIER, distance);\n\n if (parameters.amountInIsToken0) {\n cache.tokenIntermediate = FullMath.mulDiv(parameters.totalAmountIn, share1, MULTIPLIER);\n balance0 = parameters.totalAmountIn - cache.tokenIntermediate;\n balance1 = get_dy(parameters.pool, parameters.selector, parameters.i, parameters.j, cache.tokenIntermediate);\n\n _updateBalanceLeft(cache, balance0, balance1);\n for (uint256 i = 0; i < SWAP_IMBALANCE_MAX_PASS; i++) {\n if (cache.balance0Left <= parameters.minToken0Imbalance && cache.balance1Left <= parameters.minToken1Imbalance) {\n break;\n }\n\n if (cache.balance0Left * cache.amountIn1 > cache.balance1Left * cache.amountIn0) {\n cache.tokenIntermediate = FullMath.mulDiv(cache.balance0Left, share1, MULTIPLIER);\n balance0 = balance0 - cache.tokenIntermediate;\n balance1 = get_dy(\n parameters.pool,\n parameters.selector,\n parameters.i,\n parameters.j,\n parameters.totalAmountIn - balance0\n );\n\n _updateBalanceLeft(cache, balance0, balance1);\n }\n\n if (cache.balance1Left * cache.amountIn0 > cache.balance0Left * cache.amountIn1) {\n cache.tokenIntermediate = FullMath.mulDiv(cache.balance1Left, share0, MULTIPLIER);\n balance1 = balance1 - cache.tokenIntermediate;\n\n uint256 amount = get_dy(parameters.pool, parameters.selector, parameters.j, parameters.i, cache.tokenIntermediate);\n balance0 += amount;\n\n _updateBalanceLeft(cache, balance0, balance1);\n }\n }\n } else {\n cache.tokenIntermediate = FullMath.mulDiv(parameters.totalAmountIn, share0, MULTIPLIER);\n balance1 = parameters.totalAmountIn - cache.tokenIntermediate;\n balance0 = get_dy(parameters.pool, parameters.selector, parameters.i, parameters.j, cache.tokenIntermediate);\n _updateBalanceLeft(cache, balance0, balance1);\n\n for (uint256 i = 0; i < SWAP_IMBALANCE_MAX_PASS; i++) {\n if (cache.balance0Left <= parameters.minToken0Imbalance && cache.balance1Left <= parameters.minToken1Imbalance) {\n break;\n }\n\n if (cache.balance0Left * cache.amountIn1 > cache.balance1Left * cache.amountIn0) {\n cache.tokenIntermediate = FullMath.mulDiv(cache.balance0Left, share1, MULTIPLIER);\n balance0 = balance0 - cache.tokenIntermediate;\n\n uint256 amount = get_dy(parameters.pool, parameters.selector, parameters.j, parameters.i, cache.tokenIntermediate);\n balance1 += amount;\n\n _updateBalanceLeft(cache, balance0, balance1);\n }\n\n if (cache.balance1Left * cache.amountIn0 > cache.balance0Left * cache.amountIn1) {\n cache.tokenIntermediate = FullMath.mulDiv(cache.balance1Left, share0, MULTIPLIER);\n balance1 = balance1 - cache.tokenIntermediate;\n balance0 = get_dy(\n parameters.pool,\n parameters.selector,\n parameters.i,\n parameters.j,\n parameters.totalAmountIn - balance1\n );\n _updateBalanceLeft(cache, balance0, balance1);\n }\n }\n }\n }\n\n function _updateBalanceLeft(\n Cache memory cache,\n uint256 balance0,\n uint256 balance1\n ) private pure {\n cache.liquidity = LiquidityAmounts.getLiquidityForAmounts(\n cache.sqrtRatioX,\n cache.sqrtRatioAX,\n cache.sqrtRatioBX,\n balance0,\n balance1\n );\n (cache.amountIn0, cache.amountIn1) = LiquidityAmounts.getAmountsForLiquidity(\n cache.sqrtRatioX,\n cache.sqrtRatioAX,\n cache.sqrtRatioBX,\n cache.liquidity\n );\n\n cache.balance0Left = balance0 - cache.amountIn0;\n cache.balance1Left = balance1 - cache.amountIn1;\n }\n}\n" + }, + "contracts/swappers/Leverage/popsicle/PopsicleUSTUSDTLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router01.sol\";\n\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\n\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../libraries/UniswapV3OneSidedUsingCurve.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\nimport \"../../../interfaces/curve/ICurveUSTPool.sol\";\nimport \"../../../interfaces/Tether.sol\";\n\n/// @notice UST/USDT Popsicle Leverage Swapper for Ethereum\ncontract PopsicleUSTUSDTLevSwapper {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n IPopsicle public immutable popsicle;\n\n CurvePool private constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurveUSTPool private constant UST3POOL = CurveUSTPool(0x890f4e345B1dAED0367A877a1612f86A1f86985f);\n IERC20 private constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n IERC20 private constant UST = IERC20(0xa47c8bf37f92aBed4A126BDA807A7b7498661acD);\n Tether private constant USDT = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n uint256 private constant MIN_UST_IMBALANCE = 1 ether;\n uint256 private constant MIN_USDT_IMBALANCE = 1e6;\n\n IUniswapV3Pool private immutable pool;\n\n constructor(IPopsicle _popsicle) {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n USDT.approve(address(_popsicle), type(uint256).max);\n USDT.approve(address(UST3POOL), type(uint256).max);\n UST.approve(address(_popsicle), type(uint256).max);\n pool = IUniswapV3Pool(_popsicle.pool());\n popsicle = _popsicle;\n }\n\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 mimAmount, ) = DEGENBOX.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n // MIM -> USDT on Curve MIM3POOL\n MIM3POOL.exchange_underlying(0, 3, mimAmount, 0, address(this));\n uint256 usdtAmount = USDT.balanceOf(address(this));\n\n {\n (uint160 sqrtRatioX, , , , , , ) = pool.slot0();\n\n (, uint256 balance1) = UniswapV3OneSidedUsingCurve.getAmountsToDeposit(\n UniswapV3OneSidedUsingCurve.GetAmountsToDepositParams({\n sqrtRatioX: sqrtRatioX,\n tickLower: popsicle.tickLower(),\n tickUpper: popsicle.tickUpper(),\n totalAmountIn: usdtAmount,\n i: 3,\n j: 0,\n pool: address(UST3POOL),\n selector: CurvePool.get_dy_underlying.selector,\n minToken0Imbalance: MIN_UST_IMBALANCE,\n minToken1Imbalance: MIN_USDT_IMBALANCE,\n amountInIsToken0: false\n })\n );\n\n UST3POOL.exchange_underlying(3, 0, usdtAmount - balance1, 0);\n }\n\n (uint256 shares, , ) = popsicle.deposit(UST.balanceOf(address(this)), USDT.balanceOf(address(this)), address(DEGENBOX));\n (, shareReturned) = DEGENBOX.deposit(IERC20(address(popsicle)), address(DEGENBOX), recipient, shares, 0);\n extraShare = shareReturned - shareToMin;\n }\n}\n" + }, + "contracts/interfaces/curve/ICurveUSTPool.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface CurveUSTPool {\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy\n ) external returns (uint256);\n\n function get_dy_underlying(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function get_dy(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n}\n" + }, + "contracts/swappers/Leverage/popsicle/PopsicleUSDCUSTLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router01.sol\";\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\n\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../libraries/UniswapV3OneSidedUsingCurve.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\nimport \"../../../interfaces/curve/ICurveUSTPool.sol\";\n\n/// @notice USDC/UST Popsicle Leverage Swapper for Ethereum\ncontract PopsicleUSDCUSTLevSwapper {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n IPopsicle public immutable popsicle;\n\n CurvePool private constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurveUSTPool private constant UST3POOL = CurveUSTPool(0x890f4e345B1dAED0367A877a1612f86A1f86985f);\n IERC20 private constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n IERC20 private constant UST = IERC20(0xa47c8bf37f92aBed4A126BDA807A7b7498661acD);\n IERC20 private constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n\n uint256 private constant MIN_USDC_IMBALANCE = 1e6;\n uint256 private constant MIN_UST_IMBALANCE = 1 ether;\n\n IUniswapV3Pool private immutable pool;\n\n constructor(IPopsicle _popsicle) {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n USDC.approve(address(_popsicle), type(uint256).max);\n USDC.approve(address(UST3POOL), type(uint256).max);\n UST.approve(address(_popsicle), type(uint256).max);\n pool = IUniswapV3Pool(_popsicle.pool());\n popsicle = _popsicle;\n }\n\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 mimAmount, ) = DEGENBOX.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n // MIM -> USDC on Curve MIM3POOL\n MIM3POOL.exchange_underlying(0, 2, mimAmount, 0, address(this));\n uint256 usdcAmount = USDC.balanceOf(address(this));\n\n {\n (uint160 sqrtRatioX, , , , , , ) = pool.slot0();\n\n (uint256 balance0, ) = UniswapV3OneSidedUsingCurve.getAmountsToDeposit(\n UniswapV3OneSidedUsingCurve.GetAmountsToDepositParams({\n sqrtRatioX: sqrtRatioX,\n tickLower: popsicle.tickLower(),\n tickUpper: popsicle.tickUpper(),\n totalAmountIn: usdcAmount,\n i: 2,\n j: 0,\n pool: address(UST3POOL),\n selector: CurvePool.get_dy_underlying.selector,\n minToken0Imbalance: MIN_USDC_IMBALANCE,\n minToken1Imbalance: MIN_UST_IMBALANCE,\n amountInIsToken0: true\n })\n );\n\n UST3POOL.exchange_underlying(2, 0, usdcAmount - balance0, 0);\n }\n\n (uint256 shares, , ) = popsicle.deposit(USDC.balanceOf(address(this)), UST.balanceOf(address(this)), address(DEGENBOX));\n (, shareReturned) = DEGENBOX.deposit(IERC20(address(popsicle)), address(DEGENBOX), recipient, shares, 0);\n extraShare = shareReturned - shareToMin;\n }\n}\n" + }, + "contracts/withdrawer/EthereumWithdrawer.sol": { + "content": "// SPDX-License-Identifier: MIXED\npragma solidity 0.8.10;\n\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\nimport \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\n// Edited by BoringCrypto\n\ncontract BoringOwnableData {\n address public owner;\n address public pendingOwner;\n}\n\ncontract BoringOwnable is BoringOwnableData {\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /// @notice `owner` defaults to msg.sender on construction.\n constructor() {\n owner = msg.sender;\n emit OwnershipTransferred(address(0), msg.sender);\n }\n\n /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.\n /// Can only be invoked by the current `owner`.\n /// @param newOwner Address of the new owner.\n /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\n /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\n function transferOwnership(\n address newOwner,\n bool direct,\n bool renounce\n ) public onlyOwner {\n if (direct) {\n // Checks\n require(newOwner != address(0) || renounce, \"Ownable: zero address\");\n\n // Effects\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n pendingOwner = address(0);\n } else {\n // Effects\n pendingOwner = newOwner;\n }\n }\n\n /// @notice Needs to be called by `pendingOwner` to claim ownership.\n function claimOwnership() public {\n address _pendingOwner = pendingOwner;\n\n // Checks\n require(msg.sender == _pendingOwner, \"Ownable: caller != pending owner\");\n\n // Effects\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = address(0);\n }\n\n /// @notice Only allows the `owner` to execute the function.\n modifier onlyOwner() {\n require(msg.sender == owner, \"Ownable: caller is not the owner\");\n _;\n }\n}\n\ninterface IBentoBoxV1 {\n function balanceOf(IERC20 token, address user) external view returns (uint256 share);\n\n function deposit(\n IERC20 token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n function toAmount(\n IERC20 token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n function toShare(\n IERC20 token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n function transfer(\n IERC20 token,\n address from,\n address to,\n uint256 share\n ) external;\n\n function withdraw(\n IERC20 token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n}\n\n// License-Identifier: MIT\n\ninterface Cauldron {\n function accrue() external;\n\n function withdrawFees() external;\n\n function accrueInfo()\n external\n view\n returns (\n uint64,\n uint128,\n uint64\n );\n\n function bentoBox() external returns (address);\n\n function setFeeTo(address newFeeTo) external;\n\n function feeTo() external returns (address);\n\n function masterContract() external returns (Cauldron);\n}\n\ninterface CauldronV1 {\n function accrue() external;\n\n function withdrawFees() external;\n\n function accrueInfo() external view returns (uint64, uint128);\n\n function setFeeTo(address newFeeTo) external;\n\n function feeTo() external returns (address);\n\n function masterContract() external returns (CauldronV1);\n}\n\ninterface AnyswapRouter {\n function anySwapOutUnderlying(\n address token,\n address to,\n uint256 amount,\n uint256 toChainID\n ) external;\n}\n\ninterface CurvePool {\n function exchange(\n uint256 i,\n uint256 j,\n uint256 dx,\n uint256 min_dy\n ) external;\n\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address receiver\n ) external returns (uint256);\n}\n\ncontract EthereumWithdrawer is BoringOwnable {\n using SafeERC20 for IERC20;\n\n event SwappedMimToSpell(uint256 amountSushiswap, uint256 amountUniswap, uint256 total);\n event MimWithdrawn(uint256 bentoxBoxAmount, uint256 degenBoxAmount, uint256 total);\n\n bytes4 private constant SIG_TRANSFER = 0xa9059cbb; // transfer(address,uint256)\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool public constant THREECRYPTO = CurvePool(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n IBentoBoxV1 public constant BENTOBOX = IBentoBoxV1(0xF5BCE5077908a1b7370B9ae04AdC565EBd643966);\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant USDT = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n IERC20 public constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n\n address public constant SPELL = 0x090185f2135308BaD17527004364eBcC2D37e5F6;\n address public constant sSPELL = 0x26FA3fFFB6EfE8c1E69103aCb4044C26B9A106a9;\n\n address public constant MIM_PROVIDER = 0x5f0DeE98360d8200b20812e174d139A1a633EDd2;\n address public constant TREASURY = 0x5A7C5505f3CFB9a0D9A8493EC41bf27EE48c406D;\n\n // Sushiswap\n IUniswapV2Pair private constant SUSHI_SPELL_WETH = IUniswapV2Pair(0xb5De0C3753b6E1B4dBA616Db82767F17513E6d4E);\n\n // Uniswap V3\n ISwapRouter private constant SWAPROUTER = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);\n\n CauldronV1[] public bentoBoxCauldronsV1;\n Cauldron[] public bentoBoxCauldronsV2;\n Cauldron[] public degenBoxCauldrons;\n\n uint256 public treasuryShare;\n\n mapping(address => bool) public verified;\n\n constructor(\n Cauldron[] memory bentoBoxCauldronsV2_,\n CauldronV1[] memory bentoBoxCauldronsV1_,\n Cauldron[] memory degenBoxCauldrons_\n ) {\n bentoBoxCauldronsV2 = bentoBoxCauldronsV2_;\n bentoBoxCauldronsV1 = bentoBoxCauldronsV1_;\n degenBoxCauldrons = degenBoxCauldrons_;\n\n MIM.approve(address(MIM3POOL), type(uint256).max);\n WETH.approve(address(SWAPROUTER), type(uint256).max);\n USDT.safeApprove(address(THREECRYPTO), type(uint256).max);\n verified[msg.sender] = true;\n treasuryShare = 25;\n }\n\n modifier onlyVerified() {\n require(verified[msg.sender], \"Only verified operators\");\n _;\n }\n\n function withdraw() public {\n uint256 length = bentoBoxCauldronsV2.length;\n for (uint256 i = 0; i < length; i++) {\n require(bentoBoxCauldronsV2[i].masterContract().feeTo() == address(this), \"wrong feeTo\");\n\n bentoBoxCauldronsV2[i].accrue();\n (, uint256 feesEarned, ) = bentoBoxCauldronsV2[i].accrueInfo();\n if (feesEarned > (BENTOBOX.toAmount(MIM, BENTOBOX.balanceOf(MIM, address(bentoBoxCauldronsV2[i])), false))) {\n MIM.transferFrom(MIM_PROVIDER, address(BENTOBOX), feesEarned);\n BENTOBOX.deposit(MIM, address(BENTOBOX), address(bentoBoxCauldronsV2[i]), feesEarned, 0);\n }\n\n bentoBoxCauldronsV2[i].withdrawFees();\n }\n\n length = bentoBoxCauldronsV1.length;\n for (uint256 i = 0; i < length; i++) {\n require(bentoBoxCauldronsV1[i].masterContract().feeTo() == address(this), \"wrong feeTo\");\n\n bentoBoxCauldronsV1[i].accrue();\n (, uint256 feesEarned) = bentoBoxCauldronsV1[i].accrueInfo();\n if (feesEarned > (BENTOBOX.toAmount(MIM, BENTOBOX.balanceOf(MIM, address(bentoBoxCauldronsV1[i])), false))) {\n MIM.transferFrom(MIM_PROVIDER, address(BENTOBOX), feesEarned);\n BENTOBOX.deposit(MIM, address(BENTOBOX), address(bentoBoxCauldronsV1[i]), feesEarned, 0);\n }\n bentoBoxCauldronsV1[i].withdrawFees();\n }\n\n length = degenBoxCauldrons.length;\n for (uint256 i = 0; i < length; i++) {\n require(degenBoxCauldrons[i].masterContract().feeTo() == address(this), \"wrong feeTo\");\n\n degenBoxCauldrons[i].accrue();\n (, uint256 feesEarned, ) = degenBoxCauldrons[i].accrueInfo();\n if (feesEarned > (DEGENBOX.toAmount(MIM, DEGENBOX.balanceOf(MIM, address(degenBoxCauldrons[i])), false))) {\n MIM.transferFrom(MIM_PROVIDER, address(DEGENBOX), feesEarned);\n DEGENBOX.deposit(MIM, address(DEGENBOX), address(degenBoxCauldrons[i]), feesEarned, 0);\n }\n degenBoxCauldrons[i].withdrawFees();\n }\n\n uint256 mimFromBentoBoxShare = BENTOBOX.balanceOf(MIM, address(this));\n uint256 mimFromDegenBoxShare = DEGENBOX.balanceOf(MIM, address(this));\n withdrawFromBentoBoxes(mimFromBentoBoxShare, mimFromDegenBoxShare);\n\n uint256 mimFromBentoBox = BENTOBOX.toAmount(MIM, mimFromBentoBoxShare, false);\n uint256 mimFromDegenBox = DEGENBOX.toAmount(MIM, mimFromDegenBoxShare, false);\n emit MimWithdrawn(mimFromBentoBox, mimFromDegenBox, mimFromBentoBox + mimFromDegenBox);\n }\n\n function withdrawFromBentoBoxes(uint256 amountBentoboxShare, uint256 amountDegenBoxShare) public {\n BENTOBOX.withdraw(MIM, address(this), address(this), 0, amountBentoboxShare);\n DEGENBOX.withdraw(MIM, address(this), address(this), 0, amountDegenBoxShare);\n }\n\n function rescueTokens(\n IERC20 token,\n address to,\n uint256 amount\n ) external onlyOwner {\n token.safeTransfer(to, amount);\n }\n\n function setTreasuryShare(uint256 share) external onlyOwner {\n treasuryShare = share;\n }\n\n function swapMimForSpell(\n uint256 amountSwapOnSushi,\n uint256 amountSwapOnUniswap,\n uint256 minAmountOutOnSushi,\n uint256 minAmountOutOnUniswap,\n bool autoDepositToSSpell\n ) external onlyVerified {\n require(amountSwapOnSushi > 0 || amountSwapOnUniswap > 0, \"nothing to swap\");\n\n address recipient = autoDepositToSSpell ? sSPELL : address(this);\n uint256 minAmountToSwap = _getAmountToSwap(amountSwapOnSushi + amountSwapOnUniswap);\n uint256 amountUSDT = MIM3POOL.exchange_underlying(0, 3, minAmountToSwap, 0, address(this));\n THREECRYPTO.exchange(0, 2, amountUSDT, 0);\n\n uint256 amountWETH = WETH.balanceOf(address(this));\n uint256 percentSushi = (amountSwapOnSushi * 100) / (amountSwapOnSushi + amountSwapOnUniswap);\n uint256 amountWETHSwapOnSushi = (amountWETH * percentSushi) / 100;\n uint256 amountWETHSwapOnUniswap = amountWETH - amountWETHSwapOnSushi;\n uint256 amountSpellOnSushi;\n uint256 amountSpellOnUniswap;\n\n if (amountSwapOnSushi > 0) {\n amountSpellOnSushi = _swapOnSushiswap(amountWETHSwapOnSushi, minAmountOutOnSushi, recipient);\n }\n\n if (amountSwapOnUniswap > 0) {\n amountSpellOnUniswap = _swapOnUniswap(amountWETHSwapOnUniswap, minAmountOutOnUniswap, recipient);\n }\n\n emit SwappedMimToSpell(amountSpellOnSushi, amountSpellOnUniswap, amountSpellOnSushi + amountSpellOnUniswap);\n }\n\n function swapMimForSpell1Inch(address inchrouter, bytes calldata data) external onlyOwner {\n MIM.approve(inchrouter, type(uint256).max);\n (bool success, ) = inchrouter.call(data);\n require(success, \"1inch swap unsucessful\");\n IERC20(SPELL).safeTransfer(address(sSPELL), IERC20(SPELL).balanceOf(address(this)));\n MIM.approve(inchrouter, 0);\n }\n\n function setVerified(address operator, bool status) external onlyOwner {\n verified[operator] = status;\n }\n\n function addPool(Cauldron pool) external onlyOwner {\n _addPool(pool);\n }\n\n function addPoolV1(CauldronV1 pool) external onlyOwner {\n bentoBoxCauldronsV1.push(pool);\n }\n\n function addPools(Cauldron[] memory pools) external onlyOwner {\n for (uint256 i = 0; i < pools.length; i++) {\n _addPool(pools[i]);\n }\n }\n\n function _addPool(Cauldron pool) internal onlyOwner {\n require(address(pool) != address(0), \"invalid cauldron\");\n\n if (pool.bentoBox() == address(BENTOBOX)) {\n for (uint256 i = 0; i < bentoBoxCauldronsV2.length; i++) {\n require(bentoBoxCauldronsV2[i] != pool, \"already added\");\n }\n bentoBoxCauldronsV2.push(pool);\n } else if (pool.bentoBox() == address(DEGENBOX)) {\n for (uint256 i = 0; i < degenBoxCauldrons.length; i++) {\n require(degenBoxCauldrons[i] != pool, \"already added\");\n }\n degenBoxCauldrons.push(pool);\n }\n }\n\n function _getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) private pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn * 997;\n uint256 numerator = amountInWithFee * reserveOut;\n uint256 denominator = (reserveIn * 1000) + amountInWithFee;\n amountOut = numerator / denominator;\n }\n\n function _swapOnSushiswap(\n uint256 amountWETH,\n uint256 minAmountSpellOut,\n address recipient\n ) private returns (uint256) {\n (uint256 reserve0, uint256 reserve1, ) = SUSHI_SPELL_WETH.getReserves();\n uint256 amountSpellOut = _getAmountOut(amountWETH, reserve1, reserve0);\n\n require(amountSpellOut >= minAmountSpellOut, \"Too little received\");\n\n WETH.transfer(address(SUSHI_SPELL_WETH), amountWETH);\n SUSHI_SPELL_WETH.swap(amountSpellOut, 0, recipient, \"\");\n\n return amountSpellOut;\n }\n\n function _swapOnUniswap(\n uint256 amountWETH,\n uint256 minAmountSpellOut,\n address recipient\n ) private returns (uint256) {\n ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({\n tokenIn: address(WETH),\n tokenOut: SPELL,\n fee: 3000,\n recipient: recipient,\n deadline: block.timestamp,\n amountIn: amountWETH,\n amountOutMinimum: minAmountSpellOut,\n sqrtPriceLimitX96: 0\n });\n\n uint256 amountOut = SWAPROUTER.exactInputSingle(params);\n return amountOut;\n }\n\n function _getAmountToSwap(uint256 amount) private returns (uint256) {\n uint256 treasuryShareAmount = (amount * treasuryShare) / 100;\n MIM.transfer(TREASURY, treasuryShareAmount);\n return amount - treasuryShareAmount;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\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" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\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" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\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" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)\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 * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, 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 * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\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 address owner = _msgSender();\n _approve(owner, 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 * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\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 address owner = _msgSender();\n _approve(owner, spender, _allowances[owner][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 address owner = _msgSender();\n uint256 currentAllowance = _allowances[owner][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, 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 * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, 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 Spend `amount` form the allowance of `owner` toward `spender`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\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" + }, + "contracts/oracles/PLPOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\nimport \"../interfaces/IAggregator.sol\";\nimport \"../interfaces/IOracle.sol\";\nimport \"../interfaces/IPopsicle.sol\";\n\ncontract PLPOracle is IOracle {\n IAggregator public immutable token0Aggregator;\n IAggregator public immutable token1Aggregator;\n IPopsicle public immutable plp;\n\n uint256 private immutable token0NormalizeScale;\n uint256 private immutable token1NormalizeScale;\n\n constructor(\n IPopsicle _plp,\n IAggregator _token0Aggregator,\n IAggregator _token1Aggregator\n ) {\n plp = _plp;\n token0Aggregator = _token0Aggregator;\n token1Aggregator = _token1Aggregator;\n\n uint256 token0Decimals = ERC20(_plp.token0()).decimals();\n uint256 token1Decimals = ERC20(_plp.token1()).decimals();\n\n uint256 token0AggregatorDecimals = _token0Aggregator.decimals();\n uint256 token1AggregatorDecimals = _token1Aggregator.decimals();\n\n token0NormalizeScale = (10**(36 - token0Decimals - token0AggregatorDecimals));\n token1NormalizeScale = (10**(36 - token1Decimals - token1AggregatorDecimals));\n }\n\n // Calculates the lastest exchange rate\n function _get() internal view returns (uint256) {\n (uint256 amount0, uint256 amount1) = plp.usersAmounts();\n\n uint256 token0Price = amount0 * uint256(token0Aggregator.latestAnswer()) * token0NormalizeScale;\n uint256 token1Price = amount1 * uint256(token1Aggregator.latestAnswer()) * token1NormalizeScale; \n \n uint256 plpPrice = (token0Price + token1Price) / plp.totalSupply();\n\n return 1e36 / plpPrice;\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public pure override returns (string memory) {\n return \"Chainlink Popsicle\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public pure override returns (string memory) {\n return \"LINK/PLP\";\n }\n}\n" + }, + "contracts/interfaces/IAggregator.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface IAggregator {\n function decimals() external view returns (uint8);\n\n function latestAnswer() external view returns (int256 answer);\n}\n" + }, + "contracts/interfaces/IOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface IOracle {\n /// @notice Get the latest exchange rate.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return success if no valid (recent) rate is available, return false else true.\n /// @return rate The rate of the requested asset / pair / pool.\n function get(bytes calldata data) external returns (bool success, uint256 rate);\n\n /// @notice Check the last exchange rate without any state changes.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return success if no valid (recent) rate is available, return false else true.\n /// @return rate The rate of the requested asset / pair / pool.\n function peek(bytes calldata data) external view returns (bool success, uint256 rate);\n\n /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return rate The rate of the requested asset / pair / pool.\n function peekSpot(bytes calldata data) external view returns (uint256 rate);\n\n /// @notice Returns a human readable (short) name about this oracle.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return (string) A human readable symbol name about this oracle.\n function symbol(bytes calldata data) external view returns (string memory);\n\n /// @notice Returns a human readable name about this oracle.\n /// @param data Usually abi encoded, implementation specific data that contains information and arguments to & about the oracle.\n /// For example:\n /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));\n /// @return (string) A human readable name about this oracle.\n function name(bytes calldata data) external view returns (string memory);\n}\n" + }, + "hardhat/console.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >= 0.4.22 <0.9.0;\n\nlibrary console {\n\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n\tfunction _sendLogPayload(bytes memory payload) private view {\n\t\tuint256 payloadLength = payload.length;\n\t\taddress consoleAddress = CONSOLE_ADDRESS;\n\t\tassembly {\n\t\t\tlet payloadStart := add(payload, 32)\n\t\t\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n\t\t}\n\t}\n\n\tfunction log() internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log()\"));\n\t}\n\n\tfunction logInt(int p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n\t}\n\n\tfunction logUint(uint p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n\t}\n\n\tfunction logString(string memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n\t}\n\n\tfunction logBool(bool p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n\t}\n\n\tfunction logAddress(address p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n\t}\n\n\tfunction logBytes(bytes memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n\t}\n\n\tfunction logBytes1(bytes1 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n\t}\n\n\tfunction logBytes2(bytes2 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n\t}\n\n\tfunction logBytes3(bytes3 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n\t}\n\n\tfunction logBytes4(bytes4 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n\t}\n\n\tfunction logBytes5(bytes5 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n\t}\n\n\tfunction logBytes6(bytes6 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n\t}\n\n\tfunction logBytes7(bytes7 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n\t}\n\n\tfunction logBytes8(bytes8 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n\t}\n\n\tfunction logBytes9(bytes9 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n\t}\n\n\tfunction logBytes10(bytes10 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n\t}\n\n\tfunction logBytes11(bytes11 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n\t}\n\n\tfunction logBytes12(bytes12 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n\t}\n\n\tfunction logBytes13(bytes13 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n\t}\n\n\tfunction logBytes14(bytes14 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n\t}\n\n\tfunction logBytes15(bytes15 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n\t}\n\n\tfunction logBytes16(bytes16 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n\t}\n\n\tfunction logBytes17(bytes17 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n\t}\n\n\tfunction logBytes18(bytes18 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n\t}\n\n\tfunction logBytes19(bytes19 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n\t}\n\n\tfunction logBytes20(bytes20 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n\t}\n\n\tfunction logBytes21(bytes21 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n\t}\n\n\tfunction logBytes22(bytes22 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n\t}\n\n\tfunction logBytes23(bytes23 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n\t}\n\n\tfunction logBytes24(bytes24 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n\t}\n\n\tfunction logBytes25(bytes25 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n\t}\n\n\tfunction logBytes26(bytes26 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n\t}\n\n\tfunction logBytes27(bytes27 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n\t}\n\n\tfunction logBytes28(bytes28 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n\t}\n\n\tfunction logBytes29(bytes29 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n\t}\n\n\tfunction logBytes30(bytes30 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n\t}\n\n\tfunction logBytes31(bytes31 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n\t}\n\n\tfunction logBytes32(bytes32 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n\t}\n\n\tfunction log(uint p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n\t}\n\n\tfunction log(string memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n\t}\n\n\tfunction log(bool p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n\t}\n\n\tfunction log(address p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n\t}\n\n\tfunction log(uint p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n\t}\n\n\tfunction log(address p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n\t}\n\n\tfunction log(address p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n\t}\n\n\tfunction log(address p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n\t}\n\n\tfunction log(address p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n}\n" + }, + "contracts/oracles/WbtcOracleMig.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\nimport \"../interfaces/IOracle.sol\";\n\n// Chainlink Aggregator\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address account) external view returns (uint256);\n}\n\ncontract WbtcOracleMig is IOracle {\n IAggregator public constant BTCUSD = IAggregator(0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c);\n IAggregator public constant GOLD = IAggregator(0x214eD9Da11D2fbe465a6fc601a91E62EbEc1a0D6);\n // Calculates the lastest exchange rate\n // Uses both divide and multiply only for tokens not supported directly by Chainlink, for example MKR/USD\n function _get() internal view returns (uint256) {\n uint256 btcPrice = uint256(BTCUSD.latestAnswer());\n uint256 goldPrice = uint256(GOLD.latestAnswer());\n return goldPrice * 1e8 / btcPrice;\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public pure override returns (string memory) {\n return \"Chainlink GOLD BTC\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public pure override returns (string memory) {\n return \"LINK/GOLD/BTC\";\n }\n}\n" + }, + "contracts/oracles/WbtcOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\nimport \"../interfaces/IOracle.sol\";\n\n// Chainlink Aggregator\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address account) external view returns (uint256);\n}\n\ncontract WbtcOracle is IOracle {\n IAggregator public constant BTCUSD = IAggregator(0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c);\n\n // Calculates the lastest exchange rate\n // Uses both divide and multiply only for tokens not supported directly by Chainlink, for example MKR/USD\n function _get() internal view returns (uint256) {\n return 1e16 / uint256(BTCUSD.latestAnswer());\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public pure override returns (string memory) {\n return \"Chainlink BTC\";\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public pure override returns (string memory) {\n return \"LINK/BTC\";\n }\n}\n" + }, + "contracts/oracles/StargateLPOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\nimport \"../interfaces/IOracle.sol\";\nimport \"../interfaces/stargate/IStargatePool.sol\";\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n function decimals() external view returns (uint256);\n}\n\ncontract StargateLPOracle is IOracle {\n IStargatePool public immutable pool;\n IAggregator public immutable tokenOracle;\n \n uint256 public immutable denominator;\n string private desc;\n\n constructor(\n IStargatePool _pool,\n IAggregator _tokenOracle,\n string memory _desc\n ) {\n pool = _pool;\n tokenOracle = _tokenOracle;\n desc = _desc;\n denominator = 10**(_pool.decimals() + _tokenOracle.decimals());\n }\n\n function _get() internal view returns (uint256) {\n uint256 lpPrice = (pool.totalLiquidity() * uint256(tokenOracle.latestAnswer())) / pool.totalSupply();\n\n return denominator / lpPrice;\n }\n\n /// @inheritdoc IOracle\n function get(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return desc;\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return desc;\n }\n}\n" + }, + "contracts/oracles/FtmLPOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\nimport \"../interfaces/IOracle.sol\";\n\n// Chainlink Aggregator\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ncontract FtmLPOracle is IOracle {\n IAggregator public constant FTM = IAggregator(0xf4766552D15AE4d256Ad41B6cf2933482B0680dc);\n\n /// @dev should be using an implementation of LPChainlinkOracle\n IAggregator public immutable lpOracle;\n string private desc;\n\n constructor(IAggregator _lpOracle, string memory _desc) {\n lpOracle = _lpOracle;\n desc = _desc;\n }\n\n /// @notice Returns 1 USD price in LP denominated in USD\n /// @dev lpOracle.latestAnswer() returns the price of 1 LP in FTM multipled by FTM Price.\n /// It's then inverted so it gives how many LP can 1 USD buy.\n function _get() internal view returns (uint256) {\n uint256 lpPrice = uint256(lpOracle.latestAnswer()) * uint256(FTM.latestAnswer());\n\n return 1e44 / lpPrice;\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return desc;\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return desc;\n }\n}\n" + }, + "contracts/oracles/AvaxLPOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\nimport \"../interfaces/IOracle.sol\";\n\n// Chainlink Aggregator\n\ninterface IAggregator {\n function latestAnswer() external view returns (int256 answer);\n}\n\ncontract AvaxLPOracle is IOracle {\n IAggregator public constant AVAX = IAggregator(0x0A77230d17318075983913bC2145DB16C7366156);\n\n /// @dev should be using an implementation of LPChainlinkOracle\n IAggregator public immutable lpOracle;\n string private desc;\n\n constructor(IAggregator _lpOracle, string memory _desc) {\n lpOracle = _lpOracle;\n desc = _desc;\n }\n\n /// @notice Returns 1 USD price in LP denominated in USD\n /// @dev lpOracle.latestAnswer() returns the price of 1 LP in AVAX multipled by Avax Price.\n /// It's then inverted so it gives how many LP can 1 USD buy.\n function _get() internal view returns (uint256) {\n uint256 lpPrice = uint256(lpOracle.latestAnswer()) * uint256(AVAX.latestAnswer());\n\n return 1e44 / lpPrice;\n }\n\n // Get the latest exchange rate\n /// @inheritdoc IOracle\n function get(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the last exchange rate without any state changes\n /// @inheritdoc IOracle\n function peek(bytes calldata) public view override returns (bool, uint256) {\n return (true, _get());\n }\n\n // Check the current spot exchange rate without any state changes\n /// @inheritdoc IOracle\n function peekSpot(bytes calldata data) external view override returns (uint256 rate) {\n (, rate) = peek(data);\n }\n\n /// @inheritdoc IOracle\n function name(bytes calldata) public view override returns (string memory) {\n return desc;\n }\n\n /// @inheritdoc IOracle\n function symbol(bytes calldata) public view override returns (string memory) {\n return desc;\n }\n}\n" + }, + "contracts/swappers/Leverage/popsicle/PopsicleUSDCUSDTLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router01.sol\";\n\nimport \"@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol\";\n\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../libraries/UniswapV3OneSidedUsingCurve.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\nimport \"../../../interfaces/curve/ICurveThreePool.sol\";\nimport \"../../../interfaces/Tether.sol\";\n\n/// @notice USDC/USDT Popsicle Leverage Swapper for Ethereum\ncontract PopsicleUSDCUSDTLevSwapper {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n IPopsicle public immutable popsicle;\n\n CurvePool private constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurveThreePool private constant THREEPOOL = CurveThreePool(0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7);\n IERC20 private constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n\n IERC20 private constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n Tether private constant USDT = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n uint256 private constant MIN_USDC_IMBALANCE = 1e6;\n uint256 private constant MIN_USDT_IMBALANCE = 1e6;\n\n IUniswapV3Pool private immutable pool;\n\n constructor(IPopsicle _popsicle) {\n MIM.approve(address(MIM3POOL), type(uint256).max);\n USDT.approve(address(_popsicle), type(uint256).max);\n USDT.approve(address(THREEPOOL), type(uint256).max);\n USDC.approve(address(_popsicle), type(uint256).max);\n pool = IUniswapV3Pool(_popsicle.pool());\n popsicle = _popsicle;\n }\n\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 mimAmount, ) = DEGENBOX.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n // MIM -> USDT on Curve MIM3POOL\n MIM3POOL.exchange_underlying(0, 3, mimAmount, 0, address(this));\n uint256 usdtAmount = USDT.balanceOf(address(this));\n\n {\n (uint160 sqrtRatioX, , , , , , ) = pool.slot0();\n\n (, uint256 balance1) = UniswapV3OneSidedUsingCurve.getAmountsToDeposit(\n UniswapV3OneSidedUsingCurve.GetAmountsToDepositParams({\n sqrtRatioX: sqrtRatioX,\n tickLower: popsicle.tickLower(),\n tickUpper: popsicle.tickUpper(),\n totalAmountIn: usdtAmount,\n i: 2,\n j: 1,\n pool: address(THREEPOOL),\n selector: CurvePool.get_dy_underlying.selector,\n minToken0Imbalance: MIN_USDC_IMBALANCE,\n minToken1Imbalance: MIN_USDT_IMBALANCE,\n amountInIsToken0: false\n })\n );\n\n THREEPOOL.exchange(2, 1, usdtAmount - balance1, 0);\n }\n\n (uint256 shares, , ) = popsicle.deposit(USDC.balanceOf(address(this)), USDT.balanceOf(address(this)), address(DEGENBOX));\n (, shareReturned) = DEGENBOX.deposit(IERC20(address(popsicle)), address(DEGENBOX), recipient, shares, 0);\n extraShare = shareReturned - shareToMin;\n }\n}\n" + }, + "contracts/swappers/Leverage/UsdceAvaxLevSwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Router01.sol\";\nimport \"../../libraries/Babylonian.sol\";\nimport \"../../interfaces/ILevSwapperGeneric.sol\";\nimport \"../../interfaces/IBentoBoxV1.sol\";\nimport \"../../interfaces/platypus/IPlatypusRouter01.sol\";\n\ncontract UsdceAvaxLevSwapperV2 is ILevSwapperGeneric {\n IBentoBoxV1 public immutable DEGENBOX;\n IUniswapV2Pair public constant USDCEAVAX = IUniswapV2Pair(0xA389f9430876455C36478DeEa9769B7Ca4E3DDB1);\n IUniswapV2Pair public constant MIMAVAX = IUniswapV2Pair(0x781655d802670bbA3c89aeBaaEa59D3182fD755D);\n IUniswapV2Router01 public constant ROUTER = IUniswapV2Router01(0x60aE616a2155Ee3d9A68541Ba4544862310933d4);\n IPlatypusRouter01 public constant PLATYPUS_ROUTER = IPlatypusRouter01(0x73256EC7575D999C360c1EeC118ECbEFd8DA7D12);\n\n IERC20 public constant WAVAX = IERC20(0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7);\n IERC20 public constant MIM = IERC20(0x130966628846BFd36ff31a822705796e8cb8C18D);\n IERC20 public constant USDC = IERC20(0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E);\n IERC20 public constant USDCE = IERC20(0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664);\n\n constructor(IBentoBoxV1 _DEGENBOX) {\n DEGENBOX = _DEGENBOX;\n USDCEAVAX.approve(address(_DEGENBOX), type(uint256).max);\n MIM.approve(address(PLATYPUS_ROUTER), type(uint256).max);\n WAVAX.approve(address(ROUTER), type(uint256).max);\n USDCE.approve(address(ROUTER), type(uint256).max);\n }\n\n function _calculateSwapInAmount(uint256 reserveIn, uint256 userIn) internal pure returns (uint256) {\n return (Babylonian.sqrt(reserveIn * ((userIn * 3988000) + (reserveIn * 3988009))) - (reserveIn * 1997)) / 1994;\n }\n\n function _getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn * 997;\n uint256 numerator = amountInWithFee * reserveOut;\n uint256 denominator = (reserveIn * 1000) + amountInWithFee;\n amountOut = numerator / denominator;\n }\n\n // Swaps to a flexible amount, from an exact input amount\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amount, ) = DEGENBOX.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n // MIM -> USDC.e\n {\n address[] memory tokenPath = new address[](3);\n tokenPath[0] = address(MIM);\n tokenPath[1] = address(USDC);\n tokenPath[2] = address(USDCE);\n address[] memory poolPath = new address[](2);\n poolPath[0] = address(0x30C30d826be87Cd0A4b90855C2F38f7FcfE4eaA7); // MIM -> USDC\n poolPath[1] = address(0x66357dCaCe80431aee0A7507e2E361B7e2402370); // USDC -> USDC.e\n\n (amount, ) = PLATYPUS_ROUTER.swapTokensForTokens(tokenPath, poolPath, amount, 0, address(this), type(uint256).max);\n }\n\n // 50% USDC.e -> WAVAX\n (uint256 reserve0, uint256 reserve1, ) = USDCEAVAX.getReserves();\n\n // Get USDC.e amount to swap for AVAX\n uint256 amountUsdceSwapIn = _calculateSwapInAmount(reserve0, amount);\n \n // AVAX amount out\n amount = _getAmountOut(amountUsdceSwapIn, reserve0, reserve1);\n\n USDCE.transfer(address(USDCEAVAX), amountUsdceSwapIn);\n USDCEAVAX.swap(0, amount, address(this), \"\");\n\n ROUTER.addLiquidity(\n address(USDCE),\n address(WAVAX),\n USDCE.balanceOf(address(this)),\n WAVAX.balanceOf(address(this)),\n 0,\n 0,\n address(this),\n type(uint256).max\n );\n\n (, shareReturned) = DEGENBOX.deposit(IERC20(address(USDCEAVAX)), address(this), recipient, USDCEAVAX.balanceOf(address(this)), 0);\n extraShare = shareReturned - shareToMin;\n }\n}\n" + }, + "contracts/libraries/Babylonian.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.4;\n\n/// @notice Babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method).\nlibrary Babylonian {\n // computes square roots using the babylonian method\n // credit for this implementation goes to\n // https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol#L687\n function sqrt(uint256 x) internal pure returns (uint256) {\n if (x == 0) return 0;\n // this block is equivalent to r = uint256(1) << (BitMath.mostSignificantBit(x) / 2);\n // however that code costs significantly more gas\n uint256 xx = x;\n uint256 r = 1;\n if (xx >= 0x100000000000000000000000000000000) {\n xx >>= 128;\n r <<= 64;\n }\n if (xx >= 0x10000000000000000) {\n xx >>= 64;\n r <<= 32;\n }\n if (xx >= 0x100000000) {\n xx >>= 32;\n r <<= 16;\n }\n if (xx >= 0x10000) {\n xx >>= 16;\n r <<= 8;\n }\n if (xx >= 0x100) {\n xx >>= 8;\n r <<= 4;\n }\n if (xx >= 0x10) {\n xx >>= 4;\n r <<= 2;\n }\n if (xx >= 0x8) {\n r <<= 1;\n }\n r = (r + x / r) >> 1;\n r = (r + x / r) >> 1;\n r = (r + x / r) >> 1;\n r = (r + x / r) >> 1;\n r = (r + x / r) >> 1;\n r = (r + x / r) >> 1;\n r = (r + x / r) >> 1; // Seven iterations should be enough\n uint256 r1 = x / r;\n return (r < r1 ? r : r1);\n }\n}\n" + }, + "contracts/swappers/Leverage/MagicCRVLevSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable func-name-mixedcase, var-name-mixedcase\npragma solidity ^0.8.10;\n\nimport \"../../interfaces/IBentoBoxV1.sol\";\nimport \"../../interfaces/Tether.sol\";\nimport \"../../interfaces/IERC20.sol\";\nimport \"../../interfaces/curve/ICurveThreeCryptoPool.sol\";\nimport \"../../interfaces/curve/ICurvePool.sol\";\n\ninterface IMagicCRV is IERC20 {\n function mintFor(uint256 amount, address recipient) external returns (uint256 share);\n}\n\ncontract MagicCRVLevSwapper {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool public constant CRVETH = CurvePool(0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511);\n CurveThreeCryptoPool public constant THREECRYPTO = CurveThreeCryptoPool(0xD51a44d3FaE010294C616388b506AcdA1bfAAE46);\n Tether public constant USDT = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n IERC20 public constant CRV = IERC20(0xD533a949740bb3306d119CC777fa900bA034cd52);\n\n IMagicCRV public immutable magicCRV;\n\n constructor(IMagicCRV _magicCRV) {\n magicCRV = _magicCRV;\n MIM.approve(address(MIM3POOL), type(uint256).max);\n USDT.approve(address(THREECRYPTO), type(uint256).max);\n WETH.approve(address(DEGENBOX), type(uint256).max);\n CRV.approve(address(magicCRV), type(uint256).max);\n }\n\n function swap(\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amount, ) = DEGENBOX.withdraw(MIM, address(this), address(this), 0, shareFrom);\n\n // MIM -> USDT\n amount = MIM3POOL.exchange_underlying(0, 3, amount, 0, address(this));\n\n // USDT -> WETH\n THREECRYPTO.exchange(0, 2, amount, 0);\n amount = WETH.balanceOf(address(this));\n\n // WETH -> CRV\n amount = CRVETH.exchange(0, 1, amount, 0);\n\n // CRV -> MagicCRV\n amount = magicCRV.mintFor(amount, address(DEGENBOX));\n\n (, shareReturned) = DEGENBOX.deposit(magicCRV, address(DEGENBOX), recipient, amount, 0);\n extraShare = shareReturned - shareToMin;\n }\n}\n" + }, + "contracts/mspell/mSpellSender.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\nimport \"@rari-capital/solmate/src/utils/SafeTransferLib.sol\";\nimport \"../libraries/BoringOwnable.sol\";\n// Thank you Bokky\nimport \"../libraries/BokkyPooBahsDateTimeLibrary.sol\";\n\ninterface AnyswapRouter {\n function anySwapOutUnderlying(\n address token,\n address to,\n uint256 amount,\n uint256 toChainID\n ) external;\n}\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n\ninterface IWithdrawer {\n function rescueTokens(\n ERC20 token,\n address to,\n uint256 amount\n ) external ;\n function transferOwnership(\n address newOwner,\n bool direct,\n bool renounce\n ) external;\n}\n\ninterface IMSpell {\n function updateReward() external;\n}\ncontract mSpellSender is BoringOwnable, ILayerZeroReceiver {\n using SafeTransferLib for ERC20;\n\n /// EVENTS\n event LogSetOperator(address indexed operator, bool status);\n event LogAddRecipient(address indexed recipient, uint256 chainId, uint256 chainIdLZ);\n event LogBridgeToRecipient(address indexed recipient, uint256 amount, uint256 chainId);\n event LogSpellStakedReceived(uint16 srcChainId, address indexed fromAddress, uint32 timestamp, uint128 amount);\n event LogSetReporter(uint256 chainIdLZ, address indexed reporter);\n event LogChangePurchaser(address _purchaser, address _treasury, uint _treasuryPercentage);\n\n /// CONSTANTS\n ERC20 private constant MIM = ERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n ERC20 private constant SPELL = ERC20(0x090185f2135308BaD17527004364eBcC2D37e5F6);\n address private constant SSPELL = 0x26FA3fFFB6EfE8c1E69103aCb4044C26B9A106a9;\n address private constant ANY_MIM = 0xbbc4A8d076F4B1888fec42581B6fc58d242CF2D5;\n AnyswapRouter private constant ANYSWAP_ROUTER = AnyswapRouter(0x6b7a87899490EcE95443e979cA9485CBE7E71522);\n address private constant ENDPOINT = 0x66A71Dcef29A0fFBDBE3c6a460a3B5BC225Cd675;\n\n IWithdrawer private constant withdrawer = IWithdrawer(0xB2c3A9c577068479B1E5119f6B7da98d25Ba48f4);\n address public sspellBuyBack = 0xfddfE525054efaAD204600d00CA86ADb1Cc2ea8a;\n address public treasury = 0xDF2C270f610Dc35d8fFDA5B453E74db5471E126B;\n uint public treasuryPercentage = 25;\n uint private constant PRECISION = 100;\n\n struct MSpellRecipients {\n address recipient;\n uint32 chainId;\n uint32 chainIdLZ;\n uint32 lastUpdated;\n uint128 amountStaked;\n }\n\n struct ActiveChain {\n uint8 isActive;\n uint32 position;\n }\n\n MSpellRecipients[] public recipients;\n mapping(uint256 => ActiveChain) public isActiveChain;\n mapping(uint256 => address) public mSpellReporter;\n mapping(address => bool) public isOperator;\n\n error NotNoon();\n error NotPastNoon();\n error NotUpdated(uint256);\n\n modifier onlyOperator() {\n require(isOperator[msg.sender], \"only operator\");\n _;\n }\n\n modifier onlyNoon {\n uint256 hour = block.timestamp / 1 hours % 24;\n if (hour != 12) {\n revert NotNoon();\n }\n _;\n }\n\n modifier onlyPastNoon {\n uint256 hour = block.timestamp / 1 hours % 24;\n if (hour != 13) {\n revert NotPastNoon();\n }\n _;\n }\n\n constructor() {\n MIM.approve(address(ANYSWAP_ROUTER), type(uint256).max);\n }\n\n function bridgeMim() external onlyPastNoon {\n uint256 summedRatio;\n uint256 totalAmount = MIM.balanceOf(address(withdrawer));\n uint256 amountToBeDistributed = totalAmount - totalAmount * treasuryPercentage / PRECISION;\n\n withdrawer.rescueTokens(MIM, address(this), amountToBeDistributed);\n withdrawer.rescueTokens(MIM, treasury, totalAmount * treasuryPercentage / PRECISION);\n\n uint256 currentDay = BokkyPooBahsDateTimeLibrary.getDay(block.timestamp);\n uint256 sspellAmount = SPELL.balanceOf(SSPELL);\n uint256 mspellAmount;\n uint256 length = recipients.length;\n for (uint256 i = 0; i < length; i++) {\n if(recipients[i].chainId != 1) {\n summedRatio += recipients[i].amountStaked;\n if(BokkyPooBahsDateTimeLibrary.getDay(uint256(recipients[i].lastUpdated)) != currentDay) {\n revert NotUpdated(recipients[i].chainId);\n }\n } else {\n mspellAmount = SPELL.balanceOf(recipients[i].recipient);\n summedRatio += mspellAmount + sspellAmount;\n }\n }\n\n for (uint256 i = 0; i < length; i++) {\n if (recipients[i].chainId != 1) {\n uint256 amount = (amountToBeDistributed * recipients[i].amountStaked) / summedRatio;\n if (amount > 0 ) {\n ANYSWAP_ROUTER.anySwapOutUnderlying(ANY_MIM, recipients[i].recipient, amount, recipients[i].chainId);\n emit LogBridgeToRecipient(recipients[i].recipient, amount, recipients[i].chainId);\n }\n } else {\n uint256 amountMSpell = (amountToBeDistributed * mspellAmount) / summedRatio;\n uint256 amountsSpell = (amountToBeDistributed * sspellAmount) / summedRatio;\n\n MIM.transfer(recipients[i].recipient, amountMSpell);\n IMSpell(recipients[i].recipient).updateReward();\n MIM.transfer(sspellBuyBack, amountsSpell);\n }\n }\n }\n\n function lzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64, bytes calldata _payload) external onlyNoon {\n require(msg.sender == ENDPOINT);\n uint position = isActiveChain[uint256(_srcChainId)].position;\n MSpellRecipients storage recipient = recipients[position];\n address fromAddress;\n assembly {\n fromAddress := mload(add(_srcAddress, 20))\n }\n require(fromAddress == mSpellReporter[uint256(_srcChainId)]);\n (uint32 timestamp, uint128 amount) = abi.decode(_payload, (uint32, uint128));\n recipient.amountStaked = amount;\n recipient.lastUpdated = timestamp;\n emit LogSpellStakedReceived(_srcChainId, fromAddress, timestamp, amount);\n }\n\n function addMSpellRecipient(address recipient, uint256 chainId, uint256 chainIdLZ) external onlyOwner {\n require(isActiveChain[chainIdLZ].isActive == 0, \"chainId already added\");\n uint256 position = recipients.length; \n isActiveChain[chainIdLZ] = ActiveChain(1, uint32(position));\n recipients.push(MSpellRecipients(recipient, uint32(chainId), uint32(chainIdLZ), 0, 0));\n emit LogAddRecipient(recipient, chainId, chainIdLZ);\n }\n\n function setOperator(address operator, bool status) external onlyOwner {\n isOperator[operator] = status;\n emit LogSetOperator(operator, status);\n }\n\n function addReporter(address reporter, uint256 chainIdLZ) external onlyOwner {\n mSpellReporter[chainIdLZ] = reporter;\n emit LogSetReporter(chainIdLZ, reporter);\n }\n\n function transferWithdrawer(address newOwner) external onlyOwner {\n withdrawer.transferOwnership(newOwner, true, false);\n }\n\n function changePurchaser(address _purchaser, address _treasury, uint _treasuryPercentage) external onlyOwner {\n sspellBuyBack = _purchaser;\n treasury = _treasury;\n treasuryPercentage = _treasuryPercentage;\n emit LogChangePurchaser( _purchaser, _treasury, _treasuryPercentage);\n }\n}\n" + }, + "contracts/libraries/BoringOwnable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\n// Edited by BoringCrypto\n\ncontract BoringOwnableData {\n address public owner;\n address public pendingOwner;\n}\n\ncontract BoringOwnable is BoringOwnableData {\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /// @notice `owner` defaults to msg.sender on construction.\n constructor() {\n owner = msg.sender;\n emit OwnershipTransferred(address(0), msg.sender);\n }\n\n /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.\n /// Can only be invoked by the current `owner`.\n /// @param newOwner Address of the new owner.\n /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\n /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\n function transferOwnership(\n address newOwner,\n bool direct,\n bool renounce\n ) public onlyOwner {\n if (direct) {\n // Checks\n require(newOwner != address(0) || renounce, \"Ownable: zero address\");\n\n // Effects\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n pendingOwner = address(0);\n } else {\n // Effects\n pendingOwner = newOwner;\n }\n }\n\n /// @notice Needs to be called by `pendingOwner` to claim ownership.\n function claimOwnership() public {\n address _pendingOwner = pendingOwner;\n\n // Checks\n require(msg.sender == _pendingOwner, \"Ownable: caller != pending owner\");\n\n // Effects\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = address(0);\n }\n\n /// @notice Only allows the `owner` to execute the function.\n modifier onlyOwner() {\n require(msg.sender == owner, \"Ownable: caller is not the owner\");\n _;\n }\n}" + }, + "contracts/libraries/BokkyPooBahsDateTimeLibrary.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\n// ----------------------------------------------------------------------------\n// BokkyPooBah's DateTime Library v1.01\n//\n// A gas-efficient Solidity date and time library\n//\n// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary\n//\n// Tested date range 1970/01/01 to 2345/12/31\n//\n// Conventions:\n// Unit | Range | Notes\n// :-------- |:-------------:|:-----\n// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC\n// year | 1970 ... 2345 |\n// month | 1 ... 12 |\n// day | 1 ... 31 |\n// hour | 0 ... 23 |\n// minute | 0 ... 59 |\n// second | 0 ... 59 |\n// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday\n//\n//\n// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.\n// ----------------------------------------------------------------------------\n\nlibrary BokkyPooBahsDateTimeLibrary {\n\n uint constant SECONDS_PER_DAY = 24 * 60 * 60;\n uint constant SECONDS_PER_HOUR = 60 * 60;\n uint constant SECONDS_PER_MINUTE = 60;\n int constant OFFSET19700101 = 2440588;\n\n uint constant DOW_MON = 1;\n uint constant DOW_TUE = 2;\n uint constant DOW_WED = 3;\n uint constant DOW_THU = 4;\n uint constant DOW_FRI = 5;\n uint constant DOW_SAT = 6;\n uint constant DOW_SUN = 7;\n\n // ------------------------------------------------------------------------\n // Calculate the number of days from 1970/01/01 to year/month/day using\n // the date conversion algorithm from\n // http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n // and subtracting the offset 2440588 so that 1970/01/01 is day 0\n //\n // days = day\n // - 32075\n // + 1461 * (year + 4800 + (month - 14) / 12) / 4\n // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12\n // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4\n // - offset\n // ------------------------------------------------------------------------\n function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) {\n require(year >= 1970);\n int _year = int(year);\n int _month = int(month);\n int _day = int(day);\n\n int __days = _day\n - 32075\n + 1461 * (_year + 4800 + (_month - 14) / 12) / 4\n + 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12\n - 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4\n - OFFSET19700101;\n\n _days = uint(__days);\n }\n\n // ------------------------------------------------------------------------\n // Calculate year/month/day from the number of days since 1970/01/01 using\n // the date conversion algorithm from\n // http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n // and adding the offset 2440588 so that 1970/01/01 is day 0\n //\n // int L = days + 68569 + offset\n // int N = 4 * L / 146097\n // L = L - (146097 * N + 3) / 4\n // year = 4000 * (L + 1) / 1461001\n // L = L - 1461 * year / 4 + 31\n // month = 80 * L / 2447\n // dd = L - 2447 * month / 80\n // L = month / 11\n // month = month + 2 - 12 * L\n // year = 100 * (N - 49) + year + L\n // ------------------------------------------------------------------------\n function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) {\n int __days = int(_days);\n\n int L = __days + 68569 + OFFSET19700101;\n int N = 4 * L / 146097;\n L = L - (146097 * N + 3) / 4;\n int _year = 4000 * (L + 1) / 1461001;\n L = L - 1461 * _year / 4 + 31;\n int _month = 80 * L / 2447;\n int _day = L - 2447 * _month / 80;\n L = _month / 11;\n _month = _month + 2 - 12 * L;\n _year = 100 * (N - 49) + _year + L;\n\n year = uint(_year);\n month = uint(_month);\n day = uint(_day);\n }\n\n function timestampFromDate(uint year, uint month, uint day) internal pure returns (uint timestamp) {\n timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;\n }\n function timestampFromDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (uint timestamp) {\n timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second;\n }\n function timestampToDate(uint timestamp) internal pure returns (uint year, uint month, uint day) {\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n function timestampToDateTime(uint timestamp) internal pure returns (uint year, uint month, uint day, uint hour, uint minute, uint second) {\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n uint secs = timestamp % SECONDS_PER_DAY;\n hour = secs / SECONDS_PER_HOUR;\n secs = secs % SECONDS_PER_HOUR;\n minute = secs / SECONDS_PER_MINUTE;\n second = secs % SECONDS_PER_MINUTE;\n }\n\n function isValidDate(uint year, uint month, uint day) internal pure returns (bool valid) {\n if (year >= 1970 && month > 0 && month <= 12) {\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > 0 && day <= daysInMonth) {\n valid = true;\n }\n }\n }\n function isValidDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (bool valid) {\n if (isValidDate(year, month, day)) {\n if (hour < 24 && minute < 60 && second < 60) {\n valid = true;\n }\n }\n }\n function isLeapYear(uint timestamp) internal pure returns (bool leapYear) {\n (uint year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n leapYear = _isLeapYear(year);\n }\n function _isLeapYear(uint year) internal pure returns (bool leapYear) {\n leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);\n }\n function isWeekDay(uint timestamp) internal pure returns (bool weekDay) {\n weekDay = getDayOfWeek(timestamp) <= DOW_FRI;\n }\n function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) {\n weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;\n }\n function getDaysInMonth(uint timestamp) internal pure returns (uint daysInMonth) {\n (uint year, uint month,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n daysInMonth = _getDaysInMonth(year, month);\n }\n function _getDaysInMonth(uint year, uint month) internal pure returns (uint daysInMonth) {\n if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {\n daysInMonth = 31;\n } else if (month != 2) {\n daysInMonth = 30;\n } else {\n daysInMonth = _isLeapYear(year) ? 29 : 28;\n }\n }\n // 1 = Monday, 7 = Sunday\n function getDayOfWeek(uint timestamp) internal pure returns (uint dayOfWeek) {\n uint _days = timestamp / SECONDS_PER_DAY;\n dayOfWeek = (_days + 3) % 7 + 1;\n }\n\n function getYear(uint timestamp) internal pure returns (uint year) {\n (year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n function getMonth(uint timestamp) internal pure returns (uint month) {\n (,month,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n function getDay(uint timestamp) internal pure returns (uint day) {\n (,,day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n function getHour(uint timestamp) internal pure returns (uint hour) {\n uint secs = timestamp % SECONDS_PER_DAY;\n hour = secs / SECONDS_PER_HOUR;\n }\n function getMinute(uint timestamp) internal pure returns (uint minute) {\n uint secs = timestamp % SECONDS_PER_HOUR;\n minute = secs / SECONDS_PER_MINUTE;\n }\n function getSecond(uint timestamp) internal pure returns (uint second) {\n second = timestamp % SECONDS_PER_MINUTE;\n }\n\n function addYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) {\n (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n year += _years;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;\n require(newTimestamp >= timestamp);\n }\n function addMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) {\n (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n month += _months;\n year += (month - 1) / 12;\n month = (month - 1) % 12 + 1;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;\n require(newTimestamp >= timestamp);\n }\n function addDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) {\n newTimestamp = timestamp + _days * SECONDS_PER_DAY;\n require(newTimestamp >= timestamp);\n }\n function addHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) {\n newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;\n require(newTimestamp >= timestamp);\n }\n function addMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) {\n newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;\n require(newTimestamp >= timestamp);\n }\n function addSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) {\n newTimestamp = timestamp + _seconds;\n require(newTimestamp >= timestamp);\n }\n\n function subYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) {\n (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n year -= _years;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;\n require(newTimestamp <= timestamp);\n }\n function subMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) {\n (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n uint yearMonth = year * 12 + (month - 1) - _months;\n year = yearMonth / 12;\n month = yearMonth % 12 + 1;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;\n require(newTimestamp <= timestamp);\n }\n function subDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) {\n newTimestamp = timestamp - _days * SECONDS_PER_DAY;\n require(newTimestamp <= timestamp);\n }\n function subHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) {\n newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;\n require(newTimestamp <= timestamp);\n }\n function subMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) {\n newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;\n require(newTimestamp <= timestamp);\n }\n function subSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) {\n newTimestamp = timestamp - _seconds;\n require(newTimestamp <= timestamp);\n }\n\n function diffYears(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _years) {\n require(fromTimestamp <= toTimestamp);\n (uint fromYear,,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\n (uint toYear,,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\n _years = toYear - fromYear;\n }\n function diffMonths(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _months) {\n require(fromTimestamp <= toTimestamp);\n (uint fromYear, uint fromMonth,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\n (uint toYear, uint toMonth,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\n _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;\n }\n function diffDays(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _days) {\n require(fromTimestamp <= toTimestamp);\n _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;\n }\n function diffHours(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _hours) {\n require(fromTimestamp <= toTimestamp);\n _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;\n }\n function diffMinutes(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _minutes) {\n require(fromTimestamp <= toTimestamp);\n _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;\n }\n function diffSeconds(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _seconds) {\n require(fromTimestamp <= toTimestamp);\n _seconds = toTimestamp - fromTimestamp;\n }\n}\n" + }, + "contracts/mspell/mSpellReporter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\nimport \"../libraries/BokkyPooBahsDateTimeLibrary.sol\";\nimport \"@rari-capital/solmate/src/utils/SafeTransferLib.sol\";\n\ninterface ILayerZeroEndpoint {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n}\n\ncontract mSpellReporter {\n using SafeTransferLib for ERC20;\n ILayerZeroEndpoint private immutable endpoint;\n uint16 private constant destChain = 1;\n address private constant refund = 0xfddfE525054efaAD204600d00CA86ADb1Cc2ea8a;\n ERC20 public immutable SPELL;\n address public immutable mSpell;\n address public immutable mSpellSender;\n uint256 public lastUpdated;\n\n constructor (ILayerZeroEndpoint _endpoint, ERC20 _SPELL, address _mSpell, address _mSpellSender){\n SPELL = _SPELL;\n mSpell = _mSpell;\n mSpellSender = _mSpellSender;\n endpoint = _endpoint;\n }\n\n error NotNoon();\n\n modifier onlyNoon {\n uint256 hour = block.timestamp / 1 hours % 24;\n if (hour != 12) {\n revert NotNoon();\n }\n _;\n }\n\n function withdraw() external {\n require(msg.sender == refund);\n // get the amount of Ether stored in this contract\n uint amount = address(this).balance;\n\n // send all Ether to owner\n // Owner can receive Ether since the address of owner is payable\n (bool success, ) = refund.call{value: amount}(\"\");\n require(success, \"Failed to send Ether\");\n }\n\n function sendAmount () external onlyNoon {\n require(BokkyPooBahsDateTimeLibrary.getDay(lastUpdated) < BokkyPooBahsDateTimeLibrary.getDay(block.timestamp) \n || BokkyPooBahsDateTimeLibrary.getMonth(lastUpdated) < BokkyPooBahsDateTimeLibrary.getMonth(block.timestamp) \n || BokkyPooBahsDateTimeLibrary.getYear(lastUpdated) < BokkyPooBahsDateTimeLibrary.getYear(block.timestamp)\n );\n uint256 weekDay = BokkyPooBahsDateTimeLibrary.getDayOfWeek(block.timestamp);\n require(weekDay == 1 || weekDay == 3 || weekDay == 5);\n uint128 amount = uint128(SPELL.balanceOf(mSpell));\n bytes memory payload = abi.encode(uint32(block.timestamp), amount);\n\n endpoint.send{value: address(this).balance} (\n destChain,\n abi.encodePacked(mSpellSender),\n payload,\n payable(this),\n address(0),\n bytes(\"\")\n );\n\n lastUpdated = block.timestamp;\n }\n fallback() external payable {}\n receive() external payable {}\n}" + }, + "contracts/mspell/mSpell.sol": { + "content": "// SPDX-License-Identifier: MIT\n// Inspired by Stable Joe Staking which in turn is derived from the SushiSwap MasterChef contract\n\npragma solidity 0.8.10;\nimport \"@rari-capital/solmate/src/utils/SafeTransferLib.sol\";\nimport \"../libraries/BoringOwnable.sol\";\n\n/**\n * @title Magic Spell Staking\n * @author 0xMerlin\n */\ncontract mSpellStaking is BoringOwnable {\n using SafeTransferLib for ERC20;\n\n /// @notice Info of each user\n struct UserInfo {\n uint128 amount;\n\n uint128 rewardDebt;\n uint128 lastAdded;\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 SPELL. 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 ERC20 public immutable spell;\n /// @notice Array of tokens that users can claim\n ERC20 public immutable mim;\n /// @notice Last reward balance of `token`\n uint256 public lastRewardBalance;\n\n /// @notice amount of time that the position is locked for.\n uint256 private constant LOCK_TIME = 24 hours;\n bool public toggleLockup;\n\n /// @notice Accumulated `token` rewards per share, scaled to `ACC_REWARD_PER_SHARE_PRECISION`\n uint256 public accRewardPerShare;\n /// @notice The precision of `accRewardPerShare`\n uint256 public constant ACC_REWARD_PER_SHARE_PRECISION = 1e24;\n\n /// @dev Info of each user that stakes SPELL\n mapping(address => UserInfo) public userInfo;\n\n /// @notice Emitted when a user deposits SPELL\n event Deposit(address indexed user, uint256 amount);\n\n /// @notice Emitted when a user withdraws SPELL\n event Withdraw(address indexed user, uint256 amount);\n\n /// @notice Emitted when a user claims reward\n event ClaimReward(address indexed user, uint256 amount);\n\n /// @notice Emitted when a user emergency withdraws its SPELL\n event EmergencyWithdraw(address indexed user, uint256 amount);\n\n /**\n * @notice Initialize a new mSpellStaking contract\n * @dev This contract needs to receive an ERC20 `_rewardToken` in order to distribute them\n * (with MoneyMaker in our case)\n * @param _mim The address of the MIM token\n * @param _spell The address of the SPELL token\n */\n constructor(\n ERC20 _mim,\n ERC20 _spell\n ) {\n require(address(_mim) != address(0), \"mSpellStaking: reward token can't be address(0)\");\n require(address(_spell) != address(0), \"mSpellStaking: spell can't be address(0)\");\n\n spell = _spell;\n toggleLockup = true;\n\n mim = _mim;\n }\n\n /**\n * @notice Deposit SPELL for reward token allocation\n * @param _amount The amount of SPELL to deposit\n */\n function deposit(uint256 _amount) external {\n UserInfo storage user = userInfo[msg.sender];\n\n uint256 _previousAmount = user.amount;\n uint256 _newAmount = user.amount + _amount;\n user.amount = uint128(_newAmount);\n user.lastAdded = uint128(block.timestamp);\n\n updateReward();\n\n uint256 _previousRewardDebt = user.rewardDebt;\n user.rewardDebt = uint128(_newAmount * accRewardPerShare / ACC_REWARD_PER_SHARE_PRECISION);\n\n if (_previousAmount != 0) {\n uint256 _pending = _previousAmount * accRewardPerShare / ACC_REWARD_PER_SHARE_PRECISION - _previousRewardDebt;\n if (_pending != 0) {\n safeTokenTransfer(mim, msg.sender, _pending);\n emit ClaimReward(msg.sender, _pending);\n }\n }\n\n spell.safeTransferFrom(msg.sender, address(this), _amount);\n emit Deposit(msg.sender, _amount);\n }\n\n /**\n * @notice View function to see pending reward token on frontend\n * @param _user The address of the user\n * @return `_user`'s pending reward token\n */\n function pendingReward(address _user) external view returns (uint256) {\n UserInfo storage user = userInfo[_user];\n uint256 _totalSpell = spell.balanceOf(address(this));\n uint256 _accRewardTokenPerShare = accRewardPerShare;\n\n uint256 _rewardBalance = mim.balanceOf(address(this));\n\n if (_rewardBalance != lastRewardBalance && _totalSpell != 0) {\n uint256 _accruedReward = _rewardBalance - lastRewardBalance;\n _accRewardTokenPerShare = _accRewardTokenPerShare + _accruedReward * ACC_REWARD_PER_SHARE_PRECISION / _totalSpell;\n }\n return user.amount * _accRewardTokenPerShare / ACC_REWARD_PER_SHARE_PRECISION - user.rewardDebt;\n }\n\n /**\n * @notice Withdraw SPELL and harvest the rewards\n * @param _amount The amount of SPELL to withdraw\n */\n function withdraw(uint256 _amount) external {\n UserInfo storage user = userInfo[msg.sender];\n\n require(!toggleLockup || user.lastAdded + LOCK_TIME < block.timestamp, \"mSpell: Wait for LockUp\");\n\n uint256 _previousAmount = user.amount;\n uint256 _newAmount = user.amount - _amount;\n user.amount = uint128(_newAmount);\n\n updateReward();\n\n uint256 _pending = _previousAmount * accRewardPerShare / ACC_REWARD_PER_SHARE_PRECISION - user.rewardDebt;\n user.rewardDebt = uint128(_newAmount * accRewardPerShare / ACC_REWARD_PER_SHARE_PRECISION);\n\n if (_pending != 0) {\n safeTokenTransfer(mim, msg.sender, _pending);\n emit ClaimReward(msg.sender, _pending);\n }\n\n spell.safeTransfer(msg.sender, _amount);\n emit Withdraw(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraw without caring about rewards. EMERGENCY ONLY\n */\n function emergencyWithdraw() external {\n UserInfo storage user = userInfo[msg.sender];\n\n require(!toggleLockup || user.lastAdded + LOCK_TIME < block.timestamp, \"mSpell: Wait for LockUp\");\n\n uint256 _amount = user.amount;\n\n user.amount = 0;\n user.rewardDebt = 0;\n\n spell.safeTransfer(msg.sender, _amount);\n emit EmergencyWithdraw(msg.sender, _amount);\n }\n\n /**\n * @notice Update reward variables\n * @dev Needs to be called before any deposit or withdrawal\n */\n function updateReward() public {\n uint256 _rewardBalance = mim.balanceOf(address(this));\n uint256 _totalSpell = spell.balanceOf(address(this));\n\n // Did mSpellStaking receive any token\n if (_rewardBalance == lastRewardBalance || _totalSpell == 0) {\n return;\n }\n\n uint256 _accruedReward = _rewardBalance - lastRewardBalance;\n\n accRewardPerShare = accRewardPerShare + _accruedReward * ACC_REWARD_PER_SHARE_PRECISION / _totalSpell;\n lastRewardBalance = _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 ERC20 _token,\n address _to,\n uint256 _amount\n ) internal {\n uint256 _rewardBalance = _token.balanceOf(address(this));\n\n if (_amount > _rewardBalance) {\n lastRewardBalance = lastRewardBalance - _rewardBalance;\n _token.safeTransfer(_to, _rewardBalance);\n } else {\n lastRewardBalance = lastRewardBalance - _amount;\n _token.safeTransfer(_to, _amount);\n }\n }\n\n /**\n * @notice Allows to enable and disable the lockup\n * @param status The new lockup status\n */\n\n function toggleLockUp(bool status) external onlyOwner {\n toggleLockup = status;\n }\n}\n" + }, + "contracts/magic-crv/MagicCRV.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\n// Inspired by Yearn yveCRV-DAO and xSushi\npragma solidity ^0.8.10;\n\nimport \"@rari-capital/solmate/src/tokens/ERC20.sol\";\n\ninterface ICurveVoter {\n function lock() external;\n\n function totalCRVTokens() external view returns (uint256);\n}\n\ncontract MagicCRV is ERC20 {\n ERC20 public constant CRV = ERC20(0xD533a949740bb3306d119CC777fa900bA034cd52);\n ICurveVoter public immutable curveVoter;\n\n constructor(ICurveVoter _curveVoter) ERC20(\"MagicCRV\", \"mCRV\", 18) {\n curveVoter = _curveVoter;\n }\n\n function mint(uint256 amount) external returns (uint256) {\n return _mintFor(amount, msg.sender);\n }\n\n function mintFor(uint256 amount, address recipient) external returns (uint256) {\n return _mintFor(amount, recipient);\n }\n\n function _mintFor(uint256 amount, address recipient) internal returns (uint256 share) {\n CRV.transferFrom(msg.sender, address(curveVoter), amount);\n\n share = totalSupply == 0 ? amount : (amount * totalSupply) / curveVoter.totalCRVTokens();\n\n _mint(recipient, share);\n curveVoter.lock();\n }\n\n function totalCRVTokens() external view returns (uint256) {\n return curveVoter.totalCRVTokens();\n }\n}\n" + }, + "contracts/magic-crv/CurveVoter.sol": { + "content": "// SPDX-License-Identifier: MIT\n// Inspired by Yearn CurveYCRVVoter and StrategyProxy\n// solhint-disable not-rely-on-time\npragma solidity ^0.8.10;\n\nimport \"@rari-capital/solmate/src/utils/SafeTransferLib.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/curve/IFeeDistributor.sol\";\nimport \"../interfaces/curve/IVoteEscrow.sol\";\nimport \"../interfaces/curve/IGaugeController.sol\";\nimport \"../interfaces/curve/IVoting.sol\";\n\ncontract CurveVoter is Ownable {\n using SafeTransferLib for ERC20;\n\n event LogAllowedVoterChanged(address voter, bool allowed);\n event LogMagicCRVChanged(address magicCRV);\n event LogHarvesterChangeed(address harvester);\n\n error NotAllowedVoter();\n error NotMagicCRV();\n error NotAuthorized();\n\n uint256 public constant MAX_LOCKTIME = 4 * 365 * 86400; // 4 years\n\n ERC20 public constant CRV = ERC20(0xD533a949740bb3306d119CC777fa900bA034cd52);\n address public constant ESCROW = 0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2;\n address public constant GAUGE_CONTROLLER = 0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB;\n address public constant FEE_DISTRIBUTOR = 0xA464e6DCda8AC41e03616F95f4BC98a13b8922Dc;\n address public constant CRV3 = 0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490;\n address public constant MIM_GAUGE = 0xd8b712d29381748dB89c36BCa0138d7c75866ddF;\n uint256 public constant MAX_VOTE_WEIGHT = 10_000;\n\n mapping(address => bool) public voters;\n\n uint256 public lastClaimTimestamp;\n uint256 public totalCRVTokens;\n address public magicCRV;\n address public harvester;\n\n bool public migrationEnabled;\n\n modifier onlyAllowedVoters() {\n if (!voters[msg.sender] && msg.sender != owner()) {\n revert NotAllowedVoter();\n }\n _;\n }\n\n modifier onlyHarvester() {\n if (msg.sender != harvester) {\n revert NotMagicCRV();\n }\n _;\n }\n\n modifier onlyAllowedLockers() {\n if (msg.sender != magicCRV && msg.sender != owner() && msg.sender != harvester) {\n revert NotAuthorized();\n }\n _;\n }\n\n function setAllowedVoter(address voter, bool allowed) external onlyOwner {\n voters[voter] = allowed;\n\n emit LogAllowedVoterChanged(voter, allowed);\n }\n\n function setMagicCRV(address _magicCRV) external onlyOwner {\n magicCRV = _magicCRV;\n\n emit LogMagicCRVChanged(_magicCRV);\n }\n\n function setHarvester(address _harvester) external onlyOwner {\n harvester = _harvester;\n\n emit LogHarvesterChangeed(_harvester);\n }\n\n /// @notice amount 10000 = 100%\n function voteForGaugeWeights(address gauge, uint256 amount) public onlyAllowedVoters {\n IGaugeController(GAUGE_CONTROLLER).vote_for_gauge_weights(gauge, amount);\n }\n\n function voteForMaxMIMGaugeWeights() public onlyAllowedVoters {\n IGaugeController(GAUGE_CONTROLLER).vote_for_gauge_weights(MIM_GAUGE, MAX_VOTE_WEIGHT);\n }\n\n function claim(address recipient) external onlyHarvester returns (uint256 amount) {\n if (block.timestamp < lastClaimTimestamp + 7 days) {\n return 0;\n }\n\n amount = IFeeDistributor(FEE_DISTRIBUTOR).claim(address(this));\n lastClaimTimestamp = IFeeDistributor(FEE_DISTRIBUTOR).time_cursor_of(address(this));\n\n if (amount > 0) {\n ERC20(CRV3).transfer(recipient, amount);\n }\n }\n\n function claimAll(address recipient) external onlyHarvester returns (uint256 amount) {\n if (block.timestamp < lastClaimTimestamp + 7 days) {\n return 0;\n }\n\n address p = address(this);\n\n // curve claims are divided by weeks and each iterate can claim up to 20 weeks of rewards.\n IFeeDistributor(FEE_DISTRIBUTOR).claim_many([p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p]);\n lastClaimTimestamp = IFeeDistributor(FEE_DISTRIBUTOR).time_cursor_of(p);\n\n amount = ERC20(CRV3).balanceOf(address(this));\n if (amount > 0) {\n ERC20(CRV3).transfer(recipient, amount);\n }\n }\n\n /// @notice add amount to the current lock created with `createLock` or `createMaxLock`\n function lock() external onlyAllowedLockers {\n uint256 amount = ERC20(CRV).balanceOf(address(this));\n if (amount > 0) {\n CRV.safeApprove(ESCROW, 0);\n CRV.safeApprove(ESCROW, amount);\n IVoteEscrow(ESCROW).increase_amount(amount);\n totalCRVTokens += amount;\n }\n }\n\n /// @notice creates a 4 years lock\n function createMaxLock(uint256 value) external onlyOwner {\n // solhint-disable-next-line not-rely-on-time\n _createLock(value, block.timestamp + MAX_LOCKTIME);\n }\n\n function createLock(uint256 value, uint256 unlockTime) external onlyOwner {\n _createLock(value, unlockTime);\n }\n\n /// @notice extend to 4 years lock\n function increaseMaxLock() external onlyOwner {\n // solhint-disable-next-line not-rely-on-time\n _increaseLock(block.timestamp + MAX_LOCKTIME);\n }\n\n function increaseLock(uint256 unlockTime) external onlyOwner {\n _increaseLock(unlockTime);\n }\n\n function _createLock(uint256 value, uint256 unlockTime) internal {\n CRV.transferFrom(msg.sender, address(this), value);\n CRV.safeApprove(ESCROW, 0);\n CRV.safeApprove(ESCROW, value);\n IVoteEscrow(ESCROW).create_lock(value, unlockTime);\n }\n\n function _increaseLock(uint256 unlockTime) internal {\n IVoteEscrow(ESCROW).increase_unlock_time(unlockTime);\n }\n\n function release() external onlyOwner {\n IVoteEscrow(ESCROW).withdraw();\n }\n\n function vote(\n uint256 voteId,\n address votingAddress,\n bool support\n ) external onlyOwner {\n IVoting(votingAddress).vote(voteId, support, false);\n }\n\n function withdraw(\n ERC20 token,\n address to,\n uint256 amount\n ) external onlyOwner {\n token.safeTransfer(to, amount);\n }\n\n function execute(\n address to,\n uint256 value,\n bytes calldata data\n ) external onlyOwner returns (bool, bytes memory) {\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory result) = to.call{value: value}(data);\n\n return (success, result);\n }\n}\n" + }, + "contracts/interfaces/curve/IFeeDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable func-name-mixedcase\n\npragma solidity >=0.6.12;\n\ninterface IFeeDistributor {\n function claim(address account) external returns (uint256);\n\n function claim_many(address[20] calldata) external returns (bool);\n\n function last_token_time() external view returns (uint256);\n\n function time_cursor() external view returns (uint256);\n\n function time_cursor_of(address) external view returns (uint256);\n\n function checkpoint_token() external;\n}\n" + }, + "contracts/interfaces/curve/IVoteEscrow.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable func-name-mixedcase\n\npragma solidity >=0.6.12;\n\ninterface IVoteEscrow {\n function create_lock(uint256, uint256) external;\n\n function increase_amount(uint256) external;\n\n function increase_unlock_time(uint256) external;\n\n function withdraw() external;\n}\n" + }, + "contracts/interfaces/curve/IGaugeController.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable func-name-mixedcase\n\npragma solidity >=0.6.12;\n\ninterface IGaugeController {\n function vote_for_gauge_weights(address, uint256) external;\n}" + }, + "contracts/interfaces/curve/IVoting.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ninterface IVoting {\n function vote(\n uint256 _voteData,\n bool _supports,\n bool _executesIfDecided\n ) external;\n}\n" + }, + "contracts/swappers/Liquidations/popsicle/PopsicleUSTUSDTSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../../interfaces/ISwapperGeneric.sol\";\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\nimport \"../../../interfaces/Tether.sol\";\n\n/// @notice UST/USDT Popsicle Swapper for Ethereum\ncontract PopsicleUSTUSDTSwapper is ISwapperGeneric {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool public constant UST2POOL = CurvePool(0x55A8a39bc9694714E2874c1ce77aa1E599461E18);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant UST = IERC20(0xa47c8bf37f92aBed4A126BDA807A7b7498661acD);\n Tether public constant USDT = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n IPopsicle public immutable popsicle;\n\n constructor(IPopsicle _popsicle) {\n popsicle = _popsicle;\n UST.approve(address(UST2POOL), type(uint256).max);\n USDT.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amountFrom, ) = DEGENBOX.withdraw(IERC20(address(popsicle)), address(this), address(this), 0, shareFrom);\n (uint256 ustAmount, uint256 usdtAmount) = popsicle.withdraw(amountFrom, address(this));\n\n // UST -> MIM\n uint256 mimAmount = UST2POOL.exchange(1, 0, ustAmount, 0, address(DEGENBOX));\n\n // USDT -> MIM\n mimAmount += MIM3POOL.exchange_underlying(3, 0, usdtAmount, 0, address(DEGENBOX));\n \n (, shareReturned) = DEGENBOX.deposit(MIM, address(DEGENBOX), recipient, mimAmount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure virtual returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/popsicle/PopsicleUSDCWETHSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../../interfaces/ISwapperGeneric.sol\";\nimport \"../../../interfaces/IPopsicle.sol\";\n\ninterface IBentoBoxV1 {\n function withdraw(\n IERC20 token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256, uint256);\n\n function deposit(\n IERC20 token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256, uint256);\n}\n\ninterface CurvePool {\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n address receiver\n ) external returns (uint256);\n}\n\n/// @notice USDC/WETH Popsicle Swapper for Ethereum\ncontract PopsicleUSDCWETHSwapper is ISwapperGeneric {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IUniswapV2Pair public constant USDCWETH = IUniswapV2Pair(0x397FF1542f962076d0BFE58eA045FfA2d347ACa0);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n IERC20 public constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n IPopsicle public immutable popsicle;\n\n constructor(IPopsicle _popsicle) {\n popsicle = _popsicle;\n USDC.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n function _getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n uint256 amountInWithFee = amountIn * 997;\n uint256 numerator = amountInWithFee * reserveOut;\n uint256 denominator = (reserveIn * 1000) + amountInWithFee;\n amountOut = numerator / denominator;\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amountFrom, ) = DEGENBOX.withdraw(IERC20(address(popsicle)), address(this), address(this), 0, shareFrom);\n (uint256 usdcAmount, uint256 wethAmount) = popsicle.withdraw(amountFrom, address(this));\n\n // WETH -> USDC\n (uint256 reserve0, uint256 reserve1, ) = USDCWETH.getReserves();\n uint256 usdcFromWeth = _getAmountOut(wethAmount, reserve1, reserve0);\n\n WETH.transfer(address(USDCWETH), wethAmount);\n USDCWETH.swap(usdcFromWeth, 0, address(this), \"\");\n usdcAmount += usdcFromWeth;\n\n // USDC -> MIM\n uint256 mimFromUSDC = MIM3POOL.exchange_underlying(2, 0, usdcAmount, 0, address(DEGENBOX));\n\n (, shareReturned) = DEGENBOX.deposit(MIM, address(DEGENBOX), recipient, mimFromUSDC, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public virtual pure returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/popsicle/PopsicleUSDCUSTSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../../interfaces/ISwapperGeneric.sol\";\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\n\n/// @notice USDC/UST Popsicle Swapper for Ethereum\ncontract PopsicleUSDCUSTSwapper is ISwapperGeneric {\n\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n CurvePool public constant UST2POOL = CurvePool(0x55A8a39bc9694714E2874c1ce77aa1E599461E18);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant UST = IERC20(0xa47c8bf37f92aBed4A126BDA807A7b7498661acD);\n IERC20 private constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n\n IPopsicle public immutable popsicle;\n\n constructor(IPopsicle _popsicle) {\n popsicle = _popsicle;\n UST.approve(address(UST2POOL), type(uint256).max);\n USDC.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amountFrom, ) = DEGENBOX.withdraw(IERC20(address(popsicle)), address(this), address(this), 0, shareFrom);\n (uint256 usdcAmount, uint256 ustAmount) = popsicle.withdraw(amountFrom, address(this));\n\n // UST -> MIM\n uint256 mimAmount = UST2POOL.exchange(1, 0, ustAmount, 0, address(DEGENBOX));\n\n // USDT -> MIM\n mimAmount += MIM3POOL.exchange_underlying(2, 0, usdcAmount, 0, address(DEGENBOX));\n \n (, shareReturned) = DEGENBOX.deposit(MIM, address(DEGENBOX), recipient, mimAmount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure virtual returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "contracts/swappers/Liquidations/popsicle/PopsicleUSDCUSDTSwapper.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport \"@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Pair.sol\";\nimport \"../../../interfaces/ISwapperGeneric.sol\";\nimport \"../../../interfaces/IPopsicle.sol\";\nimport \"../../../interfaces/IBentoBoxV1.sol\";\nimport \"../../../interfaces/curve/ICurvePool.sol\";\nimport \"../../../interfaces/Tether.sol\";\n\n/// @notice USDC/USDT Popsicle Swapper for Ethereum\ncontract PopsicleUSDCUSDTSwapper is ISwapperGeneric {\n IBentoBoxV1 public constant DEGENBOX = IBentoBoxV1(0xd96f48665a1410C0cd669A88898ecA36B9Fc2cce);\n CurvePool public constant MIM3POOL = CurvePool(0x5a6A4D54456819380173272A5E8E9B9904BdF41B);\n IERC20 public constant MIM = IERC20(0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3);\n IERC20 public constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n Tether public constant USDT = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n IPopsicle public immutable popsicle;\n\n constructor(IPopsicle _popsicle) {\n popsicle = _popsicle;\n USDC.approve(address(MIM3POOL), type(uint256).max);\n USDT.approve(address(MIM3POOL), type(uint256).max);\n }\n\n // Swaps to a flexible amount, from an exact input amount\n /// @inheritdoc ISwapperGeneric\n function swap(\n IERC20,\n IERC20,\n address recipient,\n uint256 shareToMin,\n uint256 shareFrom\n ) public override returns (uint256 extraShare, uint256 shareReturned) {\n (uint256 amountFrom, ) = DEGENBOX.withdraw(IERC20(address(popsicle)), address(this), address(this), 0, shareFrom);\n (uint256 usdcAmount, uint256 usdtAmount) = popsicle.withdraw(amountFrom, address(this));\n\n // USDC -> MIM\n uint256 mimAmount = MIM3POOL.exchange_underlying(2, 0, usdcAmount, 0, address(DEGENBOX));\n\n // USDT -> MIM\n mimAmount += MIM3POOL.exchange_underlying(3, 0, usdtAmount, 0, address(DEGENBOX));\n \n (, shareReturned) = DEGENBOX.deposit(MIM, address(DEGENBOX), recipient, mimAmount, 0);\n extraShare = shareReturned - shareToMin;\n }\n\n // Swaps to an exact amount, from a flexible input amount\n /// @inheritdoc ISwapperGeneric\n function swapExact(\n IERC20,\n IERC20,\n address,\n address,\n uint256,\n uint256\n ) public pure virtual returns (uint256 shareUsed, uint256 shareReturned) {\n return (0, 0);\n }\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Callee.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Callee {\n function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;\n}\n" + }, + "@sushiswap/core/contracts/uniswapv2/interfaces/IERC20.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IERC20Uniswap {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external view returns (string memory);\n function symbol() external view returns (string memory);\n function decimals() external view returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n}\n" + }, + "contracts/interfaces/ICauldron.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\nimport \"./IBentoBoxV1.sol\";\n\ninterface ICauldron {\n function userCollateralShare(address account) external view returns (uint256);\n\n function bentoBox() external view returns (IBentoBoxV1);\n\n function oracle() external view returns (address);\n\n function oracleData() external view returns (bytes memory);\n\n function collateral() external view returns (address);\n\n function updateExchangeRate() external returns (bool updated, uint256 rate);\n\n function addCollateral(\n address to,\n bool skim,\n uint256 share\n ) external;\n\n function borrow(address to, uint256 amount) external returns (uint256 part, uint256 share);\n\n function cook(\n uint8[] calldata actions,\n uint256[] calldata values,\n bytes[] calldata datas\n ) external payable returns (uint256 value1, uint256 value2);\n\n function removeCollateral(address to, uint256 share) external;\n\n function userBorrowPart(address) external view returns (uint256);\n\n function liquidate(\n address[] calldata users,\n uint256[] calldata maxBorrowParts,\n address to,\n address swapper\n ) external;\n\n function exchangeRate() external view returns (uint256);\n}\n" + }, + "contracts/mocks/YearnVaultMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\nimport \"../interfaces/yearn/IYearnVault.sol\";\n\ncontract YearnVaultMock is IYearnVault {\n function withdraw() external returns (uint256) {\n\n }\n function deposit(uint256 amount, address recipient) external returns (uint256) {\n\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 690 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file