Comparing sensitive data, confidential files or internal emails?

Most legal and privacy policies prohibit uploading sensitive data online. Diffchecker Desktop ensures your confidential information never leaves your computer. Work offline and compare documents securely.

Kashi <> Cauldron

Created Diff never expires
213 removals
681 lines
182 additions
646 lines
/**
/**
*Submitted for verification at Etherscan.io on 2021-03-27
*Submitted for verification at Etherscan.io on 2021-07-06
*/
*/


// SPDX-License-Identifier: UNLICENSED
// SPDX-License-Identifier: MIXED
// Kashi Lending Medium Risk

// __ __ __ __ _____ __ __
// | |/ .---.-.-----| |--|__| | |_.-----.-----.--| |__.-----.-----.
// | <| _ |__ --| | | | | -__| | _ | | | _ |
// |__|\__|___._|_____|__|__|__| |_______|_____|__|__|_____|__|__|__|___ |
// |_____|

// Copyright (c) 2021 BoringCrypto - All rights reserved
// Twitter: @Boring_Crypto

// Special thanks to:
// @0xKeno - for all his invaluable contributions
// @burger_crypto - for the idea of trying to let the LPs benefit from liquidations

// Version: 22-Feb-2021
Text moved to lines 622-624
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

// solhint-disable avoid-low-level-calls
// solhint-disable no-inline-assembly
// solhint-disable not-rely-on-time


// File @boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol@v1.2.0
// File @boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol@v1.2.2
// License-Identifier: MIT
// License-Identifier: MIT
pragma solidity 0.6.12;


/// @notice A library for performing overflow-/underflow-safe math,
/// @notice A library for performing overflow-/underflow-safe math,
/// updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math).
/// updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math).
library BoringMath {
library BoringMath {
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
require((c = a + b) >= b, "BoringMath: Add Overflow");
require((c = a + b) >= b, "BoringMath: Add Overflow");
}
}


function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {
function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {
require((c = a - b) <= a, "BoringMath: Underflow");
require((c = a - b) <= a, "BoringMath: Underflow");
}
}


function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
require(b == 0 || (c = a * b) / b == a, "BoringMath: Mul Overflow");
require(b == 0 || (c = a * b) / b == a, "BoringMath: Mul Overflow");
}
}


function to128(uint256 a) internal pure returns (uint128 c) {
function to128(uint256 a) internal pure returns (uint128 c) {
require(a <= uint128(-1), "BoringMath: uint128 Overflow");
require(a <= uint128(-1), "BoringMath: uint128 Overflow");
c = uint128(a);
c = uint128(a);
}
}


function to64(uint256 a) internal pure returns (uint64 c) {
function to64(uint256 a) internal pure returns (uint64 c) {
require(a <= uint64(-1), "BoringMath: uint64 Overflow");
require(a <= uint64(-1), "BoringMath: uint64 Overflow");
c = uint64(a);
c = uint64(a);
}
}


function to32(uint256 a) internal pure returns (uint32 c) {
function to32(uint256 a) internal pure returns (uint32 c) {
require(a <= uint32(-1), "BoringMath: uint32 Overflow");
require(a <= uint32(-1), "BoringMath: uint32 Overflow");
c = uint32(a);
c = uint32(a);
}
}
}
}


/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint128.
/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint128.
library BoringMath128 {
library BoringMath128 {
function add(uint128 a, uint128 b) internal pure returns (uint128 c) {
function add(uint128 a, uint128 b) internal pure returns (uint128 c) {
require((c = a + b) >= b, "BoringMath: Add Overflow");
require((c = a + b) >= b, "BoringMath: Add Overflow");
}
}


function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {
function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {
require((c = a - b) <= a, "BoringMath: Underflow");
require((c = a - b) <= a, "BoringMath: Underflow");
}
}
}
}


// File @boringcrypto/boring-solidity/contracts/BoringOwnable.sol@v1.2.0
/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint64.
library BoringMath64 {
function add(uint64 a, uint64 b) internal pure returns (uint64 c) {
require((c = a + b) >= b, "BoringMath: Add Overflow");
}

function sub(uint64 a, uint64 b) internal pure returns (uint64 c) {
require((c = a - b) <= a, "BoringMath: Underflow");
}
}

/// @notice A library for performing overflow-/underflow-safe addition and subtraction on uint32.
library BoringMath32 {
function add(uint32 a, uint32 b) internal pure returns (uint32 c) {
require((c = a + b) >= b, "BoringMath: Add Overflow");
}

function sub(uint32 a, uint32 b) internal pure returns (uint32 c) {
require((c = a - b) <= a, "BoringMath: Underflow");
}
}

// File @boringcrypto/boring-solidity/contracts/BoringOwnable.sol@v1.2.2
// License-Identifier: MIT
// License-Identifier: MIT
pragma solidity 0.6.12;


// Audit on 5-Jan-2021 by Keno and BoringCrypto
// Audit on 5-Jan-2021 by Keno and BoringCrypto
// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol
// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol
// Edited by BoringCrypto
// Edited by BoringCrypto


contract BoringOwnableData {
contract BoringOwnableData {
address public owner;
address public owner;
address public pendingOwner;
address public pendingOwner;
}
}


contract BoringOwnable is BoringOwnableData {
contract BoringOwnable is BoringOwnableData {
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);


/// @notice `owner` defaults to msg.sender on construction.
/// @notice `owner` defaults to msg.sender on construction.
constructor() public {
constructor() public {
owner = msg.sender;
owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
emit OwnershipTransferred(address(0), msg.sender);
}
}


/// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.
/// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.
/// Can only be invoked by the current `owner`.
/// Can only be invoked by the current `owner`.
/// @param newOwner Address of the new owner.
/// @param newOwner Address of the new owner.
/// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.
/// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.
/// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.
/// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.
function transferOwnership(
function transferOwnership(
address newOwner,
address newOwner,
bool direct,
bool direct,
bool renounce
bool renounce
) public onlyOwner {
) public onlyOwner {
if (direct) {
if (direct) {
// Checks
// Checks
require(newOwner != address(0) || renounce, "Ownable: zero address");
require(newOwner != address(0) || renounce, "Ownable: zero address");


// Effects
// Effects
emit OwnershipTransferred(owner, newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
owner = newOwner;
pendingOwner = address(0);
pendingOwner = address(0);
} else {
} else {
// Effects
// Effects
pendingOwner = newOwner;
pendingOwner = newOwner;
}
}
}
}


/// @notice Needs to be called by `pendingOwner` to claim ownership.
/// @notice Needs to be called by `pendingOwner` to claim ownership.
function claimOwnership() public {
function claimOwnership() public {
address _pendingOwner = pendingOwner;
address _pendingOwner = pendingOwner;


// Checks
// Checks
require(msg.sender == _pendingOwner, "Ownable: caller != pending owner");
require(msg.sender == _pendingOwner, "Ownable: caller != pending owner");


// Effects
// Effects
emit OwnershipTransferred(owner, _pendingOwner);
emit OwnershipTransferred(owner, _pendingOwner);
owner = _pendingOwner;
owner = _pendingOwner;
pendingOwner = address(0);
pendingOwner = address(0);
}
}


/// @notice Only allows the `owner` to execute the function.
/// @notice Only allows the `owner` to execute the function.
modifier onlyOwner() {
modifier onlyOwner() {
require(msg.sender == owner, "Ownable: caller is not the owner");
require(msg.sender == owner, "Ownable: caller is not the owner");
_;
_;
}
}
}
}


// File @boringcrypto/boring-solidity/contracts/Domain.sol@v1.2.0
// File @boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol@v1.2.2
// License-Identifier: MIT
Text moved with changes from lines 403-412 (96.7% similarity)
pragma solidity 0.6.12;

interface IERC20 {
function totalSupply() external view returns (uint256);

function balanceOf(address account) external view returns (uint256);

function allowance(address owner, address spender) external view returns (uint256);

function approve(address spender, uint256 amount) external returns (bool);

event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);

Text moved from lines 417-426
/// @notice EIP 2612
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}

// File @boringcrypto/boring-solidity/contracts/Domain.sol@v1.2.2
// License-Identifier: MIT
// License-Identifier: MIT
// Based on code and smartness by Ross Campbell and Keno
// Based on code and smartness by Ross Campbell and Keno
// Uses immutable to store the domain separator to reduce gas usage
// Uses immutable to store the domain separator to reduce gas usage
// If the chain id changes due to a fork, the forked chain will calculate on the fly.
// If the chain id changes due to a fork, the forked chain will calculate on the fly.
pragma solidity 0.6.12;

// solhint-disable no-inline-assembly


contract Domain {
contract Domain {
bytes32 private constant DOMAIN_SEPARATOR_SIGNATURE_HASH = keccak256("EIP712Domain(uint256 chainId,address verifyingContract)");
bytes32 private constant DOMAIN_SEPARATOR_SIGNATURE_HASH = keccak256("EIP712Domain(uint256 chainId,address verifyingContract)");
// See https://eips.ethereum.org/EIPS/eip-191
// See https://eips.ethereum.org/EIPS/eip-191
string private constant EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA = "\x19\x01";
string private constant EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA = "\x19\x01";


// solhint-disable var-name-mixedcase
// solhint-disable var-name-mixedcase
bytes32 private immutable _DOMAIN_SEPARATOR;
bytes32 private immutable _DOMAIN_SEPARATOR;
uint256 private immutable DOMAIN_SEPARATOR_CHAIN_ID;
uint256 private immutable DOMAIN_SEPARATOR_CHAIN_ID;


/// @dev Calculate the DOMAIN_SEPARATOR
/// @dev Calculate the DOMAIN_SEPARATOR
function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) {
function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) {
return keccak256(abi.encode(DOMAIN_SEPARATOR_SIGNATURE_HASH, chainId, address(this)));
return keccak256(
abi.encode(
DOMAIN_SEPARATOR_SIGNATURE_HASH,
chainId,
address(this)
)
);
}
}


constructor() public {
constructor() public {
uint256 chainId;
uint256 chainId; assembly {chainId := chainid()}
assembly {
chainId := chainid()
}
_DOMAIN_SEPARATOR = _calculateDomainSeparator(DOMAIN_SEPARATOR_CHAIN_ID = chainId);
_DOMAIN_SEPARATOR = _calculateDomainSeparator(DOMAIN_SEPARATOR_CHAIN_ID = chainId);
}
}


/// @dev Return the DOMAIN_SEPARATOR
/// @dev Return the DOMAIN_SEPARATOR
// It's named internal to allow making it public from the contract that uses it by creating a simple view function
// It's named internal to allow making it public from the contract that uses it by creating a simple view function
// with the desired public name, such as DOMAIN_SEPARATOR or domainSeparator.
// with the desired public name, such as DOMAIN_SEPARATOR or domainSeparator.
// solhint-disable-next-line func-name-mixedcase
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() public view returns (bytes32) {
function _domainSeparator() internal view returns (bytes32) {
uint256 chainId;
uint256 chainId; assembly {chainId := chainid()}
assembly {
chainId := chainid()
}
return chainId == DOMAIN_SEPARATOR_CHAIN_ID ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(chainId);
return chainId == DOMAIN_SEPARATOR_CHAIN_ID ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(chainId);
}
}


function _getDigest(bytes32 dataHash) internal view returns (bytes32 digest) {
function _getDigest(bytes32 dataHash) internal view returns (bytes32 digest) {
digest = keccak256(abi.encodePacked(EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA, DOMAIN_SEPARATOR(), dataHash));
digest =
keccak256(
abi.encodePacked(
EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA,
_domainSeparator(),
dataHash
)
);
}
}
}
}


// File @boringcrypto/boring-solidity/contracts/ERC20.sol@v1.2.0
// File @boringcrypto/boring-solidity/contracts/ERC20.sol@v1.2.2
// License-Identifier: MIT
// License-Identifier: MIT
pragma solidity 0.6.12;



// solhint-disable no-inline-assembly
// solhint-disable no-inline-assembly
// solhint-disable not-rely-on-time
// solhint-disable not-rely-on-time


// Data part taken out for building of contracts that receive delegate calls
// Data part taken out for building of contracts that receive delegate calls
contract ERC20Data {
contract ERC20Data {
/// @notice owner > balance mapping.
/// @notice owner > balance mapping.
mapping(address => uint256) public balanceOf;
mapping(address => uint256) public balanceOf;
/// @notice owner > spender > allowance mapping.
/// @notice owner > spender > allowance mapping.
mapping(address => mapping(address => uint256)) public allowance;
mapping(address => mapping(address => uint256)) public allowance;
/// @notice owner > nonce mapping. Used in `permit`.
/// @notice owner > nonce mapping. Used in `permit`.
mapping(address => uint256) public nonces;
mapping(address => uint256) public nonces;
}
}


contract ERC20 is ERC20Data, Domain {
abstract contract ERC20 is IERC20, Domain {
/// @notice owner > balance mapping.
mapping(address => uint256) public override balanceOf;
/// @notice owner > spender > allowance mapping.
mapping(address => mapping(address => uint256)) public override allowance;
/// @notice owner > nonce mapping. Used in `permit`.
mapping(address => uint256) public nonces;

event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);


/// @notice Transfers `amount` tokens from `msg.sender` to `to`.
/// @notice Transfers `amount` tokens from `msg.sender` to `to`.
/// @param to The address to move the tokens.
/// @param to The address to move the tokens.
/// @param amount of the tokens to move.
/// @param amount of the tokens to move.
/// @return (bool) Returns True if succeeded.
/// @return (bool) Returns True if succeeded.
function transfer(address to, uint256 amount) public returns (bool) {
function transfer(address to, uint256 amount) public returns (bool) {
// If `amount` is 0, or `msg.sender` is `to` nothing happens
// If `amount` is 0, or `msg.sender` is `to` nothing happens
if (amount != 0) {
if (amount != 0 || msg.sender == to) {
uint256 srcBalance = balanceOf[msg.sender];
uint256 srcBalance = balanceOf[msg.sender];
require(srcBalance >= amount, "ERC20: balance too low");
require(srcBalance >= amount, "ERC20: balance too low");
if (msg.sender != to) {
if (msg.sender != to) {
require(to != address(0), "ERC20: no zero address"); // Moved down so low balance calls safe some gas
require(to != address(0), "ERC20: no zero address"); // Moved down so low balance calls safe some gas


balanceOf[msg.sender] = srcBalance - amount; // Underflow is checked
balanceOf[msg.sender] = srcBalance - amount; // Underflow is checked
balanceOf[to] += amount; // Can't overflow because totalSupply would be greater than 2^256-1
balanceOf[to] += amount;
}
}
}
}
emit Transfer(msg.sender, to, amount);
emit Transfer(msg.sender, to, amount);
return true;
return true;
}
}


/// @notice Transfers `amount` tokens from `from` to `to`. Caller needs approval for `from`.
/// @notice Transfers `amount` tokens from `from` to `to`. Caller needs approval for `from`.
/// @param from Address to draw tokens from.
/// @param from Address to draw tokens from.
/// @param to The address to move the tokens.
/// @param to The address to move the tokens.
/// @param amount The token amount to move.
/// @param amount The token amount to move.
/// @return (bool) Returns True if succeeded.
/// @return (bool) Returns True if succeeded.
function transferFrom(
function transferFrom(
address from,
address from,
address to,
address to,
uint256 amount
uint256 amount
) public returns (bool) {
) public returns (bool) {
// If `amount` is 0, or `from` is `to` nothing happens
// If `amount` is 0, or `from` is `to` nothing happens
if (amount != 0) {
if (amount != 0) {
uint256 srcBalance = balanceOf[from];
uint256 srcBalance = balanceOf[from];
require(srcBalance >= amount, "ERC20: balance too low");
require(srcBalance >= amount, "ERC20: balance too low");


if (from != to) {
if (from != to) {
uint256 spenderAllowance = allowance[from][msg.sender];
uint256 spenderAllowance = allowance[from][msg.sender];
// If allowance is infinite, don't decrease it to save on gas (breaks with EIP-20).
// If allowance is infinite, don't decrease it to save on gas (breaks with EIP-20).
if (spenderAllowance != type(uint256).max) {
if (spenderAllowance != type(uint256).max) {
require(spenderAllowance >= amount, "ERC20: allowance too low");
require(spenderAllowance >= amount, "ERC20: allowance too low");
allowance[from][msg.sender] = spenderAllowance - amount; // Underflow is checked
allowance[from][msg.sender] = spenderAllowance - amount; // Underflow is checked
}
}
require(to != address(0), "ERC20: no zero address"); // Moved down so other failed calls safe some gas
require(to != address(0), "ERC20: no zero address"); // Moved down so other failed calls safe some gas


balanceOf[from] = srcBalance - amount; // Underflow is checked
balanceOf[from] = srcBalance - amount; // Underflow is checked
balanceOf[to] += amount; // Can't overflow because totalSupply would be greater than 2^256-1
balanceOf[to] += amount;
}
}
}
}
emit Transfer(from, to, amount);
emit Transfer(from, to, amount);
return true;
return true;
}
}


/// @notice Approves `amount` from sender to be spend by `spender`.
/// @notice Approves `amount` from sender to be spend by `spender`.
/// @param spender Address of the party that can draw from msg.sender's account.
/// @param spender Address of the party that can draw from msg.sender's account.
/// @param amount The maximum collective amount that `spender` can draw.
/// @param amount The maximum collective amount that `spender` can draw.
/// @return (bool) Returns True if approved.
/// @return (bool) Returns True if approved.
function approve(address spender, uint256 amount) public returns (bool) {
function approve(address spender, uint256 amount) public override returns (bool) {
allowance[msg.sender][spender] = amount;
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
emit Approval(msg.sender, spender, amount);
return true;
return true;
}
}


// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32) {
return _domainSeparator();
}

// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 private constant PERMIT_SIGNATURE_HASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
bytes32 private constant PERMIT_SIGNATURE_HASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;


/// @notice Approves `value` from `owner_` to be spend by `spender`.
/// @notice Approves `value` from `owner_` to be spend by `spender`.
/// @param owner_ Address of the owner.
/// @param owner_ Address of the owner.
/// @param spender The address of the spender that gets approved to draw from `owner_`.
/// @param spender The address of the spender that gets approved to draw from `owner_`.
/// @param value The maximum collective amount that `spender` can draw.
/// @param value The maximum collective amount that `spender` can draw.
/// @param deadline This permit must be redeemed before this deadline (UTC timestamp in seconds).
/// @param deadline This permit must be redeemed before this deadline (UTC timestamp in seconds).
function permit(
function permit(
address owner_,
address owner_,
address spender,
address spender,
uint256 value,
uint256 value,
uint256 deadline,
uint256 deadline,
uint8 v,
uint8 v,
bytes32 r,
bytes32 r,
bytes32 s
bytes32 s
) external {
) external override {
require(owner_ != address(0), "ERC20: Owner cannot be 0");
require(owner_ != address(0), "ERC20: Owner cannot be 0");
require(block.timestamp < deadline, "ERC20: Expired");
require(block.timestamp < deadline, "ERC20: Expired");
require(
require(
ecrecover(_getDigest(keccak256(abi.encode(PERMIT_SIGNATURE_HASH, owner_, spender, value, nonces[owner_]++, deadline))), v, r, s) ==
ecrecover(_getDigest(keccak256(abi.encode(PERMIT_SIGNATURE_HASH, owner_, spender, value, nonces[owner_]++, deadline))), v, r, s) ==
owner_,
owner_,
"ERC20: Invalid Signature"
"ERC20: Invalid Signature"
);
);
allowance[owner_][spender] = value;
allowance[owner_][spender] = value;
emit Approval(owner_, spender, value);
emit Approval(owner_, spender, value);
}
}
}
}


// File @boringcrypto/boring-solidity/contracts/interfaces/IMasterContract.sol@v1.2.0
contract ERC20WithSupply is IERC20, ERC20 {
uint256 public override totalSupply;

function _mint(address user, uint256 amount) private {
uint256 newTotalSupply = totalSupply + amount;
require(newTotalSupply >= totalSupply, "Mint overflow");
totalSupply = newTotalSupply;
balanceOf[user] += amount;
}

function _burn(address user, uint256 amount) private {
require(balanceOf[user] >= amount, "Burn too much");
totalSupply -= amount;
balanceOf[user] -= amount;
}
}

// File @boringcrypto/boring-solidity/contracts/interfaces/IMasterContract.sol@v1.2.2
// License-Identifier: MIT
// License-Identifier: MIT
pragma solidity 0.6.12;


interface IMasterContract {
interface IMasterContract {
/// @notice Init function that gets called from `BoringFactory.deploy`.
/// @notice Init function that gets called from `BoringFactory.deploy`.
/// Also kown as the constructor for cloned contracts.
/// Also kown as the constructor for cloned contracts.
/// Any ETH send to `BoringFactory.deploy` ends up here.
/// Any ETH send to `BoringFactory.deploy` ends up here.
/// @param data Can be abi encoded arguments or anything else.
/// @param data Can be abi encoded arguments or anything else.
function init(bytes calldata data) external payable;
function init(bytes calldata data) external payable;
}
}


// File @boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol@v1.2.0
// File @boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol@v1.2.2
// License-Identifier: MIT
// License-Identifier: MIT
pragma solidity 0.6.12;


struct Rebase {
struct Rebase {
uint128 elastic;
uint128 elastic;
uint128 base;
uint128 base;
}
}


/// @notice A rebasing library using overflow-/underflow-safe math.
/// @notice A rebasing library using overflow-/underflow-safe math.
library RebaseLibrary {
library RebaseLibrary {
using BoringMath for uint256;
using BoringMath for uint256;
using BoringMath128 for uint128;
using BoringMath128 for uint128;


/// @notice Calculates the base value in relationship to `elastic` and `total`.
/// @notice Calculates the base value in relationship to `elastic` and `total`.
function toBase(
function toBase(
Rebase memory total,
Rebase memory total,
uint256 elastic,
uint256 elastic,
bool roundUp
bool roundUp
) internal pure returns (uint256 base) {
) internal pure returns (uint256 base) {
if (total.elastic == 0) {
if (total.elastic == 0) {
base = elastic;
base = elastic;
} else {
} else {
base = elastic.mul(total.base) / total.elastic;
base = elastic.mul(total.base) / total.elastic;
if (roundUp && base.mul(total.elastic) / total.base < elastic) {
if (roundUp && base.mul(total.elastic) / total.base < elastic) {
base = base.add(1);
base = base.add(1);
}
}
}
}
}
}


/// @notice Calculates the elastic value in relationship to `base` and `total`.
/// @notice Calculates the elastic value in relationship to `base` and `total`.
function toElastic(
function toElastic(
Rebase memory total,
Rebase memory total,
uint256 base,
uint256 base,
bool roundUp
bool roundUp
) internal pure returns (uint256 elastic) {
) internal pure returns (uint256 elastic) {
if (total.base == 0) {
if (total.base == 0) {
elastic = base;
elastic = base;
} else {
} else {
elastic = base.mul(total.elastic) / total.base;
elastic = base.mul(total.elastic) / total.base;
if (roundUp && elastic.mul(total.base) / total.elastic < base) {
if (roundUp && elastic.mul(total.base) / total.elastic < base) {
elastic = elastic.add(1);
elastic = elastic.add(1);
}
}
}
}
}
}


/// @notice Add `elastic` to `total` and doubles `total.base`.
/// @notice Add `elastic` to `total` and doubles `total.base`.
/// @return (Rebase) The new total.
/// @return (Rebase) The new total.
/// @return base in relationship to `elastic`.
/// @return base in relationship to `elastic`.
function add(
function add(
Rebase memory total,
Rebase memory total,
uint256 elastic,
uint256 elastic,
bool roundUp
bool roundUp
) internal pure returns (Rebase memory, uint256 base) {
) internal pure returns (Rebase memory, uint256 base) {
base = toBase(total, elastic, roundUp);
base = toBase(total, elastic, roundUp);
total.elastic = total.elastic.add(elastic.to128());
total.elastic = total.elastic.add(elastic.to128());
total.base = total.base.add(base.to128());
total.base = total.base.add(base.to128());
return (total, base);
return (total, base);
}
}


/// @notice Sub `base` from `total` and update `total.elastic`.
/// @notice Sub `base` from `total` and update `total.elastic`.
/// @return (Rebase) The new total.
/// @return (Rebase) The new total.
/// @return elastic in relationship to `base`.
/// @return elastic in relationship to `base`.
function sub(
function sub(
Rebase memory total,
Rebase memory total,
uint256 base,
uint256 base,
bool roundUp
bool roundUp
) internal pure returns (Rebase memory, uint256 elastic) {
) internal pure returns (Rebase memory, uint256 elastic) {
elastic = toElastic(total, base, roundUp);
elastic = toElastic(total, base, roundUp);
total.elastic = total.elastic.sub(elastic.to128());
total.elastic = total.elastic.sub(elastic.to128());
total.base = total.base.sub(base.to128());
total.base = total.base.sub(base.to128());
return (total, elastic);
return (total, elastic);
}
}


/// @notice Add `elastic` and `base` to `total`.
/// @notice Add `elastic` and `base` to `total`.
function add(
function add(
Rebase memory total,
Rebase memory total,
uint256 elastic,
uint256 elastic,
uint256 base
uint256 base
) internal pure returns (Rebase memory) {
) internal pure returns (Rebase memory) {
total.elastic = total.elastic.add(elastic.to128());
total.elastic = total.elastic.add(elastic.to128());
total.base = total.base.add(base.to128());
total.base = total.base.add(base.to128());
return total;
return total;
}
}


/// @notice Subtract `elastic` and `base` to `total`.
/// @notice Subtract `elastic` and `base` to `total`.
function sub(
function sub(
Rebase memory total,
Rebase memory total,
uint256 elastic,
uint256 elastic,
uint256 base
uint256 base
) internal pure returns (Rebase memory) {
) internal pure returns (Rebase memory) {
total.elastic = total.elastic.sub(elastic.to128());
total.elastic = total.elastic.sub(elastic.to128());
total.base = total.base.sub(base.to128());
total.base = total.base.sub(base.to128());
return total;
return total;
}
}
}

// File @boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol@v1.2.0
Text moved with changes to lines 143-152 (96.7% similarity)
// License-Identifier: MIT

interface IERC20 {
function totalSupply() external view returns (uint256);

function balanceOf(address account) external view returns (uint256);

function allowance(address owner, address spender) external view returns (uint256);

function approve(address spender, uint256 amount) external returns (bool);


event Transfer(address indexed from, address indexed to, uint256 value);
/// @notice Add `elastic` to `total` and update storage.
event Approval(address indexed owner, address indexed spender, uint256 value);
/// @return newElastic Returns updated `elastic`.
function addElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {
newElastic = total.elastic = total.elastic.add(elastic.to128());
}


Text moved to lines 157-166
/// @notice EIP 2612
/// @notice Subtract `elastic` from `total` and update storage.
function permit(
/// @return newElastic Returns updated `elastic`.
address owner,
function subElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {
address spender,
newElastic = total.elastic = total.elastic.sub(elastic.to128());
uint256 value,
}
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
}


// File @boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol@v1.2.0
// File @boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol@v1.2.2
// License-Identifier: MIT
// License-Identifier: MIT
pragma solidity 0.6.12;

// solhint-disable avoid-low-level-calls


library BoringERC20 {
library BoringERC20 {
bytes4 private constant SIG_SYMBOL = 0x95d89b41; // symbol()
bytes4 private constant SIG_SYMBOL = 0x95d89b41; // symbol()
bytes4 private constant SIG_NAME = 0x06fdde03; // name()
bytes4 private constant SIG_NAME = 0x06fdde03; // name()
bytes4 private constant SIG_DECIMALS = 0x313ce567; // decimals()
bytes4 private constant SIG_DECIMALS = 0x313ce567; // decimals()
bytes4 private constant SIG_TRANSFER = 0xa9059cbb; // transfer(address,uint256)
bytes4 private constant SIG_TRANSFER = 0xa9059cbb; // transfer(address,uint256)
bytes4 private constant SIG_TRANSFER_FROM = 0x23b872dd; // transferFrom(address,address,uint256)
bytes4 private constant SIG_TRANSFER_FROM = 0x23b872dd; // transferFrom(address,address,uint256)


function returnDataToString(bytes memory data) internal pure returns (string memory) {
function returnDataToString(bytes memory data) internal pure returns (string memory) {
if (data.length >= 64) {
if (data.length >= 64) {
return abi.decode(data, (string));
return abi.decode(data, (string));
} else if (data.length == 32) {
} else if (data.length == 32) {
uint8 i = 0;
uint8 i = 0;
while (i < 32 && data[i] != 0) {
while(i < 32 && data[i] != 0) {
i++;
i++;
}
}
bytes memory bytesArray = new bytes(i);
bytes memory bytesArray = new bytes(i);
for (i = 0; i < 32 && data[i] != 0; i++) {
for (i = 0; i < 32 && data[i] != 0; i++) {
bytesArray[i] = data[i];
bytesArray[i] = data[i];
}
}
return string(bytesArray);
return string(bytesArray);
} else {
} else {
return "???";
return "???";
}
}
}
}


/// @notice Provides a safe ERC20.symbol version which returns '???' as fallback string.
/// @notice Provides a safe ERC20.symbol version which returns '???' as fallback string.
/// @param token The address of the ERC-20 token contract.
/// @param token The address of the ERC-20 token contract.
/// @return (string) Token symbol.
/// @return (string) Token symbol.
function safeSymbol(IERC20 token) internal view returns (string memory) {
function safeSymbol(IERC20 token) internal view returns (string memory) {
(bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_SYMBOL));
(bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_SYMBOL));
return success ? returnDataToString(data) : "???";
return success ? returnDataToString(data) : "???";
}
}


/// @notice Provides a safe ERC20.name version which returns '???' as fallback string.
/// @notice Provides a safe ERC20.name version which returns '???' as fallback string.
/// @param token The address of the ERC-20 token contract.
/// @param token The address of the ERC-20 token contract.
/// @return (string) Token name.
/// @return (string) Token name.
function safeName(IERC20 token) internal view returns (string memory) {
function safeName(IERC20 token) internal view returns (string memory) {
(bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_NAME));
(bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_NAME));
return success ? returnDataToString(data) : "???";
return success ? returnDataToString(data) : "???";
}
}


/// @notice Provides a safe ERC20.decimals version which returns '18' as fallback value.
/// @notice Provides a safe ERC20.decimals version which returns '18' as fallback value.
/// @param token The address of the ERC-20 token contract.
/// @param token The address of the ERC-20 token contract.
/// @return (uint8) Token decimals.
/// @return (uint8) Token decimals.
function safeDecimals(IERC20 token) internal view returns (uint8) {
function safeDecimals(IERC20 token) internal view returns (uint8) {
(bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_DECIMALS));
(bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(SIG_DECIMALS));
return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;
return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;
}
}

/// @notice Provides a safe ERC20.transfer version for different ERC-20 implementations.
/// Reverts on a failed transfer.
/// @param token The address of the ERC-20 token.
/// @param to Transfer tokens to.
/// @param amount The token amount.
function safeTransfer(
IERC20 token,
address to,
uint256 amount
) internal {
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(SIG_TRANSFER, to, amount));
require(success && (data.length == 0 || abi.decode(data, (bool))), "BoringERC20: Transfer failed");
}

/// @notice Provides a safe ERC20.transferFrom version for different ERC-20 implementations.
/// Reverts on a failed transfer.
/// @param token The address of the ERC-20 token.
/// @param from Transfer tokens from.
/// @param to Transfer tokens to.
/// @param amount The token amount.
Text moved with changes from lines 601-606 (91.4% similarity)
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 amount
) internal {
(bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(SIG_TRANSFER_FROM, from, to, amount));
require(success && (data.length == 0 || abi.decode(data, (bool))), "BoringERC20: TransferFrom failed");
}
}
}


// File @sushiswap/bentobox-sdk/contracts/IBatchFlashBorrower.sol@v1.0.1
// File @sushiswap/bentobox-sdk/contracts/IBatchFlashBorrower.sol@v1.0.2
// License-Identifier: MIT
// License-Identifier: MIT
pragma solidity 0.6.12;


interface IBatchFlashBorrower {
interface IBatchFlashBorrower {
function onBatchFlashLoan(
function onBatchFlashLoan(
address sender,
address sender,
IERC20[] calldata tokens,
IERC20[] calldata tokens,
uint256[] calldata amounts,
uint256[] calldata amounts,
uint256[] calldata fees,
uint256[] calldata fees,
bytes calldata data
bytes calldata data
) external;
) external;
}
}


// File @sushiswap/bentobox-sdk/contracts/IFlashBorrower.sol@v1.0.1
// File @sushiswap/bentobox-sdk/contracts/IFlashBorrower.sol@v1.0.2
// License-Identifier: MIT
// License-Identifier: MIT
pragma solidity 0.6.12;


interface IFlashBorrower {
interface IFlashBorrower {
function onFlashLoan(
function onFlashLoan(
address sender,
address sender,
IERC20 token,
IERC20 token,
uint256 amount,
uint256 amount,
uint256 fee,
uint256 fee,
bytes calldata data
bytes calldata data
) external;
) external;
}
}


// File @sushiswap/bentobox-sdk/contracts/IStrategy.sol@v1.0.1
// File @sushiswap/bentobox-sdk/contracts/IStrategy.sol@v1.0.2
// License-Identifier: MIT
// License-Identifier: MIT
pragma solidity 0.6.12;


interface IStrategy {
interface IStrategy {
// Send the assets to the Strategy and call skim to invest them
// Send the assets to the Strategy and call skim to invest them
function skim(uint256 amount) external;
function skim(uint256 amount) external;


// Harvest any profits made converted to the asset and pass them to the caller
// Harvest any profits made converted to the asset and pass them to the caller
function harvest(uint256 balance, address sender) external returns (int256 amountAdded);
function harvest(uint256 balance, address sender) external returns (int256 amountAdded);


// Withdraw assets. The returned amount can differ from the requested amount due to rounding.
// Withdraw assets. The returned amount can differ from the requested amount due to rounding.
// 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.
// 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.
function withdraw(uint256 amount) external returns (uint256 actualAmount);
function withdraw(uint256 amount) external returns (uint256 actualAmount);


// Withdraw all assets in the safest way possible. This shouldn't fail.
// Withdraw all assets in the safest way possible. This shouldn't fail.
function exit(uint256 balance) external returns (int256 amountAdded);
function exit(uint256 balance) external returns (int256 amountAdded);
}
}


// File @sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol@v1.0.1
// File @sushiswap/bentobox-sdk/contracts/IBentoBoxV1.sol@v1.0.2
// License-Identifier: MIT
// License-Identifier: MIT
Text moved from lines 22-24
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;






interface IBentoBoxV1 {
interface IBentoBoxV1 {
event LogDeploy(address indexed masterContract, bytes data, address indexed cloneAddress);
event LogDeploy(address indexed masterContract, bytes data, address indexed cloneAddress);
event LogDeposit(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);
event LogDeposit(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);
event LogFlashLoan(address indexed borrower, address indexed token, uint256 amount, uint256 feeAmount, address indexed receiver);
event LogFlashLoan(address indexed borrower, address indexed token, uint256 amount, uint256 feeAmount, address indexed receiver);
event LogRegisterProtocol(address indexed protocol);
event LogRegisterProtocol(address indexed protocol);
event LogSetMasterContractApproval(address indexed masterContract, address indexed user, bool approved);
event LogSetMasterContractApproval(address indexed masterContract, address indexed user, bool approved);
event LogStrategyDivest(address indexed token, uint256 amount);
event LogStrategyDivest(address indexed token, uint256 amount);
event LogStrategyInvest(address indexed token, uint256 amount);
event LogStrategyInvest(address indexed token, uint256 amount);
event LogStrategyLoss(address indexed token, uint256 amount);
event LogStrategyLoss(address indexed token, uint256 amount);
event LogStrategyProfit(address indexed token, uint256 amount);
event LogStrategyProfit(address indexed token, uint256 amount);
event LogStrategyQueued(address indexed token, address indexed strategy);
event LogStrategyQueued(address indexed token, address indexed strategy);
event LogStrategySet(address indexed token, address indexed strategy);
event LogStrategySet(address indexed token, address indexed strategy);
event LogStrategyTargetPercentage(address indexed token, uint256 targetPercentage);
event LogStrategyTargetPercentage(address indexed token, uint256 targetPercentage);
event LogTransfer(address indexed token, address indexed from, address indexed to, uint256 share);
event LogTransfer(address indexed token, address indexed from, address indexed to, uint256 share);
event LogWhiteListMasterContract(address indexed masterContract, bool approved);
event LogWhiteListMasterContract(address indexed masterContract, bool approved);
event LogWithdraw(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);
event LogWithdraw(address indexed token, address indexed from, address indexed to, uint256 amount, uint256 share);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

function balanceOf(IERC20, address) external view returns (uint
function balanceOf(IERC20, address) external view returns (uint256);

function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results);

function batchFlashLoan(
IBatchFlashBorrower borrower,
address[] calldata receivers,
IERC20[] calldata tokens,
uint256[] calldata amounts,
bytes calldata data
) external;

function claimOwnership() external;

function deploy(
address masterContract,
bytes calldata data,
bool useCreate2
) external payable;

function deposit(
IERC20 token_,
address from,
address to,
uint256 amount,
uint256 share
) external payable returns (uint256 amountOut, uint256 shareOut);

function flashLoan(
IFlashBorrower borrower,
address receiver,
IERC20 token,
uint256 amount,
bytes calldata data
) external;

function harvest(
IERC20 token,
bool balance,
uint256 maxChangeAmount
) external;

function masterContractApproved(address, address) external view returns (bool);

function masterContractOf(address) external view returns (address);

function nonces(address) external view returns (uint256);

function owner() external view returns (address);

function pendingOwner() external view returns (address);

function pendingStrategy(IERC20) external view returns (IStrategy);

Text moved with changes to lines 562-567 (91.4% similarity)
function permitToken(
IERC20 token,
address from,
address to,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;

function registerProtocol() external;

function setMasterContractApproval(
address user,
address masterContract,
bool approved,
uint8 v,
bytes32 r,
bytes32 s
) external;

function setStrategy(IERC20 token, IStrategy newStrategy) external;

function setStrategyTargetPercentage(IERC20 token, uint64 targetPercentage_) external;

function strategy(IERC20) external view returns (IStrategy);

function strategyData(IERC20)
external
view
returns (
uint64 strategyStartDate,
uint64 targetPercentage,
uint128 balance
);

function toAmount(
IERC20 token,
uint256 share,
bool roundUp
) external view returns (uint256 amount);

function toShare(
IERC20 token,
uint256 amount,
bool roundUp
) external view returns (uint256 share);

function totals(IERC20) external view returns (Rebase memory totals_);

function transfer(
IERC20 token,
address from,
address to,
uint256 share
) external;

function transferMultiple(
IERC20 token,
address from,
address[] calldata tos,
uint256[] calldata shares
) external;

function transferOwnership(
address newOwner,
bool direct,
bool renounce
) external;

function whitelistMasterContract(address masterContract, bool approved) external;

function whitelistedMasterContracts(address) external view returns (bool);

function withdraw(
IERC20 token_,
address from,
address to,
uint256 amount,